Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Mindisgone
May 18, 2011

Yeah, well you know...
That's just like, your opinion man.
Hopefully a simple question for the following code:

code:
<?php  //dnd.php
$r1d6 = rand(1,6);
$r1d8 = rand(1,8);
$r1d10 = rand(1,10);
echo <<<_END
<form method='post' action='dnd.php'>
Roll 1d6: <input type='submit' value='$r1d6' />
</form></br></br>
<form method='post' action='dnd.php'>
Roll 1d8: <input type='submit' value='$r1d8' />
</form></br></br>
<form method='post' action='dnd.php'>
Roll 1d10: <input type='submit' value='$r1d10' />
</form>
_END;
?>
I thought by separating each dice into its own form it would roll separately while preserving the other dice rolls. I forgot submitting the form will refresh the whole page thus re rolling the other dice at the same time. Does anyone have an easy way of preserving the other 2 dice rolls when rolling a dice? I thought about encapsulating each html form within a php if statement checking if something was posted. Thoughts???

EDIT: :horse:

Adbot
ADBOT LOVES YOU

fletcher
Jun 27, 2003

ken park is my favorite movie

Cybernetic Crumb
You would need a way of persisting the previous rolls using something like Sessions or submit the form using "AJAX" so the page doesn't refresh.

Mindisgone
May 18, 2011

Yeah, well you know...
That's just like, your opinion man.

fletcher posted:

You would need a way of persisting the previous rolls using something like Sessions or submit the form using "AJAX" so the page doesn't refresh.

I have never used AJAX before but sessions I can handle. I will give it a shot.

crabrock
Aug 2, 2002

I

AM

MAGNIFICENT






This would really work better with javascript, but if you insist on being PHP only:

code:
//dnd.php
$r1d6 = rand(1,6);
$r1d8 = rand(1,8);
$r1d10 = rand(1,10);
if ($_POST['d6']) { $r1d8=$_POST['hd8'];$r1d10=$_POST['hd10']; }
elseif ($_POST['d8']) { $r1d6=$_POST['hd6'];$r1d10=$_POST['hd10']; }
elseif ($_POST['d10']) { $r1d8=$_POST['hd8'];$r1d6=$_POST['hd6']; }
echo "<form method='post'>
<input type='hidden' name='hd6' value='".$r1d6."' />
<input type='hidden' name='hd8' value='".$r1d8."' />
<input type='hidden' name='hd10' value='".$r1d10."' />
Roll 1d6: <input type='submit' name='d6' value='".$r1d6."' />
</br></br>
Roll 1d8: <input type='submit' name='d8' value='".$r1d8."' />
</br></br>
Roll 1d10: <input type='submit' name='d10' value='".$r1d10."' />
</form>";
Things I did:
Put all the rolls in a hidden input, so they submit when the button is mashed.
generate new random numbers on page load
Only the "submit" button that is pushed gets count as sent, so I just look for the one that's pushed
update the other 2 to their old values, display.

Sulla Faex
May 14, 2010

No man ever did me so much good, or enemy so much harm, but I repaid him with ENDLESS SHITPOSTING
You would also want to sanitise that POST data.

musclecoder
Oct 23, 2006

I'm all about meeting girls. I'm all about meeting guys.
Shameless plug time!

I finished my first book named Expert PHP Deployments. In the process of writing my book on Symfony, I realized I had a smaller book contained within it on deploying any PHP application.

So, I took the 85 pages on deploying Symfony, made them generic for any PHP application, and published my first book. It's only $9.99. But, I have a special discount for goons. $2 off so only $7.99. You can probably get through the book in an afternoon, and it has a ton of details on how to use Vagrant, Capistrano, Phing, Nginx, and PHP-FPM.

Here's a direct link to get the $2 off: https://gum.co/expert-php-deployments/goons

Or simply use the coupon code goons.

Would absolutely love your feedback and advice. Thanks!

silentpenguins
May 9, 2013

Abysswalking
hey, a bit lost here:

I have a global ($existing_topics) I'm using in a function and it seems to lose it's value at $topics_list[]=key($existing_topics);

existing topics is an array with the keys being the topic id and the value being the topic name.

I took this code that was working perfectly and put it in a function and now it's not... I'm pretty sure I didn't mistakenly rename a variable or anything. I'm aware it's not great code, so if you have suggestions on how to make it better, or just fix it, I would appreciate either.

