A guide into PHP for C++ programmers

By Joel Yliluoma, August 2007

Introduction

This document introduces quickly (yet rather thoroughly) the PHP programming language to those who are already well-versed in the C++ programming language (or can read it through experience of other similar languages such as Java). It may also teach new things for those who are already familiar with PHP.

The primary focus is for those who want to use PHP for serious programming, not just for scripting something for web. Also, this page only covers the language; the library functions are not covered.

Program structure

PHP is designed originally as a script engine that supports adding script into HTML documents. A typical file might look like this:

 <h1>Hello</h1>
 The time is <?php   print date('Y-m-d H:i:s');   ?>.
 <hr>
 This is a PHP hypertext processed page.
This can be explained by saying that the whole PHP document has an implicit "print" over and around it. The pseudo tag, "<?php", starts actual PHP code. From PHP code mode, it is possible to return back to the "print" mode with another pseudo tag, "?>".

If you intend to do actual programming in PHP and not use it as a script insertion engine, you are best off by starting the entire file with:

 <?php
And then just starting coding below it. Example:
 <?php
 echo "Hello, world!\n";
 echo 'The time is now ', date('Y-m-d H:i:s'), ".\n";
Note that it is not necessary to terminate the file with ?>. In fact, if you do, you risk the program outputting extra spaces and newlines if you happen to unknowingly enter them beyond the trailing ?>. This may be important, if you output binary data such as images.

Note: The <?php tag is sometimes written shortly as <?. However, because of possible ambiguities with other types of scripts, it is deprecated to do so.

Main program

In C and C++, the program starts from a magic function called main(). In PHP, there is no such magic function. If you want something executed immediately upon script execution, you just write it outside any function, in the global scope. Example:
 <?php

 function test($who) // declares a function
 {
   print "Hello, $who!\n";
 }

 // this is the main program

 $greet = 'world'; 
 test($greet);     // calls the function "test".
This example program executes in the following order:
  1. Define a function
  2. Declare and assign a variable
  3. Call a function
  4. Terminate

Operators

The same operators that work in C++, work in PHP. However, there are a few new operators: For precedence, you should check the manual.

Comments

PHP supports three styles of comments.

  
 /* C style
  */
  
 // C++ style
 // which can NOT be continued \
      on the next line with a backslash.

 # And unix shell/configuration file style.

Identifiers

In PHP, all variables begin with a dollar sign: $

If you see something like $x somewhere in the code, you definitely know that it is a variable (or in the case of $this, acts semantically like a variable).

Anything else, if it consists of letters, may be any of these three:

  1. A reserved word (keyword)
  2. A user-defined function or method name
  3. A class or interface name (only when preceded by class, new, extends or implements or followed by ::)
  4. A defined constant

When PHP parses your program, if it encounters an identifier that does not begin with a $, it first looks whether it is a reserved word or a constant. If it is neither, the semantics define how it is handled then. If it looks like a function call, it will interpret it as a function call. Otherwise, it will implicitly turn it into a string constant! This can sometimes be a "gotcha" to beginners.

Example:

 define('test', 9); // define is a reserved word.
                    // Here it defines a constant named "test".

 if($a == 5)  // if is a reserved word, $a is a variable
 {
   $gruu = 9; // $gruu is a variable
   fun(6);     // fun is a function
   fun(test);  // test is a constant, which evaluates into 9
   fun($gruu); // the value of the variable is passed as parameter
   fun(gruu);  // gruu is not a constant, the string literal "gruu" will be assumed
   fun(fun);   // the string literal "fun" will be passed to function fun().
 }
For brevity, we omit the <?php tag in this and all following examples.

The reason why unrecognized identifiers are automatically turned into string literals relies in the callback mechanism. For a function call such as this to work:

 
 uasort($myarray, mycomparer);
 
It has to turn "mycomparer" into a string literal. In PHP, if a variable contains a string value and one attempts to call the variable as if it were a function, the function that has the name by that string value will be called.

Constants and literals

Numeric literals

Numeric literals work the same way as in C++.

 $a = 5;       // integer literal 5
 $a = 5.3;     // floating point literal 5.3
 $a = 5.3e3;   // floating point literal 5300.0
 $a = 0x14;    // integer literal 20
 $a = -1;      // integer literal -1
 $a = 015;     // integer literal 13 (octal 015)

String constructs

String constructs in PHP bear superficial similarity to C++ string literals. However, it is important to recognize the differences.

