Free Republic
Browse · Search
Bloggers & Personal
Topics · Post Article

To: Mycroft Holmes

PHP:

Functions Variables Strings Concatenation If

You can't use PHP on the forum for obvious reasons.

PHP is a Scripting Language like JavaScript. Unlike JavaScript, which runs in the user's browser to mediate user interactions, PHP runs on the server in a fashion which is invisible to the user. It the user invokes View Source he won't see any of the PHP on the page. PHP is used to run C programs as part of the HTML pages on the server before the raw HTML is generated and presented to the user.

All scripts in HTML begin with <? Have script stuff here, and end with ?>. The default script type is JavaScript. To get the PHP interpreter you need to start the script with <?php You can find the PHP manual here. What you will find if you poke the link is a pretty good manual describing how the PHP preprocessor works and quite a bit of material about the language C. You need to know this, leave this tab open if you are not fluent in C.

C is fundamental. You can not go wrong learning C, it's everywhere you want to be. C in PHP is a little different than standard C, it is not really typed. This means that variables, which all start with $, can have any sort of value stuffed into them. If you try to multiply a character by an array this implementation will let you and not warn you. It's part of its charm. Let's talk about that magical little PHP fragment we are using for debugging:

<?php 
$debug = true;
if($debug) {$ta = array_keys($_POST);for($ti=0;$ti<count($ta);$ti++) {echo $ta[$ti]."=".$_POST[$ta[$ti]]."<br>";}}
?>
If your eyes glaze over as you read this next passage just skip it. I promised to do this bit earlier and understanding exactly how this works is not at all necessary to continue but it is a nice spot to stop and talk about the syntax of C as practiced by PHP.

The first line opens the PHP script. The second line assigns the value of "true" to the variable $debug. The assignment operator is an equals sign = . Note that the line, and what we call the expression ends with the semicolon → ; ←. Expressions are bits of C that have meaning and are almost always terminated with a semicolon. Expressions may continue across lines that don't end with a semicolon.

The third line is an if statement, if $debug is true (and it is, we set it the line before) then we do all of the stuff inside the first pair of curly braces {...do all this stuff...}. This is the entire rest of the line as the curly braces nest so you do the stuff out to the matching brace at the end of the line. The curly braces serve to group the entire rest of the line as the required "do if true" part of the if statement. There is an optional "else, do if false" part but that isn't present here. A parenthetical note here, if you are using Programmer's Notepad you'll see that PN will show you the matching brace to one you select. This is really sweet and you need this, get it now.

The first expression in the "do if true" part is $ta = array_keys($_POST); $ta is a variable we pulled out of thin air. I call it 'ta' as a really short form of TemporaryArray. I don't call it TemporaryArray because I want the entire expression to fit on one line. array_keys($_POST); is what we are assigning to $ta. array_keys is a built in PHP function that returns an array of keys from the key=>value pairs which comprise an array.

Arrays are a bit different in PHP; the index of the array is not constrained to be numeric, it can also be a string. This is very different from C and has profound and useful implications. $_POST is an array constructed from the HTML post data where the keys (indexes of the array) are the names of the inputs in the form being submitted and the values of the array are the values of those inputs. And yes, you can have arrays of arrays. PHP is nothing if not flexible.

So after the first expression is evaluated we have an array of keys in $ta. The second expression:
for($ti=0;$ti<count($ta);$ti++) {echo $ta[$ti]."=".$_POST[$ta[$ti]]."<br>";}
is a for loop. This is a loop that iterates through a sequence of instructions a number of times and then quits. The basic logic goes: 1. set x to some number; 2. if x < some other number don't quit ; 3. do some thing; 4. increment x; 5. Go to 2 until quit. The actual formal expression is a bit more compact.

for($ti=0;$ti<count($ta);$ti++) is the control structure for the loop. The first expression inside the parenthesis assigns $ti (temporary index) the value 0. The second expression checks to see if $ti is less than count($ta). count is another built in PHP function that returns the number of keys in an array. If $ti is less than count($ta) then the statement(s) in the curly braces { } right after the closing parenthesis of the control structure are executed:
{echo $ta[$ti]."=".$_POST[$ta[$ti]]."<br>";}
echo emits a string as raw HTML to the page. What we are echoing is the concatenation of four strings. The concatenation operator is the period (.), really. The first string $ta[$ti] is fetched from the array of keys we put in $ta. The keys for the array $ta itself are numeric, as this is the default for the function array_keys. Other options are possible, we'll see those later. As the loop increments the string in $ta[$ti] will be the name of each input in the previous form's post and that will be printed to the screen. The next string to be printed is an equals sign "=". Next is the string in the array $_POST[$ta[$ti]]. $_POST contains the key=>value pairs that are the previous form's inputs, $ta[$ti] contains the string that is the key for $_POST so that whole bit resolves to the value in $_POST pointed to by a particular named input. This cycles through all of the variables passed in the post. Hope that made sense.