code:
function get_article_topics($categories){
        global $existing_topics;
        
        $topics_list = array();

        foreach($categories as $brafton_cat){

                $topic_exists = false;
                foreach ($existing_topics as $topic) { 
                    if($brafton_cat == $topic){
                        $topics_list[]=key($existing_topics);
                        $topic_exists = true;
                    }

                }

                if($topic_exists) continue;

                //if we get here, the category doesn't exist.  Make it.
                
                $c = create_topic($brafton_cat);
                
                //echo 'creating ' . $brafton_cat . '<br/>';
                $topics_list[] = $c->id;
            }

        return $topics_list;

    }

IT BEGINS
Jan 15, 2009

I don't know how to make analogies

silentpenguins posted:

I have a global ($existing_topics) I'm using in a function and it seems to lose it's value at $topics_list[]=key($existing_topics);

Not sure why it doesn't have a value - what value did you assign it before calling the function? Are you calling it from within another function? If you want to debug it, print out the value right as you get into the function - is it what you expect there?

My main tip - never, ever, use globals. If you want to use $existing_topics in the function, pass it in. Declaring and using that global only means your function signature is lying to you (you have more dependencies on the outside than it looks). Second tip is to try not to use a continue if you can - it means your loop has multiple places to exit from, which can make code harder to comprehend. You could instead use something like this:

php:
<?
if (!$topic_exists) {
    $c = create_topic($brafton_cat);
    $topics_list[] = $c->id;
}
?>

silentpenguins
May 9, 2013

Abysswalking

IT BEGINS posted:

Not sure why it doesn't have a value - what value did you assign it before calling the function? Are you calling it from within another function? If you want to debug it, print out the value right as you get into the function - is it what you expect there?

My main tip - never, ever, use globals. If you want to use $existing_topics in the function, pass it in. Declaring and using that global only means your function signature is lying to you (you have more dependencies on the outside than it looks). Second tip is to try not to use a continue if you can - it means your loop has multiple places to exit from, which can make code harder to comprehend. You could instead use something like this:

php:
<?
if (!$topic_exists) {
    $c = create_topic($brafton_cat);
    $topics_list[] = $c->id;
}
?>

Thanks for this, the tip on code structure is helpful. Printing out the variable is something I generally do as a debugging reference, I tried that. The variable just goes null halfway through the function and I have no idea why. However I'm thinking it has something to do with the global, so I will rewrite it as you suggested and hopefully that will fix the issue. Appreciate the help!!

Sulla Faex
May 14, 2010

No man ever did me so much good, or enemy so much harm, but I repaid him with ENDLESS SHITPOSTING
I'm on holiday and messaging from my phone at the moment but if i were you i would definitely print_r the global within that function. I suspect the issue is with the value youre expecting to get back from the key function, php functions that handles arrays sometimes expect weird formats. Try to get the value you expect in a tighter, contrived context using that (or an equivalent) function then use it in the function you have created

Fluue
Jan 2, 2008
I'm not sure if this goes into the database thread or here, so correct me if I'm wrong.

I'm designing a web dashboard for my school's clubs so the administrative office can manage them. What I want to eventually implement is a way for the admins to send out "notifications" to all the users. The notification will just be a message, maybe a link to read more.

What I'm having trouble with is wrapping my head around how to properly handle sending a notification out to EVERY user (there are about 300-400 total users at any given time) when a new message is sent by the admins. Should I be making 300-400 new rows in a notification table (holding a userid, message id, and read boolean)? Or is there a more efficient way of making this?

McGlockenshire
Dec 16, 2005

GOLLOCKS!
It depends.

If the messages will be the same for all users, and you don't need to keep track if they've read it, then you just need a place to store the messages in one central place. No need for everyone to get their own copy.

If the messages will be the same for all users, but you only need to keep track of whether they've read the latest message, then you can simply store their last-message-read time somewhere with the user record. No need for everyone to get their own copy.

If the messages will be the same for all users, but you need to keep track of whether they've read individual messages, then a simple table with the user id, message id and read timestamp should suffice. No need for everyone to get their own copy, just the read timestamp should do it.

If the messages will be customized per user, or if different users will receive different messages, then you'd want to do the whole one-row-per-message-per-user thing.

McGlockenshire fucked around with this message at 21:34 on Dec 30, 2013

Sulla Faex
May 14, 2010