First of all, there's two ways to declare string constructs.

 $a = "in double quotes";
 $b = 'in single quotes';
Both ways can be used interchangeably, but there is a difference in the features supported by each convention.

 $a = "This string contains a newline, a carriage return and a doublequote.\n \r \"";
 $b = 'This string also contains a doublequote, but instead of
       newline, there is a literal backslash and a letter. By
       the way, a string literal may span multiple lines (it
       includes newline literals). " \r \n';
 $c = 'String literals may be concatenated with the period operator.' . "\n";
  • The singlequote-enclosed string supports only two escapes: \' and \\.
  • The doublequote-enclosed string supports more escapes: \n, \r, \t, \\, \$, \", \[0-7]{1,3} (octal character codes) and \x[0-9A-Fa-f]{1,2} (hexadecimal character codes).
  • All other escapes are literals, where the backslash becomes also part of the string content. (Possible gotcha!)
  • The doublequote-enclosed string may also include variables; it is not necessarily a pure literal. The variables are evaluated and coerced into string to construct the string.

 // These two statements are equivalent:
 $a = "Apples are $x each.";
 $a = 'Apples are ' . $x . ' each.';
 
 // These two statements are equivalent:
 $a = "Apples are \$x each.";
 $a = 'Apples are $x each.';
 
 // These three statements are equivalent:
 $a = "Your {$item->name} is {$item->kind} and expires in {$item->eta} days.";
 $a = "Your ${item->name} is ${item->kind} and expires in ${item->eta} days.";
 $a = 'Your ' . $item->name . ' is '
              . $item->kind . ' and expires in '
              . $item->eta . ' days.';

 // These four statements are equivalent:
 $a = "The file is {$stat["size"]} bytes long.";
 $a = "The file is {$stat['size']} bytes long.";
 $a = 'The file is ' . $stat["size"] . ' bytes long.';
 $a = 'The file is ' . $stat['size'] . ' bytes long.';
 
 // Variable inclusions may be very complex, even recursive,
 // to the chagrin of writers of syntax highlighters.
 // These two statements are equivalent:
 $a = "This is {$table["subtable{$subnums["current"]}"][$position['now']]}.";
 $a = 'This is ' . $table[ 'subtable' . $subnums['current'] ]
                         [ $position['now'] ]
                 . '.';
The author of this article prefers to use the singlequotes whenever the features of the doublequotes are not used in the context, but always the form that requires less use of backslashes.

There is also a third kind of expression that looks a lot like a string constant, but it surrounds the string with backticks, i.e. the grave apostrophe. It parallers the similar syntax of the unix shell.

 $num_functions = `cat *.php | grep -c function`;
This syntax invokes the system shell, passes the command to the shell and returns the output of that shell. This syntax also accepts variable inclusions:
 $reqtype = 'lines';
 $filename = 'test.php';
 $linecount = `wc --$reqtype < $filename`;
However, it is very dangerous to use unless you know exactly what you are doing; the syntax does not escape parameters automatically, permitting remote code execution in the worst case.

A fourth way of entering string literals exists also. It parallers the here-doc mechanism of the unix shell.

 $testvar = 1;
 $testtext = <<<EOF
This is a long piece of text that may span multiple lines
and contain unescaped 'apostrophes' and "quotes".
As for any other escapes, such as variable references
($testvar) or backslash escapes (\r, \n), it behaves like
the doublequote-enclosed strings.
EOF;

Array constructs

Arrays in PHP are constructed very similarly to the way they are constructed in Javascript, Ruby, Python and a few other languages, albeit with more verbose syntax. It also slightly resembles the C++ way, but is more versatile.

 $powers_of_two = Array(1,2,4,8,16,32,64,128,256,512,1024,2048,4096);
 $vg_characters = Array
 (
   'supermariobros' => Array(
       'hero' => 'Mario Mario',
       'alternative_hero' => 'Luigi Mario',
       'enemy' => 'King Bowser Koopa',
       'henchmen' => Array('Goomba', 'Lakitu', 'Piranha plant', 'Koopa troopa')
     ),
   'metroid' => Array(
       'hero' => 'Samus Aran',
       'enemy' => 'Metroids'
     ),
   'megaman' => Array(
       'hero' => 'Mega Man',
       'hero_alternative_name' => 'Rockman',
       'enemy' => 'Dr. Wily'
     )
 );