The previous web page rewritten in PHP idiom looks like:

  <body>
	<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
<?php 
$debug = true;
if($debug) {$ta = array_keys($_POST);for($ti=0;$ti<count($ta);$ti++) {echo $ta[$ti]."=".$_POST[$ta[$ti]]."<br>";}}

	echo "Hello World...<br />";
	echo "Fave Flav:<input type='text' name='favorite_flavor' /> ";
	echo "<select onchange='updateMenu();' name='command'>";
		echo "<option value='Global Commands'>Global Commands</option>";
		echo "<option value='Add To List'>Add To List</option>";
		echo "<option value='Delete From List'>Delete From List</option>";
	echo "</select>";
	echo "<br />";
	echo "<input type='submit' name='submit' /> ";
?>
	<form>
  </body>
This is pretty boring, all we have done is put the PHP command echo in front of each line of HTML, quoted the HTML using double quotes, and replaced the double quotes " in the HTML with single quotes '. The last bit is important, HTML doesn't care about the difference between double and single quotes, PHP does. If you write all your HTML using single quotes you may then grab it right up and echo it without editing. Also, we added a semicolon ; to the end of each line of PHP, that's what indicates the end of the line.

One of the many things that PHP lets us do is sort of hide, or cram down information. The select in the previous example takes a lot of lines to make but is conceptually simple. Using PHP we can make the creation of that select appear as a single line by putting most of the work in another file. Copy the following text into a subdirectory you name "include", name the file "tutorial_functions.php".

<?php
/*		file: include/tutorial_functions.php
*		2012/029/13 - working initial cut
*		
*		Functions for tutorial
*/
function select_command($_POST, $base_name) {
	echo "<select onchange='updateMenu();' name='".$base_name."'>";	
	if ($base_name == 'command') {
		echo "<option value='Global Commands'>Global Commands</option>";
		echo "<option value='Add To List'>Add To List</option>";
		echo "<option value='Delete From List'>Delete From List</option>";
	} else {
		echo "<option value='Local Commands'>Local Commands</option>";
		echo "<option value='Chocolate'>Chocolate</option>";
		echo "<option value='Vanilla'>Vanilla</option>";
	}
	echo "</select><br />";
}
?>
to PHP
This is a function that makes a Select Object. A function is not an in-line replacement, rather it is a template for an instance of, in this case, a select object. The function's name is select_command. Information is passed into the function by the variables inside the parenthesis after the function name. All variables in PHP begin with $, that's how you know they are variables. Variables that are used by PHP and the System begin with $_, don't begin your variable names with underscore. In this case, we are passing in all of the inputs from the previous page in $_POST and a name for the particular select we are making when we call this function in $base_name.

The second line of the function begins with echo to emit raw HTML to make the select. The onchange='updateMenu();' bit is a directive to the select to call the script updateMenu(); when the value of the select changes. There is no script available to run, yet, so this is ignored. We'll be using this later. To understand the next new bit .$base_name. we'll need to talk a bit about strings.

Strings in PHP are collections of characters surrounded by double quotes. They can also be variables which have been assigned the value of strings, like $base_name in the example above. The PHP command echo expects one string as its argument. In the above example there are three distinct strings, two delimited by double quotes and the string contained in the value of $base_name. How we make these three strings one is by Concatenation of the strings using the . operator. Yes, the operator (symbol) for concatenation (mushing the strings together) is a period. Learn more about strings here.

So what we are doing with the second line is an echo of three strings mushed into one by the two periods surrounding .$base_name. followed by a ; (semicolon) to terminate the line.

The next line is an If Statement. The if statement is one method of directing program flow, or deciding things depending on how you think of this stuff. It has the form if(some_expression){do_if_true;}else{do_if_false;} The some_expression part has to evaluate to true or false. This is called a Boolean type. The semicolons after the do_if_true/false parts are required, the else do_if_false part is not required. The parentheses are used to group statements together and are optional if there is only one statement in each group.

The boolean expression in the example if($base_name == 'command') gets evaluated. If $base_name is equal to the string literal 'command' the expression evaluates to TRUE and the next statement is executed. The double equals == is the comparison operator for equals. A single equals = is an assignment operator which would assign the string 'command' to the variable $base_name, not what we want.

To recap, we have a function which when called creates an instance of a select which is named whatever name we passed in $base_name and depending on the value of that name makes one or the other type of select. After the select is constructed we echo a break to put whatever comes next on a new line.

Now we'll rework index.php, copy the following into the body part of the file.

  <body>
	<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