No man ever did me so much good, or enemy so much harm, but I repaid him with ENDLESS SHITPOSTING
Also remember not to worry about using a database for its intended purpose. If you're really stressing and want to make sure, chuck in ten to a hundred thousand fake rows and test your normal queries, but computers are super fast nowadays and relational databases have gotten really good at doing what they do. Unless you're doing something silly like not using unique identifiers or trying to access weird data in a bizarre way, the efficiency you might gain by spending ages carefully cutting utility and ease-of-use would pale in comparison to the time wasted trying to figure it out. Just write it in a way that's easy to manage and let the database worry about how it's going to cache and traverse data. Even small businesses often deal with database tables of millions of rows and hundreds of queries simultaneously, unless you're running your website on a potato dipped in red bull then I wouldn't worry about it.

e: Your utilisation will depend on what functionality/features you want. Do you want to know whether a user has read a message, and when? Do you want to limit the messages displayed by time (for e.g. not show messages over 10 days old, etc)?

One example would be two tables:

One which tracks the content of messages and has a unique incrementing ID, messagetitle, messagebody, senderID (i.e. id of admin who sent message), timecreated, timefinish (when the message should stop being shown, if applicable).

And another that tracks which users have read what messages, with a unique incrementing id, a userid, a messageid (corresponds to the unique ID from the first table), and a timeread.

When the user loads the message box, it queries the database for all messages with a timecreated within X days and a timefinish less than the current time and that DOESNT have a corresponding row in the second table for that particular user.

Also note that the more those tables are queried in that manner, the smarter (to an extent) your RDBMS will get at searching through them and returning the right results.

Sulla Faex fucked around with this message at 23:12 on Dec 30, 2013

Cthulhuite
Mar 22, 2007

Shwmae!
I'm trying to use array_diff and it's not working, not even close. It's like it doesn't recognise the second array at all, and just outputs array1 unchanged. Any idea where i'm going wrong?

code:
	$open_positions_query = "SELECT position FROM ship_positions WHERE ship_id = '$ship_id'";
	$open_positions_result = mysqli_query($mysqli, $open_positions_query);
	while ($open_positions_array = mysqli_fetch_row($open_positions_result))
	{
   		$array2[] = array($open_positions_array);
	}

	$array1 = array("CO", "XO", "OPS", "NAV", "CTO", "TAC", "CMO", "MED", "CSO", "SCI", "CEO", "ENG", "CIV");	
	
	$arrayresult = array_diff($array1, $array2);
I've got it outputting elsewhere, and right now it just outputs array1 unchanged. If I put this in though, it outputs the correct difference.

code:
	$array2 = array("CO", "XO", "OPS", "NAV", "CTO", "TAC", "CMO", "SCI", "CEO");

McGlockenshire
Dec 16, 2005

GOLLOCKS!
Can you show us a var_dump($array1)? From your post, it's going to look nothing like array2.

IT BEGINS
Jan 15, 2009

I don't know how to make analogies

Cthulhuite posted:

I'm trying to use array_diff and it's not working, not even close. It's like it doesn't recognise the second array at all, and just outputs array1 unchanged. Any idea where i'm going wrong?

code:
	$open_positions_query = "SELECT position FROM ship_positions WHERE ship_id = '$ship_id'";
	$open_positions_result = mysqli_query($mysqli, $open_positions_query);
	while ($open_positions_array = mysqli_fetch_row($open_positions_result))
	{
   		$array2[] = array($open_positions_array);
	}

	$array1 = array("CO", "XO", "OPS", "NAV", "CTO", "TAC", "CMO", "MED", "CSO", "SCI", "CEO", "ENG", "CIV");	
	
	$arrayresult = array_diff($array1, $array2);
I've got it outputting elsewhere, and right now it just outputs array1 unchanged. If I put this in though, it outputs the correct difference.

code:
	$array2 = array("CO", "XO", "OPS", "NAV", "CTO", "TAC", "CMO", "SCI", "CEO");

At the very least, this line:

php:
<?
$array2[] = array($open_positions_array);
?>
is not doing what you are expecting. This is making every element in your array an array, with the value of $open_positions_array inside it. You are likely want to do this:

php:
<?
while ($open_positions_array = mysqli_fetch_row($open_positions_result)) {
    $array2[] = $open_positions_array;
}
?>

Cthulhuite
Mar 22, 2007

Shwmae!

IT BEGINS posted:

At the very least, this line:

php:
<?
$array2[] = array($open_positions_array);
?>
is not doing what you are expecting. This is making every element in your array an array, with the value of $open_positions_array inside it. You are likely want to do this:

php:
<?
while ($open_positions_array = mysqli_fetch_row($open_positions_result)) {
    $array2[] = $open_positions_array;
}
?>