Note that this is not merely an array initializer. Array constructs can be used in expressions, unlike in C++. It is also not a function call, though it is evaluated at runtime. It is a language construct with its own distinct syntax.

Examples of using array constructs in an expression:

 $colortable->Init( Array('blue', 'red', 'green') );
 
 function PrintBoxCoordinateList($x,$y, $w,$h)
 {
   foreach(Array($x, $x-$w, $x+$w) as $xcoord)
     foreach(Array($y, $y-$h, $y+$h) as $ycoord)
       print "$xcoord,$ycoord\n";
 }
Arrays are discussed in more detail in the "Data structures" chapter of this document.

Named constants

It is possible to define named constants in PHP. The syntax for them is very different from the way how variables are declared:

 define('MERCURY_RADIUS', 2440);
 
 echo 'The radius of Mercury is ', MERCURY_RADIUS, " km\n";
 
 $radius = MERCURY_RADIUS;
Note that named constants cannot be used in the variable inclusion syntax of doublequote-enclosed strings.

For the syntax of named constants in interfaces and classes, see the section about classes.

Note that the meaning of named constants is different from that in C++: In C++, named constants are simply variables whose value cannot be changed. In PHP, the use is the same but they live in another namespace, and you cannot create a reference to a constant.

Variables, types and scope

Declaration

In PHP, variables do not need to be declared. They exist from the first instant they are referred to. For example, this is valid code:
 
 $test_var = 'Testing, testing...';
 
It introduces a variable called $test_var into the current scope and assigns it a string value. If there already exists a variable by that name in the current scope, that variable is changed instead.

Accessing an uninitialized variable (i.e. when the first encounter of the variable is in a reading context) may cause a warning, but it is not an error in PHP.

Scope

The scope of locally declared variables (in functions) is the function. The angle braces { and } do not start a new scope, like they do in C++.

The scope of globally declared variables is the main program. They can be imported to functions using the global keyword, but by default, they do not exist in the function scope. This is opposite to how it works in C++.

Example:

 $a = 5; // a global variable
 function test()
 {
   $b = 3; // a local variable
   $a = 8; // a local variable; global is not affected
   global $a; // now imports the global variable into local scope
   $a = 11; // changes the global variable
 }
 $a = 9; // changes the global variable
 { $c=4; // declares another global variable
 }
 print $c; // prints 4; scope did not end with }.
 print $b; // prints nothing; there is no initialized
           // variable by that name in this scope.
           // (The actual expression printed is null,
           // which is different from C/C++ null pointer.)
Speaking of scope, there is also the scope resolution operator, ::, but unlike in C++, where the scope resolution operator needs to be used only where the symbol is not otherwise found in the current symbol table, in PHP it is always required in the contexts where it can apply (i.e. static class methods and properties).

Types

Variables in PHP are weakly typed. The same variable may denote any type of content depending on the way it is assigned at runtime.

 $a = 5;           // $a is now an integer
 $a = 'test';      // $a is now a string
 $a = Array(5,3);  // $a is now an array containing two values
 $a = 8.3;         // $a is now a floating point value
 $a = new tester;  // $a is now an instance of a class called "tester"
 unset($a);        // $a no longer exists. If one tries to read it,
                   // a null value is received. isset($a) will return false.

 function test($a) // test is a function that takes a parameter of any type
 {
   $a *= 9;
   // If $a is numeric, multiplies it by 9
   // If $a is string, coerces it into integer and then multiplies by 9
   // Otherwise, runtime error 
   // Note that $a is an on-write copy of the parameter (see below for references)
 }
However, it is possible to force type constraints in PHP (since PHP 5.1), by the means of "type hinting":

 function Test(Array $x)
 {
   print $x;
 }
 
 Test(array(1));   // ok
 Test('x');        // error, fails at runtime (can be caught)
However, type hinting only works for user-defined classes and Arrays.

 function Test(int $x)
 {
 }
 Test(5); // Errors, excepts an instance of user-defined class "int".

Templates

PHP does not support template types like C++ does. However, because PHP does not do explicit requirements on the types of variables and parameters, there's little need either.

References

Although PHP supports references, they resemble the C++ pointers more than they resemble the C++ references.

