Getting Started with Adobe After Effects - Part 6: Motion Blur


Upload Image Close it
Select File

A step-by-step guide to learn PHP

Authors

Getting Started with PHP

Getting Started with PHP - Part 3: Language Basics

Sep 18 2012 12:00AM by grantwparks   

I think of PHP as a C-like language, but actually C's roots go back to ALGOL, in the 1960's. You could call it another “curly-brace” language. All of these programming languages have familiar tokens and control structures, although they may be used a little differently, especially during initialization.

  • ; ends a statement
  • {} wraps blocks of code like functions and loop bodies
  • [] delimits array indices
  • if, while, for, switch
  • function, return, try, throw, catch
  • class, public, private, interface (for object oriented programming)

Variables

In PHP, variables begin with '$'. They don't have to be declared before using them, although some people feel it's good practice to initialize them at the beginning of code. PHP has the basic data types like integer, boolean, strings and arrays. And more exotic types like objects, callbacks and resources. PHP arrays are uniquely useful, and include functionality of hashes (also known as maps or dictionaries) as well as basic arrays. They're not “strongly typed”, which means that the value in a variable determines its type.

$myString = “some string”;     
$myInteger = 5;                        
$myArray = array('key1' => $value, 'foo' => 6);
$myBoolean = true;
$myFloat = 1.234;
$myObject = new MyClass();

It's even possible to say:

$myVar = “5”;  // it's a string value
$myVar += 5;   // now it's an integer 10, because PHP turned “5” into 5 for adding

So PHP will implicitly convert data types, if possible, wherever it's necessary. For instance, instead of testing a boolean before incrementing

if ($myVar == true)
    $count ++;

We could add the boolean to the integer, because += requires number operands which will force false to be converted to 0 and true to 1.

$count += $myVar;

Arrays

PHP arrays are very flexible and deserve an in depth discussion. In PHP, an array can be a list of values:

$myarray = array ('apple', 'pear', 'kiwi');

or an indexed structure, also known as a hash, or dictionary:

$myhash = array (
  'fruits' => array ("apple", "pear", "kiwi"),
  'veggies' => 'no',
  'nuts', 'berries', 'roots'
);

Any array members that don't have an explicit index are assigned an integer index, beginning with 0. So the internal representation of that last one is:

array (
    'fruits' => Array
        (
            0 => apple
            1 => pear
            2 => kiwi
        )

    'veggies' => no
    '0' => nuts
    '1' => berries
    '2' => roots
)

Array values can be arrays, allowing nested structures representing complex data.

PHP comes with a large number of functions to search and manipulate arrays.

Operators

The operators in PHP mirror C's operators, with the omission of pointer operations. Operators also have a relative precedence, which controls the order of evaluation in a statement. Adding parentheses can alter this order or make statements more readable. For instance,

$foo = $width - $border * $length;

If the subtraction needs to be first, this statement must be written like:

$foo = ($width - $border) * length;

The rules are mostly intuitive, but not always.

$fooBool = false;
echo “I want to print 'yes' or 'no' . Is this boolean true? ” . $fooBool ? “yes” : “no”;

The output of this statement is “yes”, because string concatenation using . has higher precedence than the conditional operator, ?:. Therefore the main string gets concatenated with $fooBool's string representation (which is an empty string for false). Then that string evaluates as a true condition for the ?: operation. To get the expected output, you have to wrap the expression in parentheses.

$fooBool = false;
echo “I want to print 'yes' or 'no' . Is this boolean true? ” . ($fooBool ? “yes” : “no”);

I want to print 'yes' or 'no'. Is this boolean true? no

Like some other languages, PHP has two equality tests, == and ===. The latter checks that both the value and type are the same.

$strVar = "5";
$numVar = 5;

echo "equal values? " . ($strVar == $numVar ? "yes" : "no") . '<br/>';
echo "equal values and types? " . ($strVar === $numVar ? "yes" : "no");

equal values? yes
equal values and types? no

In the case of objects, == tests that two instances are of the same class and contain the same values; === will only be true if they refer to the same instance.

class MyClass {
  public $foo;
  function __construct ($foo) {
    $this->foo = $foo;
  } 
}

$obj1 = new MyClass (1);
$obj2 = new MyClass (2);
printf ("obj1 vs obj2: ==, %s ===, %s.", 
    	$obj1 == $obj2 ? 'yes' : 'no', 
    	$obj1 === $obj2 ? 'yes' : 'no');