This worked once I'd changed mysqli_fetch_row to mysqli_fetch_array.

Thanks!

McDeth
Jan 12, 2005
I'm currently watching the phpacademy YouTube guide on creating an OOP Login/Registration System and am getting stuck on video 11/23: Form Validation.

I'm getting an error when I try to call a the Validate class using the passed() method that says
code:
Fatal error: Call to undefined method Validate::_passed() in /Applications/MAMP/htdocs/classes/Validate.php on line 59
I'm a beginner at PHP, but the Validate.php file looks fine to me...halp?

Validate.php

php:
<?php

class Validate {
    private $_passed false,
            $_errors = array(),
            $_db null;

    public function __construct(){
        $this->_db DB::getInstance();
    }

    public function check($source$items = array()){
        foreach($items as $item => $rules){
            foreach($rules as $rule => $rule_value){

                $value trim($source[$item]);
                
                if($rule === 'required' && empty($value)){
                    $this->addError("{item} is Required");
                } else if(!empty($value)){
                    switch($rule){
                        case 'min':
                            if(strlen($value) < $rule_value){
                                $this->addError("{$item} must be a minimum of {$rule_value} characters.");
                            }
                        break;
                        case 'max':

                        break;
                        case 'matches':

                        break;
                        case 'unqiue':

                        break;
                    }
                }
            
            }
        }

        if(empty($this->_errors)) {
            $this->_passed true;
        }

        return $this;
    }

    private function addError($error){
        $this->_errors[]= $error;

    }

    public function errors(){
        return $this->_errors;
    }

    public function passed(){
        return $this->_passed();
    }

}

Wheany
Mar 17, 2006

Spinyahahahahahahahahahahahaha!

Doctor Rope

McDeth posted:

php:
<?php

class Validate {
    private $_passed false,
// [snip]
            $this->_passed true;
// [snip]
    public function passed(){
        return $this->_passed();
    }
}

Validate::_passed is a boolean and you're trying to call it like a function.

McDeth
Jan 12, 2005
/facepalm

Mundane details...the bane of my existence.

Thanks!

edit: I have a quick follow-up question. If a method is always going to be returning a boolean, is there any reason you couldn't just use
$class->booleanMethod to test as opposed to $class->booleanMethod()? I just tested it and it works, but just wondering if it's considering lazy coding or bad coding practices to do that?

edit2: NM, was just explained to me that $class->booleanMethod is a property access and $class->boleanMethod() is a method call, so they are two completely separate things.

McDeth fucked around with this message at 23:20 on Jan 7, 2014

karms
Jan 22, 2006

by Nyc_Tattoo
Yam Slacker
It has to do with interfaces and intent.

OOP is about hiding code behind an interface so that whatever calls upon that piece of code doesn't have to know about the nitty gritty behind the scenes. This brings with it all kinds of interesting side-problems of how to make the interface's intent clear through language constructs. Making method-versus-value discussion worthy.

In reality though, if you're not concerned with building a consistent interface it is moot. And as you can see, the guide you're following is of the latter. It also does the whole OOP == classes thing, but it's really hard to find any clear OOP explanations that don't.

If you do want to learn about proper OOP, the book practical obejct-oriented design in ruby - an agile primer was the one recommended to me. Don't worry about the ruby part, it's only used as pseudocode that also happens to be a real language.

McDeth
Jan 12, 2005

KARMA! posted:

It has to do with interfaces and intent.

OOP is about hiding code behind an interface so that whatever calls upon that piece of code doesn't have to know about the nitty gritty behind the scenes. This brings with it all kinds of interesting side-problems of how to make the interface's intent clear through language constructs. Making method-versus-value discussion worthy.

In reality though, if you're not concerned with building a consistent interface it is moot. And as you can see, the guide you're following is of the latter. It also does the whole OOP == classes thing, but it's really hard to find any clear OOP explanations that don't.

If you do want to learn about proper OOP, the book practical obejct-oriented design in ruby - an agile primer was the one recommended to me. Don't worry about the ruby part, it's only used as pseudocode that also happens to be a real language.

Thanks for the book suggestion. I'm just starting down the path of learning PHP (I have a background in relational database design) so part my difficulty is unlearning what I have learned about databases and applying it to PHP OOP. I'll check it out!

karms
Jan 22, 2006

by Nyc_Tattoo
Yam Slacker

McDeth posted:

Thanks for the book suggestion. I'm just starting down the path of learning PHP (I have a background in relational database design) so part my difficulty is unlearning what I have learned about databases and applying it to PHP OOP. I'll check it out!