Example code:

 $a = 5;
 $b = 7;
 $c = &$a;    // $c is now a reference to $a
 $c = 3;      // changes the value of $a
 $c = &$b;    // $c is now a reference to $b
 $c = 3;      // changes the value of $b
 $c = 'test'; // changes the value (and the type) of $b
 unset($c);   // now $c no longer exists ($b is not affected)
 $c = 9;      // declares and sets the value of $c
Function parameters may also be passed by reference. The default is to pass them by value.

 function test(&$a) // test is a function that takes a reference to a variable
 {
   $a = 4;
 }

 $b = 9;
 test($b); // sets $b to 4
 test(11); // error, requires a reference to a variable.
Note: Passing variables by value is not slow in PHP. PHP uses a lazy algorithm, which only makes a copy if the variable is written to.

Pointers

Pointers are string variables that contain the name of the referred variable or function.

 $test = 5;
 $a = 'test';
 $$a = 3;     // changes $test to 3.
The PHP manual calls them "variable variables".

The effect can be stacked:

 $test = 5;
 $a = 'test';
 $b = 'a';
 $$$b = 3; // changes $test to 3.
Note however, that variable pointers can only refer to simple variable names.

 $test = Array(1,2);
 $a = 'test[1]';
 $$a = 5;  // This does not change the contents of anything in $test.
 $"test" = 5;        // This is not valid code. It is a syntax error.
 ${'te' . 'st'} = 5; // This however is okay.

The pointer may also refer to a function (it is called a "callback" then):

 function test()
 {
   print "gruu";
 }
 test();             // This calls test() directly
 $a = 'test';
 $a();               // This calls test() indirectly
 
 call_user_func($a); // This calls test() indirectly, too
Or an object instance:

 class gruu
 {
   public $x;
   function __construct()  { $this->x = 5; }
   function show_x()       { print "x is {$this->x}.\n"; }
   function show_nothing() { print "Nothing.\n"; }
 };
 $test = new gruu;
 $a = 'test';
 $$a->x = 5;     // This sets $test->x to 5.
 print_r($test); // Displays it.
Or a method:

 $test = new gruu;
 $a    = 'show_x';

 $test->show_x(); // Calls gruu::show_x() for $test directly.
 $test->$a();     // Calls gruu::show_x() for $test indirectly.
Or a property:

 $test = new gruu;
 $a    = 'x';
 
 print $test->$a; // prints the value of $test->x.
Or an instance and a method simultaneously:

 $r = Array(&$test, 'show_x');
 
 call_user_func($r); // Calls gruu::show_x() for $test indirectly.
 // $r();            // For some reason, this is not accepted by PHP.
Or a class name and a method simultaneously:

 gruu::show_nothing(); // Calls gruu::show_nothing() without an instance, directly.
 
 $r = Array('gruu', 'show_nothing');

 call_user_func($r);   // Calls gruu::show_nothing() without an instance, indirectly.
 // $r();              // For some reason, this is not accepted by PHP.

Memory allocation and lifetime

There are no memory allocation directives in PHP. Basically, everything holds a reference count. When the reference count goes zero, the object referred will be deallocated automatically.

Example:

 class Tester
 {
   static public $num_instances = 0;
   function __construct() { ++ self::$num_instances; }
   function __destruct()  { -- self::$num_instances; }
 };
 
 function test()
 {
   $a = new Tester;
   $b = new Tester;
   echo "Number of Tester instances: ", Tester::$num_instances, "\n"; // gives 2
   unset($b);
   echo "Number of Tester instances: ", Tester::$num_instances, "\n"; // gives 1
 }
 echo "Number of Tester instances: ", Tester::$num_instances, "\n"; // gives 0
 test();
 echo "Number of Tester instances: ", Tester::$num_instances, "\n"; // gives 0
 
Beware: If there are circular references in your code, the memory will never be freed. Example circular reference code (do not use, doing this is bad!):

 $a = Array(); // create an array
 $a[] = &$a;   // $a now contains a reference to itself
 unset($a);    // leaks memory!

Command structures

If, while and for statements

C and C++:
 if(condition) statement
 if(condition) statement else statement2
 if(condition) statement else if(condition2) statement2 else statement3
 while(condition) statement
 for(expression1; expression2; expression3) statement
 do statement while(condition);
Note that statement in C/C++ has a trailing semicolon, unless it's a compound statement, which starts with a { and ends with a }. Because this is a list of syntax, those semicolons are not included; they are assumed to be included in those nonterminals.