<?php 
$debug = true;
if($debug) {$ta = array_keys($_POST);for($ti=0;$ti<count($ta);$ti++) {echo $ta[$ti]."=".$_POST[$ta[$ti]]."<br>";}}

	include "include/tutorial_functions.php";  // a collection of functions for various stuff

	echo "Hello World...<br />";
	echo "Fave Flav:<input type='text' name='favorite_flavor' /> ";
	select_command($_POST, $base_name="command"); // pick a command
	select_command($_POST, $base_name="something_else"); // pick another command
	echo "<input type='submit' name='submit' /> ";
?>
	<form>
  </body>
What's changed here is the include directly after the debug line. This sticks the contents of the named file inline in that spot. Since the file is a function it isn't executed (run) until it is called (invoked). We call that function twice with the lines that start select_command. If you save both files and mash Submit you should see something like:

10 posted on 02/14/2012 8:37:28 PM PST by Mycroft Holmes (Mash name for HTML primer)
[ Post Reply | Private Reply | To 9 | View Replies ]


To: Mycroft Holmes
The function we have constructed previously is pretty trivial and perhaps not very interesting but it does show how you can use a function as a template to create different instances of similar items.

What follows is a more amusing piece of code that actually does solve something. Specifying a quantity of stuff is a problem that comes up fairly often. Quantities have an amount and a unit, like 3 gallons or 5 feet. As a general rule you want to avoid allowing the user to type anything that will be used as an entry into a database, they will only break your heart (or tables). So selects are preferred to text inputs for pretty much everything. This generates a pair of selects named $prefix.'count' and $prefix.'units' right next to each other.

By this time when you see $ you should think variable. So you know that $prefix means some string that has been assigned to the variable $prefix. You should also think string literal when you see single quotes around some text, like 'count'. So when you see $prefix.'count' you are seeing the contents of the variable $prefix concatenated (.) with the string literal 'count' which results in one string.

Another thing you need to be aware of is that if something isn't a variable and it isn't quoted by either single or double quotes and it isn't an operator (<,>,=,+,-,...) and it looks like some_text($mumble_optional) then it is probably a function. Either one of yours or a PHP built in function. There is a nifty little search feature at the top of the the PHP documentation that defaults to searching the PHP function list. If you see something you don't understand that looks like a function(), go there for enlightenment grasshopper.

If you find yourself doing the same thing more that once you probably want to try to generalize it an make it into a function. Think of functions as tools that you are building. A few tools that do a a lot of things are better than a lot of tools that each do a few things. They are easier to find if they don't proliferate in an uncontrolled fashion.

A word about comments. PHP supports C style comments, which you don't see in the fragment below. I think comments are an unalloyed good, I just couldn't think of any to add to the code here that aren't blindingly obvious. Maybe I have been doing this too long. I do try to give variables and functions names that have readily apparent meaning.

Another thing I find useful is using text for option values in selects. If you don't specify a value an integer is assigned. Later when you evaluate the value you have an integer with no readily apparent meaning. In the past, integers were the preferred way of carrying value because memory was expensive and we tried to cram as much meaning into each bit as possible. Today memory is cheap, programmer's time is expensive. So any little thing we can do to make things blindingly obvious is a good thing.

Note that we are passing $Ingredient_Count and $Units into the function. This is because we can use the select as both a knob (to adjust things) and an indicator (to inform the user). Without special effort a select shows the first option on the list. We are passing the function the values that we want the select to stick at. If we don't provide values it will do the default behavior. In general we want to design objects that are as broadly useful as possible. This is why we didn't stick any labels on the selects in this function; any that we picked now would probably be wrong. We could pass one in, but it's a complication. Simple and general are what we strive for in functions.