Keep in the back of your mind that OOP is a solution to a set of problems you might not have experienced yet! If you are still learning to write code, it might all seem a bit esoteric. I will say however, if you get the reasonings you'll have experience with thinking about software as a complex interconnecting whole instead of a loosely combined collection of solutions. It takes years for self-taught programmers to figure out that that's a side of programming which is also important.

Don't be afraid to put this on the shelf for a while if you can't seem to get your head around it; it'll still be there tomorrow when you work on smaller things today.

Good luck!

karms fucked around with this message at 01:25 on Jan 8, 2014

Sulla Faex
May 14, 2010

No man ever did me so much good, or enemy so much harm, but I repaid him with ENDLESS SHITPOSTING
OOP and various other 'best practice' programming guidelines are a bit like filing your receipts, invoices, and tax documents as you go. You'll hate it at first, it'll seem like a lot of work for no real immediate gain, but it's really just protecting you from future nightmares once you get into deeper waters - but you don't need to, and you won't, comprehend everything immediately just from reading a book.

You can do things your own way and then the bigger and more complex your solutions get the more time you'll spend maintaining it and then you go "okay now I get it, this really sucks having to fix it, next time I'm going to code everything from the ground up to be scaleable and modular and standardised and future-proof and it's going to use the latest technology and i'm going to build a sentient robot to maintain it for me and cook me lunch so I don't need to starve while i perform private investigations on my own code to figure out what's going on every time I need to change one value".

It's the same with taxes. Imagine tax time comes and all you do is pull out twelve monthly folders, neatly labelled and sorted in the "monthly tax summary" drawer, and add a few columns together. Had an unexpected windfall? That's cool, you've already accounted for it in your "unexpected windfall" folder.

Or if that doesn't make sense, I can also use a car analogy (that's right a car analogy (it's a car analogy)). It's great to read all the OOP theory and everything before you start but it's like when your dad is trying to teach you how to drive - he's using all these weird abstract expressions that refer to feelings and sensations that you don't have yet, having never had the chance to extend your perception of 'self' to encompass a one-tonne rubber-wheeled death mobile.

At the end of the day you have to feel it, and you best learn best practices by coding a bunch of spaghetti nonsense then coming to a roadblock and saying "oh yeah I guess I should have coded it in a different way to account for this". You can almost feel your brain levelling up. Like when you plough your car through your first line of elvis joggers and decide that head-checks are probably worth doing from now on.

Sulla Faex fucked around with this message at 15:10 on Jan 8, 2014

duck monster
Dec 15, 2004

OOP is one of those things that seem a bit mysterious, even plain baffling at first until you encounter a really good example and then BLAMMO it all makes sense and nothing is ever the same. (Functional is a bit like that too) I do advocate learning a few patterns (No need to turn into a raving martin fowler prototype lunatic, unless your coding JAVA or chained to some lovely Zend 2 style monstrosity in which case welp!) particularly MVC and try and get an apreciation for *modelling* your problem. Learning UML can be useful to this even though its rarely as practical in real life stressful deadline situations than it would seem. I at least try and draw up entity relationship diagrams and work through use cases and the like.

But yeah, ultimately its great stuff and totally worth learning ,even if you just end up doing a hybrid approach like I find myself doing when under time pressure.

McDeth
Jan 12, 2005
My first exposure to PHP came when I had to dissect a project we had hired a consulting firm to code for us. When I first opened up the index.php file and saw that it was like 2,000 lines of code encapsulated by If and else if statements, my mind exploded and I automatically assumed that we had been bilked. No OOP. No MVC. Nothing. Good luck trying to troubleshoot that level of spaghetti code.

Bear in mind that this was for an extremely simple website portal that basically authenticated a user and displayed a found set of records. I shiver thinking about it.

Cthulhuite
Mar 22, 2007

Shwmae!
EDIT: Fixed it! I took out the ['position'] on the echo <option> statement, because duh of course that's a string not an array or whatever.

I'm getting a stupid "Illegal String Offset" error on a piece of code that works fine in another place. This one is getting jqueried and ajaxed though.

It's only outputting the first letter of the key value, instead of the whole string. Here's the code;

I've tried looking up this error, and it says it's outputting a string instead of an array, but I have no idea how to stop that and like I said it works fine somewhere else on the site.

code:
<?php
	
	require ('../config/db.php');
	
	$mysqli = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME);
	
	if (isset($_GET['ship_id']))
	{
		$ship_id = $_GET['ship_id'];

		$array1 = array("CO", "XO", "OPS", "NAV", "CTO", "TAC", "CMO", "MED", "CSO", "SCI", "CEO", "ENG", "AUX");		
		$open_positions_query = "SELECT position FROM ship_positions WHERE ship_id = '$ship_id'";
		$open_positions_result = mysqli_query($mysqli, $open_positions_query);
		
		while ($open_positions_array = mysqli_fetch_array($open_positions_result))
		{
			$array2[] = $open_positions_array['position'];
		}
			
		if (empty($array2))
		{
			$arrayresult = $array1;
		}
		else
		{
			$arrayresult = array_diff($array1, $array2);
		}
		
		while(list($key, $val) = each ($arrayresult))
		{
			$option .= '<option value="' . $val['position'] . '">' . $val['position'] . '</option>';
		}
	
		echo $option;
	}