PHP:

 if(condition) statement
 if(condition) statement else statement2
 if(condition) statement elseif(condition2) statement2 else statement3
 while(condition) statement
 for(expression1; expression2; expression3) statement
 do statement while(condition);
As you see, everything is almost the same except for elseif, which does not exist in C++. (else if is also supported.) The use of semicolons is also the same as in C++.

An alternative syntax exists also, but it is rarely used:

  if(condition): statements endif
  if(condition): statements else: statements2 endif
  if(condition): statements elseif(condition): statements2 else: statements3 endif
  while(condition): statements endwhile
  for(expression1; expression2; expression3): statements endfor 
The alternative syntax allows to include multiple statements in the structure body without the use of braces { and }.

Switch-case statement

The syntax of the switch-case statement is the same in PHP as it is in C++:
 switch(expression)
 {
   case expression1: statement break;
   case expression2: statement break;
   default: statement break;
 }
However, the expressions tested in the switch-case need not be compile-time constants. In fact, the interpreter interprets each expression sequentially at run-time. Unlike in C++, the PHP switch-case is more optimal than a sequence of if() statements only in that it avoids the evaluation of the test expression more than once.

The break statement is optional, as is in C++.

Note that because PHP lacks the concept of labels, the PHP switch-case statement cannot be used to write duff's device. Unlike in C++, the case/default statement is a rigid part of the switch syntax and not a label.

 /* This is invalid in PHP, although valid in C&C++ */
 switch(expression)
 {
   case 1:
     if(condition)
     {
   case 2: // error
       statement
     }
 }
An alternative syntax exists also, but it is rarely used:

 switch(expression):
   case expression1: statement break;
   case expression2: statement break;
   default: statement break;
 endswitch;

Foreach statement

The PHP foreach statement is a command structure that provides a way to iterate over the values and/or keys in an array without an explicit for-loop.
 foreach(array_expression as value_var) statement
 foreach(array_expression as &value_var) statement
 foreach(array_expression as key_var => value_var) statement
 foreach(array_expression as key_var => &value_var) statement
Example:
 $array = Array('a' => 'alpha', 'b' => 'beta', 'd' => 'delta');
 foreach($array as $k => $v)
 {
   print "The value corresponding to key '$k' is '$v'\n";
 }
An alternative syntax exists also, but it is rarely used:

 foreach(array_expression as value_var): statements endforeach
 foreach(array_expression as &value_var): statements endforeach
 foreach(array_expression as key_var => value_var): statements endforeach
 foreach(array_expression as key_var => &value_var): statements endforeach 
The alternative syntax allows to include multiple statements in the structure body without the use of braces { and }.

Goto, labels, break and continue

PHP does not support goto or labels.

The break and continue statements have the almost the same semantics as in C++, except for the following differences:

  • An optional number may be added after break, telling how many enclosing structures to break out of.
  • An optional number may be added after continue, telling how many levels of enclosing loops it should skip to the end of.
  • A switch statement is also considered a looping structure for the purpose of continue.

 // Find a fobrinicatable item:
 foreach($items as $v)
 {
   if(IsFobrinicatable($v))
     break; //breaks out from the foreach loop
 }
 function FeedTroll()
 {
   global $trolls, $foods;
   do {
     foreach($trolls as &$troll)
     {
       foreach($foods as &$food)
       {
         if($troll->WantsToEat($food))
         {
           $troll->Eat($food);
           break 3; // exits from three do/foreach constructs at once
         }
       }
     }
     print "Couldn't find a troll to feed.\n";
     return;
   } while(false);
   print "Done feeding.\n";
 }

Functions

In PHP, functions are identified by their name, and their name only.

Here are some key points of interest:

Examples on function declarations:

 function test1()
 {
   // this function does nothing and returns nothing
 }
 function test2()
 {
   // this function does nothing and returns 5
   return 5;
 }
 function add($a, $b)
 {
   // This function assumes the parameters
   // are of some addable type (integer or float)
   // (Passing strings coerces them into numerals before addition.)
   return $a + $b;
 }
 function multiply(&$a, $factor=1)
 {
   // $a was passed by a reference, $factor by value (and has a default of 1)
   $a *= $factor;
 }
 function test1($k) { } // this is an error, redefinition of a function
Variables declared within the function have the scope of the function.

Variables declared outside the function have the scope outside the function, but not inside the function (unless the keyword global is used).

Function declarations are always global, even if they are defined within another function.