$obj2->foo = 1;
printf ("obj1 vs obj2: ==, %s ===, %s.", 
    	$obj1 == $obj2 ? 'yes' : 'no', 
    	$obj1 === $obj2 ? 'yes' : 'no');

$obj2 = $obj1;
printf ("obj1 vs obj2: ==, %s ===, %s.", 
    	$obj1 == $obj2 ? 'yes' : 'no', 
    	$obj1 === $obj2 ? 'yes' : 'no');
return;

obj1 vs obj2: ==, no ===, no.
obj1 vs obj2: ==, yes ===, no.
obj1 vs obj2: ==, yes ===, yes.

The use of === is only occasionally called for, in my opinion. In a sense, being so strict with the type gets in the way of writing more reusable (and polymorphic) code. It's probably most useful when comparing against null or false, since these are equal in value to a number of non-true values. For instance, the PHP function strpos() returns the position of one string in another, or false if not found. Since the position starts at 0, it's necessary to use === to tell the difference between “not found” or “found in position 0”.

if (false === strpos ($stringToSearch, 'lookfor'))
  // can't find lookfor

Logical operators are the next most common after comparison operators. They allow us to combine multiple tests. So we can ask if ($thisIsTrue && $soIsThat || $neitherIs). Logical operators have a natural precedence, also, making the “and” (&&) evaluate before the “or”.

Let's use some of the types to write a function that returns HTML to be inserted in the header of every page. You should have /public and /includes directories from the installation examples. Create /includes/user_status.php with this code:

<?php
function getHeader () {
  $user = "Anonymous";
  $time = date('M d, g:i a');
  return '<div class="page header">' .
        "<span class=\"message\">Hello, {$user}</span>&nbsp;&nbsp;” 
        ."<span class=\"information\">" . 
        "Prior Sign In {$time}" . '</span></div>';
}

And require it in index.php, anywhere inside the tag.

<?php
    require '../includes/user_status.php';
    echo getHeader();
?>

Resulting in the following HTML:

Hello, Anonymous  Prior Sign In Jun 10, 1:03 pm

Notice that spaces are not significant outside of strings, and I can concatenate strings using the . operator anywhere between two strings. Sometimes people will code a long string on multiple lines without closing it until the end.

echo '<ul>
    	<li>', $choice1, '</li>
    	<li>', $choice2, '</li>
    </ul>';

It works because spaces outside the HTML tags aren't significant in the final output. But think of all that empty space.

String Delimiters

I used a mix of string delimiters in getHeader() to illustrate PHP's flexibility. A team should pick a style and use it consistently, but there are times when taking advantage of a different string delimiter can make things more readable.

If a string is delimited by “, PHP will replace the values of variables in the string. There is an ongoing argument that using ' to delimit strings instead of " is more efficient. The truth is it has a very small effect. In fact, concatenating strings for echo, as I did above, has a more negative impact on performance. (The more efficient way is to separate each piece of the string with a comma, because echo is a strange keyword that acts like a function with optional arguments.) My personal preference is to use " around values that are used as strings and ' around values that are used as symbols. To see what I mean, consider an array containing a user's information:

$myArray = array (
      'name' => “Steve Jones”,
      'addr' => “100 Cherry St”
);

In this code, I think of name and addr as keys. Although, it's not necessary to delimit variables in a string with {} in all cases, I recommend always using them for readability:

print "My name is {$username}.";

As I said, there are situations when using the opposite delimiter works better: when I'm formatting HTML, I use ', because the HTML attributes should technically use “ as delimiter, and I want to avoid escaping them all:

$headerOption = '<optgroup class="filter-label" label="%s">%s</optgroup>';

(The %s values are format specifiers used by the printf() function.)

A simple way to see the interpretive nature of the language is to do multiple substitution.

$a = "apple";
$b = "a";
$c = "b";
print "value is {${${$c}}}";

value is apple

As you can see, echo, print and printr are effective ways of outputting the results directly to the browser. They can be used to debug trivial code, but for normal programming I use the errorlog() function to send output to the file we specified in php.ini. errorlog() can do a lot, but in its most basic form it just writes the string argument to our PHP log. To print arrays we need to use printr's optional argument.

error_log (print_r ($myArray, true));

The true argument tells print_r to return the result as a string instead of sending it to the HTTP response stream.

Scope and function arguments

getHeader would be of little value if it always prints information from a local variable. Maybe we should simply set $user outside of getHeader:

$user = "Fred";