It outputs the following;
code:
<b>Warning</b>:  Illegal string offset 'position' in <b>/blah/blah/blah/DropdownRetrievalScript.php</b> on line <b>31</b><br />
<option value="M">M</option><option value="C">C</option><option value="E">E</option><option value="A">A</option>

Cthulhuite fucked around with this message at 23:55 on Jan 10, 2014

fletcher
Jun 27, 2003

ken park is my favorite movie

Cybernetic Crumb
Throw in a var_dump($val) to see what $val is and why 'position' is not in there, maybe some additional var_dump's of the other variables if that doesn't help.

BTW, what happens if somebody malicious hits:

code:
http://yoursite.com/DropdownRetrievalScript.php?ship_id=1'%20or%20''%3B%20drop%20database%20ship_positions
(i used the encodeURIComponent javascript function from the Chrome Console to do that encoding there)

Spoiler: it drops your table since you used string concatenation to build that query

code:
SELECT position FROM ship_positions WHERE ship_id = '1' or ''; drop database ship_positions
You are using mysqli, which is good (PDO is more ideal), but I don't think you should progress any further until you learn about prepared statements!

Cthulhuite
Mar 22, 2007

Shwmae!

fletcher posted:

Throw in a var_dump($val) to see what $val is and why 'position' is not in there, maybe some additional var_dump's of the other variables if that doesn't help.

BTW, what happens if somebody malicious hits:

code:
http://yoursite.com/DropdownRetrievalScript.php?ship_id=1'%20or%20''%3B%20drop%20database%20ship_positions
(i used the encodeURIComponent javascript function from the Chrome Console to do that encoding there)

Spoiler: it drops your table since you used string concatenation to build that query

code:
SELECT position FROM ship_positions WHERE ship_id = '1' or ''; drop database ship_positions
You are using mysqli, which is good (PDO is more ideal), but I don't think you should progress any further until you learn about prepared statements!

I managed to get that part working okay as it was, just apparently unsecure. Yikes!

So i've done some reading on prepared statements (I always thought just real_escape_string on all of my inputs was enough, guess I was wrong!) and i've changed my code to implement prepared statements. bind_param seems to be throwing up some problems for me though in that I have my code as this;

code:
$ship_id = $_GET['ship_id'];

		$array1 = array("CO", "XO", "OPS", "NAV", "CTO", "TAC", "CMO", "MED", "CSO", "SCI", "CEO", "ENG", "AUX");		
		$open_positions_query = "SELECT position FROM ship_positions WHERE ship_id = ?";
		$stmt = $mysqli->prepare($open_positions_query);
		$stmt->bind_param('s',$ship_id);
		$stmt->execute();
		
		while ($open_positions_array = $stmt->fetch())
		{
			$array2[] = $open_positions_array['position'];
		}
For some reason it's not pulling anything from the query, it's blank, and therefore the original array_diff doesn't have anything to compare against and just feeds me back $array1 into my dropdown.

I'm sure that i'm just not using bind_param correctly.

Edit: I have a feeling i'm mixing up PDO and mysqli. Ugh, do I need to learn PDO? :(

Cthulhuite fucked around with this message at 01:36 on Jan 11, 2014

substitute
Aug 30, 2003

you for my mum
Check this out.
http://wiki.hashphp.org/PDO_Tutorial_for_MySQL_Developers

php:
<?

$dbh = new PDO('mysql:host=localhost;dbname=testdb;charset=utf8', 'username', 'password');
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

$query = "SELECT * FROM table WHERE id=:id AND name=:name"
$bind = array(
    'id' => $id
    ,'name' => $name
);

$stmt = $dbh->prepare($query);