Examples on function calling:

  test1(); // calls test1
  test2(); // calls test2, ignores return value
  $a = test2(); // calls test2, assigns return value into a variable
  test1(5,3,1); // calls test1 with extra parameters, not an error
  multiply($a);   // multiplies $a by 1 (default parameter)
  multiply($a,3); // multiplies $a by 3
  multiply(7);    // error, requires a reference to a variable
When a function is called with extra parameters, the function may use the standard library function func_get_args() and its relatives to acquire the parameters.

Function pointers

In PHP, there is no separate datatype called function pointer. Instead, string values are used to denote which function to call. Example:

 function test()
 {
   print "gruu";
 }
 test();      // This calls test() directly
 $a = 'test';
 $a();        // This calls test() indirectly
This is useful with functions taking callback functions, such as uasort():
 function mycomparer($a,$b) { return strlen($a) - strlen($b); }
 $myarray = Array('dog', 'horse', 'calf');
 uasort($myarray, 'mycomparer');
More details about pointers are shown in the chapter about pointers.

Anonymous functions (lambda functions)

Although this is not a concept that exists in C++, I thought it would be good to mention it here as well. PHP supports the concept of anonymous functions — i.e. functions that do not have any particular name in the global scope. However, because they are constructed at runtime by parsing the code provided in a string parameter, they are rather clumsy. But they still have their uses:
 uasort($myarray,
   create_function('$a,$b', 'return strlen($a)-strlen($b);')
       );
Because create_function() is just a library function instead of a language construct, if you run this code in a loop, it will parse the function body again and again at each loop, so it has really worse performance compared to named functions. The primary use of create_function() may be to create algorithmically defined functions.

Function-local static variables

Like in C++, the static keyword can be used in functions to indicate that the local variable keeps its value over successive calls.

 function Test()
 {
   static $num_calls = 0;
   ++$num_calls;
   print "Number of times Test() has been called: $num_calls\n";     
 }
 
 Test(); Test(); Test();

Data structures (Array)

The principal data structure in PHP is the Array. The Array is an associative container, which in C++ terms, resembles mostly the std::map<> and std::vector<>.

An array is a collection of pairs consisting of the key and the value. The type of the key is an integer, a float or a string. The same array may contain keys of different types. The value may be of any type. The same array may contain values of different types.

Example:

 $a = Array
 (
   5,          // same as 0 => 5
   7,          // same as 1 => 7
   3 => 11,    // key is 3, value is 11
   'x' => 'y', // key is 'x', value is 'y',
   'moo' => file_get_contents('moo.txt')
               // key is 'moo', value is the return value of that function
               // (evaluated here)
 );
 $a[1] = 13;    // changes the value corresponding to key 1 to 13
 $a['x'] = 'z'; // changes the value corresponding to key 'x' to 'z'
 $a[] = 19;     // appends to array extending the largest numeric key,
                // i.e. here it is equivalent to $a[4] = 19; 
 unset($a['x']);  // erases an array element
 $b = &$a[3];   // $b is a reference to the value corresponding to key 3
 $a = Array();  // $a is now an empty array.
 print $b;      // prints 11 (the reference held prevents
                // the previous array from being deallocated)
 unset($b);     // remove variable $b (also decrements the reference count
                // of the previous array to zero, causing its deallocation)
To iterate through the values of the array, you can use the foreach statement.

Note that the array is not sorted by default. Rather, it retains the order in which it was constructed. There are separate functions for sorting arrays.

Besides the classes (described below), there are no other data structures in PHP. Because the arrays can be nested, they can be used for the purposes of trees and other structures.

Array performance

<to be written>

Modules

Often it is useful to put commonly used code in dedicated files that do not contain a main program; they only contain functions, constants and/or classes. In C++, such files are called header files; in Pascal, they are units. In PHP, they are include files. However, in PHP, because there is no separate concept of a prototype and a definition for a function, the include files always contain also the implementation.

The basic idea is to use require_once to include the needed modules. There is also a require, which omits the check for multiple inclusion, and include_once and include, which treat a missing file as a warning instead of an error.

Technically, the require/require_once/include/include_once statements work as if they insert the included file in the exact spot where the inclusion statement was (except for turning the parser into print mode, explaining the need for <?php.)

You can also call the inclusion statement from within a function, but note that globals defined within the included file will become locals to that calling function, except for the possible functions and classes it defines.

Here is a basic example of a modular program.