function getHeader () {
  $time = date('M d, g:i a');
  return '<div class="page header">' .
        "<span class=\"message\">Hello, {$user}</span>&nbsp;&nbsp;”
        ."<span class=\"information\">" . 
        "Prior Sign In {$time}" . '</span></div>';
}

However, we get an error (you'll won't see this if ENOTICE is turned off in the errorreporting setting – EALL includes ENOTICE):

Notice: Undefined variable: user in C:\Users\grantwparks\workspace\phpweb\public\user_status.php on line 8

PHP doesn't make $user visible inside the function, which is good thing. There should be very few lines of PHP existing outside of functions and theoretically no use of global variables. There are a number of common practices that create the same dependency as using global variables, but are better from a maintenance perspective, including define symbols and "static classes". We could make the global variable available by adding a line to getHeader:

function getHeader () {
  global $user;
  ...
}

By declaring the variable global, we make it visible inside this function. Sometimes I see the following outside of any function declaration (in the global space):

<?php
  global $user;
  $user = "Fred";

PHP programmers should know that "global" here has no effect. There is no “global declaration” that makes a variable global, global only makes a variable visible inside the function where it appears.

But instead of a global variable, let's pass an argument, or parameter, to getHeader. Remove the line inside getHeader that defines $user, change the function declaration to function getHeader ($user) and pass a value for $user in the call from /index.php like getHeader ("Any User");

Hello, Any User  Prior Sign In Jul 16, 7:41 pm

What happens if we forget to pass a user to getHeader? Several errors appear, depending on the error settings, and we get notified that there wasn't a value for $user. PHP can still return its value, with an empty string in $user's place.

Hello,   Prior Sign In Jul 16, 7:42 pm

A default value can be supplied in the function declaration.

function getHeader ($user = "default user name")

That will guarantee that $user has a value to operate with and now we have a function that will work for any $user, by passing it as an argument.

Pass By Value vs Pass By Reference

In PHP, every function argument is passed by value, meaning a copy of the value – it can't be changed by the function. Objects are passed by reference. It's not exactly a pointer or reference, but that's how it works. To do the same with another type, the argument is prefixed by & in the function declaration, not in the call. Passing a non-object variable normally protects it from being changed within a function

function foobar ($arg) {
  $arg = "bar";
  echo $arg, '<br/>';
  return;
}

$outerVar = "foo";
foobar ($outerVar);
echo $outerVar;

bar
foo

Even though a new value was set inside the function, it's still the same outside. But when the reference operator is added to the function argument, the outer variable becomes modified by the function.

function foobar (&$arg)

bar
bar

Changing a variable's value inside the function should normally be used only under special circumstances; it's very “unstructured”, because it's not obvious that the argument's value can be changed. It can be handy for special purposes, like when a function needs to return more than one result. Imagine a function that decides whether the user can access some information.

function allowAccess() {
  if (test-expression-1 && test-expression-2)
    return true;
  else 
    return false;
}

Also assume in most cases, we only need to know if access is allowed

if (allowAccess()) {
  // show the data
}

In some cases, it might be appropriate to display an error after checking. Now, there may be several reasons why allowAccess returns false, and that knowledge should only exist inside allowAccess. Whenever we need to implement some kind of rule, we want it in one place only and not have any other code know what the specifics are. In other words, if it returns false, there's no way for the caller to know why. However, we can pass an optional reference argument to allowAccess to get back the reason when we need it.

function allowAccess(&$reason = false) {
  if (test-expression-1 && test-expression-2)
    return true;
  else {
    if ($reason !== false)
      $reason = "User doesn't have authority to read.";
    return false;
  }
}

if (!allowAccess($msg)) {
  echo '<div class=”error”>Not allowed.', $msg, '</div>';
}

It's important that $reason is checked before setting it, to make sure an argument was passed. Using the strict equality test is important, because an unitialized argument, like $msg, will have a null value which is equal in value to false.

We covered a lot of the basics and some trivia. Next we can start putting them together to serve Web pages.


grantwparks
174 · 1% · 280
7



Submit

Your Comment


Sign Up or Login to post a comment.

"Getting Started with PHP - Part 3: Language Basics" rated 5 out of 5 by 7 readers
Getting Started with PHP - Part 3: Language Basics , 5.0 out of 5 based on 7 ratings
    Copyright © Rivera Informatic Private Ltd Contact us      Privacy Policy      Terms of use      Report Abuse      Advertising      [ZULU1097]