function select_quantity($prefix, $Ingredient_Count, $Units)
{			
	echo "<select onchange='updateMenu();' name='".$prefix."count' >";
	for($i=0.5;$i<5;$i=$i+0.5) {
		if($i != $Ingredient_Count) echo "<option value='".$i."'>".$i."</option>";
		else echo "<option selected='selected' value='".$i."'>".$i."</option>";	
	}
	for($i=5;$i<33;$i++) { 
		if($i != $Ingredient_Count) echo "<option value='".$i."'>".$i."</option>";
		else echo "<option selected='selected' value='".$i."'>".$i."</option>";	
	}
	echo "</select>";
	echo "<select onchange='updateMenu();'  value='ea' name='".$prefix."units' >";
	if ('ea' != $Units) {echo "<option value='ea'>ea</option>";}
	else {echo "<option selected='selected' value='ea'>ea</option>";}
	if ('oz' != $Units) {echo "<option value='oz'>oz</option>";}
	else {echo "<option selected='selected' value='oz'>oz</option>";}
	if ('g' != $Units) {echo "<option value='g'>g</option>";}
	else {echo "<option selected='selected' value='g'>g</option>";}
	if ('lb' != $Units) {echo "<option value='lb'>lb</option>";}
	else {echo "<option selected='selected' value='lb'>lb</option>";}
	if ('tsp' != $Units) {echo "<option value='tsp'>tsp</option>";}
	else {echo "<option selected='selected' value='tsp'>tsp</option>";}
	if ('tbsp' != $Units) {echo "<option value='tbsp'>tbsp</option>";}
	else {echo "<option selected='selected' value='tbsp'>tbsp</option>";}
	echo "</select>";
}
The first line echos the opening tag of the select assigning the name of the select to be $prefix."count' so we can identify this particular select. The next line is the beginning of a for loop which spans 4 lines. The control structure for the loop increments the temporary variable $i by 0.5 for each pass of the loop. We are doing this because we want the count part of this control to increment by half on the low end till the value 5 and then increment by 1 to 32 which is done in the second for loop. This gives us a finer control of the value on the low end where it is more important and the ability to choose the appropriate units give the user the ability to input any reasonable values for this application.

Thinking about reasonable values is part of what you want to do when you design a function. This particular application manages a household inventory. Initially I believed that most of what I was buying was groceries and this select design reflects that. The units are all weights and volumes which are useful in the kitchen and not lengths which are useful other places. After using the program for a bit I would add lengths to this control. I just haven't done it yet because I designed a general purpose work-around into the program that makes this flaw not painful enough to immediately address.

I'd also might add more numbers at the top incrementing by 5 from maybe 30 to 100. There is a limit to how many items you can usefully cram into a select though. One of the ways to manage that is to use a two stage select but that has some interesting complications we will get into later.

The third section of the function generates the units selector. In a select an option has two parts, a value and a label that appears to the user on the select itself. Explicitly calling out the value is not required, if it is absent an integer starting at 0 and incrementing for each additional option is provided. I like to use the same text for the value as the user sees; this way when I encounter the value in the program I know what it does, not just that it is '2'.

Now grab that code above and save it in ~www/tutorial/include/tutorial_functions.php just in front of the closing tag for the PHP at the end of the file. We'll be using this bit shortly. Now we want to rework ~www/tutorial/index.php so that the body looks like:

  <body>
	<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
<?php 
$debug = true;
if($debug) {$ta = array_keys($_POST);for($ti=0;$ti<count($ta);$ti++) {echo $ta[$ti]."=".$_POST[$ta[$ti]]."<br>";}}

	include "include/tutorial_functions.php";  // a collection of functions for various stuff

	echo "Hello World...<br />";
	echo "Fave Flav:<input type='text' name='favorite_flavor' /> ";
	select_command($_POST, $base_name="command"); // pick a command
	echo "<br />Food: ";
	select_quantity($prefix='food_'); // pick a quantity of food
	echo "<br />Drink: ";
	select_quantity($prefix='drink_'); // pick a quantity of drink
	echo "<input type='submit' name='submit' /> ";
?>
	<form>
  </body>

So save the files and hit Submit or Reload and pay attention. The first time you hit submit or reload the debug values aren't quite what you expect. Then you hit Submit again and they look OK. This is because the values in the debug area are the values that were on the previous screen. You need to keep that firmly in mind. These things become much more important later. You should now be seeing a screen that looks much like this:

So who ordered that break between Fave Flave: and Food:? Not what I had in mind. Poking about I notice that the select_command() function emits a <br /> at the end which is affecting our placement of related objects. Do not put positioning stuff in functions, it doesn't belong there. So fix select_command() in include/tutorial_functions.php so it doesn't emit that nasty break and save it away so it works properly. Good.

Another thing you might notice is that I entered 'chocolate => really' into the favorite_flavor text field. That => bit looks dangerously like an operator which ought to scare you. Remember, users can enter anything they can type into a text field and they are not usually looking to make life easy for you. They'll type the darnedest things... Don't give them the chance if you don't have to; if you do, pay attention, there are ways to mitigate the problem.

Another thing that is irritating about this program is that the controls and text inputs are not sticky. The data disappears when you Submit it. Usually that is what we want so that is the default behavior, but not always. Sometimes we want the data to stick. I want it to stick so that's what we'll do next.

13 posted on 02/15/2012 11:18:10 AM PST by Mycroft Holmes (Mash name for HTML primer)
[ Post Reply | Private Reply | To 10 | View Replies ]

Free Republic
Browse · Search
Bloggers & Personal
Topics · Post Article


FreeRepublic, LLC, PO BOX 9771, FRESNO, CA 93794
FreeRepublic.com is powered by software copyright 2000-2008 John Robinson