Example main program

 <?php
 require_once 'hellolib.php';
 printf("%s\n", hellotext());
Example hellolib.php
 <?php
 function hellotext()
 {
   return 'Hello, world!';
 }
Note that the name of the file included may also come from a variable:
  $modulename = 'testmodule';
  if(file_exists("modules/{$modulename}.php"))
  {
    include_once ("modules/{$modulename}.php"); 
    // ... code to use module here
  }

Classes

PHP supports object-oriented programming that resembles the C++ classes.

Class syntax

 class ClassName
 {
   // This declares some properties:
   public $public_member_var;
   private $private_member_var;
   
   // This declares the constructor:
   function __construct($param = 3)
   {
     // This sets properties. Note that 
     // the $this-> is a mandatory part of the syntax.
     $this->public_member_var = $param;
   }
   
   // This declares the destructor:
   function __destruct()
   {
   }
   
   public function PublicMemberFunc()
   {
     // This calls a member function. Note that 
     // the $this-> is a mandatory part of the syntax.
     $this->PrivateMemberFunc( $this->private_member_var );
     
     // This is alternative syntax to call a member function.
     self::PrivateMemberFunc( $this->private_member_var );
   }
   private function PrivateMemberFunc($testparam)
   {
     $this->public_member_var = $testparam;
   }   
 };
 

Destructor semantics

The destructor of the class will be called when the class instance is destructed — that is, when the last reference to the class instance is removed. See the chapter about memory allocation and lifetime for details.

Instantiation and use

A class instance is created with the new keyword. Access to the class members is done through the instance variable and the -> operator (and in some cases, through the scope resolution operator ::).

 
 $instance = new TestClass;
 $instance->one_var = $instance->another_var + 1; // accesses properties
 $instance->memberfunction($a, $b); // calls a method.
 
 unset($instance); // Removes reference to the instance,
                   // also destructs the object in this
                   // example because no other references
                   // remain.

Use without instance (static methods)

In PHP classes, member methods can be called through an instance or without an instance, much like in C++.

 class StaticTest
 {
   static function ddd()
   {
   }
 };
 
 StaticTest::ddd(); // ok
It is possible also to call statically methods that are not explicitly defined static. However, if the called method accesses instance members through $this->, it will fail at runtime.

 class TestClass
 {
   function aaa()
   {
   }
   function bbb()
   {
     $this->ccc();
   }
   function ccc()
   {
   }
 };
 
 TestClass::aaa(); // ok
 TestClass::bbb(); // error, fails at runtime because $this is not defined.

Static properties

Like methods, also properties can be set static. Such properties are common to all instances of the class, instead of every instance owning a copy.

 class Tester
 {
   static public $num_instances = 0;
   
   function __construct() { ++ self::$num_instances; }
   function __destruct()  { -- self::$num_instances; }
 };
 
 $a = new Tester;
 $b = new Tester;
 
 echo "Number of tests:", Tester::$num_instances, "\n"; //displays 2
 
 unset($a);

 echo "Number of tests remaining:", Tester::$num_instances, "\n"; //displays 1

Class constants

Global constants are declared in PHP using the define keyword. However, the method to create class constants resembles more the C++ way.

 class TestClass
 {
    public const Gravity = 9.81; // Possible gotcha: Note the lack of $
    
    function test()
    {
      print self::Gravity; // $this->Gravity does not work here.
    }
 };

The difference between $this-> and self::

This table explains when it is ok to use $this-> and when to use self::.

Note that $this-> is merely an alias for $instance_var-> and self:: is an alias for class_name::. parent:: is similarly an alias for parent_class_name::.

task $instance_var-> class_name:: implied
Member properties MUST MUST NOT MUST NOT
Static properties MUST NOT MUST MUST NOT
Member methods MAY MAY MUST NOT
Static methods MUST NOT MUST MUST NOT
Class constants MUST NOT MUST MUST NOT

Here's how you read the table: "To access static methods, you MUST NOT use $instance_var->x, but you MUST use class_name::x."

"Implied" stands for the C++ way of simply using the context to deduce whether to call a global function or a member function. Unlike in C++, in PHP you MUST NOT omit the context indicator.

 class TestClass
 {
   public $testprop;
   
   function Test()
   {
     // This declares a local variable. It does not access
     // the instance property, which would be $this->testprop.
     $testprop = 5; 
     
     // This calls a global function, not $this->Test().
     Test();
   }
 };