$stmt->execute($bind);

$result = $stmt->fetchAll(PDO::FETCH_ASSOC);

foreach($result as $row) {
    echo $row['some_column'] ."<br>\n";
}

// OR to test your result

print_r($result);
?>

substitute fucked around with this message at 01:52 on Jan 11, 2014

Cthulhuite
Mar 22, 2007

Shwmae!

That's fantastic! Took a bit of frustrated hacking away until I understood, but I got there! I but the $db PDO thing in my database include, then slammed this in and it works!

php:
<?php    
    require ('../config/db.php');
        
    if (isset($_GET['ship_id']))
    {
        $ship_id $_GET['ship_id'];

        $array1 = array("CO""XO""OPS""NAV""CTO""TAC""CMO""MED""CSO""SCI""CEO""ENG""AUX");    
            
        $open_positions_query "SELECT position FROM ship_positions WHERE ship_id = :ship_id";
        $bind = array('ship_id' => $ship_id);
        
        $stmt $db->prepare($open_positions_query);
        $stmt->execute($bind);
        
        $result $stmt->fetchAll(PDO::FETCH_ASSOC);
        
        foreach ($result as $row)
        {
            $array2[] = $row['position'];
        }
                
        if (empty($array2))
        {
            $arrayresult $array1;
        }
        else
        {
            $arrayresult array_diff($array1$array2);
        }
        
        while(list($key$val) = each ($arrayresult))
        {
            $option .= '<option value="' $val '">' $val '</option>';
        }
    
        echo $option;

    }
?>

Is that acceptable and secure code or should I go back and try again?

fletcher
Jun 27, 2003

ken park is my favorite movie

Cybernetic Crumb
Looks good. Also make sure that if/when this thing is publicly facing, then your error reporting is set up so that end users won't see any details about PHP, PDO, etc when it hits an error. You don't want to leak any debug info or implementation details. Try shutting down MySQL or executing a malformed query and see what it does.

Also be aware that if you are generating HTML from user supplied values stored in your database, you have to escape it with htmlspecialchars (I think this is still the one, been awhile since I've done PHP). Otherwise you would end up with something like:

code:
<option><script>alert('pwned');</script></option>
For this particular snippet it's hard to say whether or not you have to be concerned about since we don't know where position comes from, but just something to generally be aware of when making dynamic websites.

substitute
Aug 30, 2003

you for my mum

Cthulhuite posted:

That's fantastic! Took a bit of frustrated hacking away until I understood, but I got there! I but the $db PDO thing in my database include, then slammed this in and it works!

Cool, here's how I would probably something like this. Test to see if it works.

php:
<?php
// do some clean-up on $_GET before this
$ship_id $_GET['ship_id'];

if($ship_id) {
    $query "SELECT position FROM ship_positions WHERE ship_id = :ship_id";
    $bind = array('ship_id' => $ship_id);
    
    $stmt $db->prepare($query);
    $stmt->execute($bind);

    $result $stmt->fetchAll(PDO::FETCH_ASSOC);

    foreach($result as $row) {
        $open_positions[] = $row['position'];
    }
}

$default_positions = array('CO''XO''OPS''NAV''CTO''TAC''CMO''MED''CSO''SCI''CEO''ENG''AUX');    

$positions = ($open_positions) ? array_diff($default_positions$open_positions) : $default_positions;

foreach($positions as $position) {
    $options_html .= "<option value='$position'>$position</option>\n";
}
?>

<select name="positions">
    <?= $options_html?>
</select>

Sulla Faex
May 14, 2010

No man ever did me so much good, or enemy so much harm, but I repaid him with ENDLESS SHITPOSTING
I'm on my phone so cant see some of the code from cthulhuite but make sure you filter each GET according to the variable you expect to receive. Php has functions for this or you can muck around with regular expressions and make your own. E.g. If you are expecting ids, only allow 0-9s and set a max length.

Cthulhuite
Mar 22, 2007

Shwmae!

Sulla-Marius 88 posted:

I'm on my phone so cant see some of the code from cthulhuite but make sure you filter each GET according to the variable you expect to receive. Php has functions for this or you can muck around with regular expressions and make your own. E.g. If you are expecting ids, only allow 0-9s and set a max length.

Based on this, I also cobbled this together;

php:
<?
if (!ctype_digit($_GET['ship_id']) || (!preg_match('/^\d{2}$/', $_GET['ship_id'])))
    {
        // Redirect to roster page
        header("Location: roster_fleet");
    }
 
$ship_id = $_GET['ship_id'];
?>
ship_id is never expected to be more than 2 characters, and always an integer. So, that checks to make sure it's a number and also that it's two characters, and if it's not it redirects you to the roster page.

Seems to work, is there something i'm missing?

Blinkz0rz
May 27, 2001

MY CONTEMPT FOR MY OWN EMPLOYEES IS ONLY MATCHED BY MY LOVE FOR TOM BRADY'S SWEATY MAGA BALLS

Cthulhuite posted:

Based on this, I also cobbled this together;

php:
<?
if (!ctype_digit($_GET['ship_id']) || (!preg_match('/^\d{2}$/', $_GET['ship_id'])))
    {
        // Redirect to roster page
        header("Location: roster_fleet");
    }
 
$ship_id = $_GET['ship_id'];
?>
ship_id is never expected to be more than 2 characters, and always an integer. So, that checks to make sure it's a number and also that it's two characters, and if it's not it redirects you to the roster page.

Seems to work, is there something i'm missing?

use filter_input or filter_input_array for your input validation. It's designed to do exactly what you want.

Cthulhuite
Mar 22, 2007

Shwmae!

Blinkz0rz posted:

use filter_input or filter_input_array for your input validation. It's designed to do exactly what you want.

I couldn't get that working straight away, but i've played with it and that is certainly a lot easier than a big if statement. Thanks!

Sulla Faex
May 14, 2010

No man ever did me so much good, or enemy so much harm, but I repaid him with ENDLESS SHITPOSTING
Yep that's what I was referring to, if your GET vars are basic types then you can use those, otherwise if they're more complicated you'll have to muck around with preg match etc.

Also note that in your example you'd also want to follow the header() with a die() so if the header gets blocked (it's not foolproof) at least the script stops executing at that point.