Inheritance

 class BaseClass
 {
   public $x;
   function __construct() { $this->x = 'something'; }
   function Moo()    
   {
     print "I'm just a regular moo.\n";
     print "My x is {$this->x}.\n";
   }
 };
 class DerivedClass extends BaseClass
 {
   function Moo()
   {
     $this->x = 7;
     print "-- I'm a DerivedClass, and I moo.\n";
     print "However, if I were the BaseClass, I would say:\n";
     parent::Moo(); // calls BaseClass::Moo() explicitly
     // BaseClass::Moo(); // this is also permissible.
   }
 };
 
 $tmp1 = new BaseClass;
 $tmp1->Moo(); // calls BaseClass::Moo()
 
 $tmp2 = new DerivedClass;
 $tmp2->Moo(); // calls Derivedclass::Moo()
PHP does not do virtual functions. However, there's little need for that, because PHP does not require the function parameters or the array members to be of any specific type. You can just use the derived class object where you would use the baseclass pointer in C++.

Like in Java, it is possible to define an entire class or some class methods final. This indicates that the class, or the particular method, cannot be extended through inheritance, and it will be enforced by the interpreter.

 final class aaa  // this class may never be extended
 {
 };
 class bbb
 {
   final function moo() // this method may never be overloaded
   {
   }
 };

Abstract methods (i.e. purely virtual methods)

It is possible to declare methods that have no implementation, and which must be overridden in derived classes.

 class BaseClass
 {
   abstract protected function Moo();
 };
 class DerivedClass extends BaseClass
 {
   public function Moo()
   {
     print "Moo!\n";
   }
 };
 
 $d = new DerivedClass;
 $d->Moo();
 $d = new BaseClass; // error, BaseClass contains abstract methods.
There is another way to create abstract methods, through a method called reflection. It involves creating an interface that describes what a class should implement, and declaring that a class implements that interface.

 interface GraphicObject
 {
   function Draw(&$surface);
   function Clear();
 };
 
 class Line implements GraphicObject
 {
   private $x1, $y1, $x2, $y2;
   function Clear() { $x1=$y1=$x2=$y2=0; }
 };
 
 $n = new Line; // error, Line does not implement Draw().
An interface never implements anything; it just shows what should be implemented in order to conform to the interface.

Private and public members

In C++, private and public members are created in a class by the means of sections. In PHP, the publicness/privateness is specified individually for each member function and member variable.

 class TestClass
 {
   public function PublicFunc() { }
   private function PrivateFunc() { }
   public $publicvar;
   private $privatevar;
   
   protected function ProtectedFunc() { }
   
   function AlsoPublicFunc() { }  // public is the default.
 };

The class instance is not a pointer

Even though the instance members are accessed through the -> operator, which looks like pointer access to C++ users, the instance variable is not a pointer, and it is not a reference. It is an object.

Well, technically, internally these things are implemented through a myriad of pointers, but it is not a pointer in the way it would be in C++. You can't change it to point to something else, without it meaning changing the contents of the variable and possibly destructing the class instance in the process. Similarly, the word new does not mean memory allocation in this context. It is just part of the syntax that creates instances — it is equivalent to an explicit constructor call in C++.

 $stringvar = 'aiueo';
 $instance  = new TestClass;
 printf("%s\n", gettype($stringvar)); // outputs "string"
 printf("%s\n", gettype($instance));  // outputs "object"

Method pointers

In PHP, there is no separate datatype called a method pointer. But there is a callback mechanism, which is explained in detail in the chapter about Pointers.

Other things of interest

The Classes and Objects section of the PHP manual points out many other features supported by PHP classes, that don't exist in C++. Most importantly perhaps, the magic methods, which will not be documented here for now.

Exceptions

PHP exceptions work in a similar manner to C++ extensions.

 try
 {
   $error = 'Always throw this error';
   throw new Exception($error);

   // Code following an exception is not executed.
   echo 'Never executed';
 }
 catch (Exception $e)
 {
   echo 'Caught exception: ',  $e->getMessage(), "\n";
 }

 // Continue execution
 echo 'Hello World';

Useful reading

The official PHP site contains a searchable online manual that is very invaluable in all PHP coding even when you are experienced. This is especially true because the standard library in PHP is quite large, and it is difficult to remember the parameters to all the functions.


Last edited at: 2010-02-16T21:18:13+00:00