In my view it's also better form to create new variables at the point of doing the input checking, and then refer only to those in your later script. That way you know you are working with validated data and you don't accidentally run the risk of missing an input check and working with the originals. If it doesn't pass the validation check, it doesn't get assigned and any later calls to use it fail.

Cthulhuite
Mar 22, 2007

Shwmae!

Sulla-Marius 88 posted:

Yep that's what I was referring to, if your GET vars are basic types then you can use those, otherwise if they're more complicated you'll have to muck around with preg match etc.

Also note that in your example you'd also want to follow the header() with a die() so if the header gets blocked (it's not foolproof) at least the script stops executing at that point.

In my view it's also better form to create new variables at the point of doing the input checking, and then refer only to those in your later script. That way you know you are working with validated data and you don't accidentally run the risk of missing an input check and working with the originals. If it doesn't pass the validation check, it doesn't get assigned and any later calls to use it fail.

Thanks!

That's how i've been doing it, so it was pretty simple to change as I was only pulling one $_GET at the start and then building other variables from that if needed. This is the first time i've even looked at PHP in ten years, and my first big project beyond tweaking phpBB, so I set out with the goal to learn everything I could while doing it. It's been a task, and it's taken me about 4 months just to get things doing the things I want, so it's good that going through and making everything more secure was a fairly straight-forward process.

Adbot
ADBOT LOVES YOU

sausage king of Chicago
Jun 13, 2001
Anyone familiar with the Yahoo Sports API? I'm trying to pull in the current NFL roster but having some issues. I'm using the login_with_yahoo OAuth script found here and running a simple script to run a YQL query:

php:
<?php  
$consumer_key 'myKey';  
$consumer_secret 'myKey';  
$o = new OAuth$consumer_key$consumer_secret,   
                OAUTH_SIG_METHOD_HMACSHA1,  
                OAUTH_AUTH_TYPE_URI );  
  
$query urlencode("select * from fantasysports.players where league_key='314.l.408939'");
$url 'http://query.yahooapis.com/v1/yql?q='.$query;

try {  
  if( $o->fetch$url ) ) {  
    print $o->getLastResponse();  
    print "Successful fetch\n";  
  } else {  
    print "Couldn't fetch\n";   
  }  
} catch( OAuthException $e ) {  
  print 'Error: ' $e->getMessage() . "\n";  
  print 'Response: ' $e->lastResponse "\n";  
  
}  
?> 
The query works fine if I run it from the YQL Console, but if I run it from the script I get "Authentication Error. The table fantasysports.games requires a higher security level than is provided, you provided APP but at least USER is expected". My key is set to grab private data, so I'm not sure what the deal is. Looking on their forums and Googling hasn't given me anything.

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply