Appendix A. Crash Course on PHP and Object-Oriented Programming

This appendix is designed as a quick-start guide for PHP and object-oriented programming. Here we try to give you the minimum you need to get started with Joomla! programming. Our focus is on short, practical explanations. There are many online tutorials and books on these subjects that you are encouraged to explore for more in-depth information about any of these topics.

PHP File Structure

PHP is an interpreted language, so the .php files are both the source code and the executable code. These text files can be edited with any text editor. Note that for Joomla, we use UTF-8 encoding for all text files.

PHP-Only Files

Most PHP files in Joomla only contain PHP code. These files start with an open PHP tag of <?php and the remainder of the file is PHP code. Note that these files normally do not include a closing PHP tag (?>). The closing tag is not needed and in fact can cause problems if there are any spaces after the closing tag. So it is preferred to omit the closing PHP tag for PHP-only files.

Files with PHP and HTML

Layout and template index.php files in Joomla contain a mix of PHP and other HTML elements. In these files, the PHP code is contained inside PHP tags (<?php . . . ?>). It is customary to use the PHP alternative syntax in mixed files, as described later in this appendix.

PHP Syntax Basics

White Space

White space (spaces, tabs, carriage returns, line feeds, and so on) is ignored by the PHP interpreter, so formatting is important only for readability. For example, the line

$a=$b+$c;

is equivalent to

$a = $b + $c;

although the second is preferred because it is more readable. Also, a single line of code can take up more than one line of text, for example:

$a = $b + $c
   + $d;

Important Characters

Every PHP statement ends with a semicolon (“;”). Curly braces (“{” and “}”) are used to enclose code blocks. Code blocks are used to designate the start and end of code for classes, functions (also referred to as methods), if statements, switch statements, and loops. Parentheses are used for the conditional statement for if, switch, and while statements.

Comments can be entered as any characters after “//” in a line of code. Comments beginning with “/*” and ending with “*/” can span more than one line of code. For example,

/* This is a comment
   And more comments
*/
// This is a comment
$a = $b + $c; // this is another comment

The dash plus greater than (“->”) is used to invoke a class method. For example,

$name = $db->loadResult();

calls the loadResult() method of the object in the variable called $db. Double colons (“::”) do the same thing for static methods. For example,

$user = JFactory::getUser();

Table A.1 shows the common uses of special characters in PHP.

Table A.1. Special Characters in PHP

Image
Image

Common Operators

Arithmetic and String Concatenate

PHP uses +,–,*,/ for addition, subtraction, multiplication, and division. Period or dot (.) is used to concatenate (join together) two strings. For example,

$a = 'dog';
$b = 'cat';
$c = $a . $b; //  $c is 'dogcat'

Double “++” means add one ($a++;). Plus + “=” (“+=”) means increment a value by another value. Dot + “=” (“.=”) means concatenate. For example,

$a += $b; // same as $a = $a + $b
$c .= $d; // same as $c = $c . $d

Setting Variable Types

To set or cast a variable type, use the type inside parentheses as the operator. For example,

$a = (string) $b; // $a is $b converted to a string
$c = (int) $d; // $c is $d converted to an integer

Specific rules apply when converting values from one type to another. For example, when converting strings to integers,

$int = (int) 'abc'; // $int is zero
$int = (int) '123abc'; // $int is 123

If the first group of letters can be interpreted as an integer, that is the value used. Otherwise, the value is zero.

Logical Operators

It is important to remember that a single equals assigns a value to a variable (and returns this value), whereas a double or triple equals is a logical equals.

$a = $b; // assigns value of $b to $a
($a == $b) // true if $a is equivalent to $b
($a === $b) // true if $a is the same value and the same type as $b

Use ! to make this a not compare—for example, ($a != $b) or ($a !== $b). Use < or > for less than or greater than—for example, ($a < $b). Use <= for less than or equal and >= for greater than or equal.

Connect logical expressions with || or OR for logical or. Use && or AND for logical and. For example,

($a == $b || $c == $d)
($a == $b OR $c == $d)
($a == $b && $c == $d)
($a == $b AND $c == $d)

If Statements

If statements are the most common way to execute code conditionally. The basic syntax is as follows:

if ($a == $b)
{
  // do these statements if condition is true
   $c = d;
   $e = $f;
}
else
{
// otherwise do these statements
   $g = $h;
   $i = $j;
}

You don’t need an else block. You can use elseif to add conditions to subsequent code blocks. For example,

if ($a == $b)
{
   $x = $y; // if condition is true
}
elseif ($c == $d)
{
   $g = $h; // only if not ($a == $b) and ($c equals $d)
}

You can have as many elseif blocks as you like.

Caution: Don’t use single equals instead of the double equals to compare values. Single equals assigns values and returns the assigned value. For example, consider the following code:

      $a = 'dog';
      $b = 'cat';
      if ($a = $b) // used "=" instead of "==" by mistake!
      {
         echo "true "; // result is always true
         echo $a . " "; // $a is now 'cat'
      }

Here we accidentally used a single equals instead of double equals. The single equals does two things: (1) assigns the value of $b to $a and (2) returns the new value of $a. So $a = $b returns cat, which evaluates to a boolean true. Therefore, the if statement is true.

We can use a single equals inside an if condition when we are executing a method and assigning the results to a variable. For example, the loadResult() method of JDatabase returns a value or a null value if the query result is empty. So we can use the return value of loadResult() inside an if condition as follows:

if ($link = $db->loadResult()) {// true if query returns a non-zero result

This code is a bit tricky. We are really doing three things here: (1) executing the loadResult() method of JDatabase, (2) saving that value to the $link variable, and (3) using that value as the condition for the if statement. We could write the equivalent code in two lines as follows:

$link = $db->loadResult();
if ($link) { // link is true if query returns a result

There is one important caution in this. If the query could return a zero as a valid result, this code will not work as expected. This is because zero will evaluate to false in the if condition. In this case, we could use the following code to fix the problem:

$link = $db->loadResult();
if ($link !== null) { // only false if query result is null

You can use the PHP ternary operator to substitute for some simple if statements, as follows:

$a = ($b == $c) ? $d : $e; // returns $d if true, $e otherwise

This assigns $a the value of $d if the condition is true and $e otherwise.

Switch Statement

The switch is a good structure if you need to execute different code blocks based on the value of one expression. The basic syntax is as follows:

switch ($a)
{
   case 'abc':
      $b = $c; // do these statements if $a equals 'abc'
      break;
   case 'def':
      $d = $e; // do these statements if $a = 'def'
      break;
   default:
      $f = $g; // do this if none of the above
      break;
}

The break statements are necessary for the first two cases. For example, if the first break statement was omitted, when $a equals 'abc', the statement $d = $e; would also be executed.

Looping Statements

Foreach Loops

Foreach loops are the simplest way to loop through an array. The code block in the loop is executed once for each element in the array. For example, if $groups is a simple array:

foreach ($groups as $group) // groups must be an array!
{
   echo $group; // $group contains the nth array element;
   // do more stuff as needed
}

In this example, if $groups is not an array, you will get a PHP Warning. It is OK if the array is empty. In that case, the loop will be skipped.

You can use foreach loops with associative arrays by specifying the variables to use for each key and each value. For example,

$assoc = array('name' => 'Fred', 'age' => 29);
foreach ($assoc as $key => $value) {
   echo $key . ': ' . $value . " "; // prints out each key/value pair
}

Here, $key will hold the key for each array element and $value will hold the value for each element.

For Loops

For loops allow you to perform a loop n times. For example:

// start at 0, add 1 to $i each time, continue until condition is not true
for( $i = 0; $i < $len; $i++)
{
   echo $i; // will be executed until $i == $len
}

Here we use $i as our loop counter and increment it by one using $i++. We execute the loop until the condition $i < $len is not true.

Do/While Loops

Do/while loops allow you to process a code block until a condition is no longer true. One type executes a code block first and then checks a condition to see whether to repeat it. For example,

do
{
   // code block is done once and then will be repeated
   // as long as while condition is true
   // code in code block must eventually made condition false!
}
while ($a != $b);

The second type checks the condition first, before executing the code block. For example,

while ($a != $b)
{
   // code block will be executed only if condition is true
   // code in code block must eventually made condition false!
}

In both cases, it is important to understand that executed code block must eventually make the condition false. Otherwise, you will get an infinite loop condition.

Continue Command

The continue command is used to skip the remainder of the loop’s code block for one iteration of the loop. For example,

foreach ($groups in $group)
{
   if ($group = 'Public') {
       continue; // Skip 'Public' group
   }
   echo $group;
}

Alternative Syntax

In files containing only PHP code, all the code is normally placed in one PHP element. In layout files, however, we mix PHP elements with other HTML elements, and we will have multiple PHP elements in the file. Depending on the situation, we may wish to output HTML elements in the code blocks of if statements and loops.

In this situation, it is generally preferred to use the alternative syntax for if statements and loops. This lets us output HTML elements outside of PHP elements, so we don’t need to put HTML elements in quotation marks. It also avoids having a PHP tag that contains only an open or close bracket (for example, “<?php }>”), which is very easy to miss when looking at the code.

Table A.2 shows examples of the standard and alternative syntax. In the alternative syntax, note that PHP comments must be put inside PHP elements.

Table A.2. Alternative Syntax Examples

Image

Also, although white space characters are not important inside PHP elements, they are important outside these elements. For example, the following two lines of code will produce different results:

<p>This is a <?php echo 'test'; ?></p>
<p>This is a <?php echo 'test'; ?></p>

The first one has a space between a and test. The second one does not.

Variables

All PHP variables start with a dollar sign followed by a letter or underscore (for example, $myvariable or $_myvariable). You can use numbers and dashes after the letter or underscore. Variable names are case sensitive, so $myvariable and $myVariable are different. It is very easy to mistakenly reference a variable using different case. That is one reason why it is good to be consistent about naming variables (for example, using “camel casing,” like $myVariableName).

Declaring variables

You don’t declare variables in PHP, but you should assign them a value before you use them in an expression. Otherwise, you will get a PHP warning.

Variable Scope

In general, variables are defined—are in scope—only in the code block where they are set. For example, if a variable is set in the outermost code block of a script, it will be in scope for the rest of that script, including in contained code blocks such as if statements and loops. If a file is included using the include or require commands, variables will stay in scope in the included files. This is why variables from a view are still in scope when we use the loadTemplate() method to load layout files.

When we are inside a class method or a function, only variables local to that method or function are in scope.

Arrays

Arrays can be created with or without initial values. The following code creates an empty array:

$emptyArray = array();

This code creates an array with two values:

$simple = array('zero', 'one'),// $simple[0] = 'zero', $simple[1] = 'one'

Arrays can be indexed or associative. Indexed arrays use the integers 0, 1, 2 etc. to access the elements. For example, the following code accesses the first element in the previous example (note that the first element is 0, not 1):

echo $simple[0]; // will print 'zero'

Associative arrays are stored in key-value pairs. This example creates an associative array:

$assoc = array('name' => 'Jim', 'age' => 29);

To access the values, use the following:

echo $assoc['name']; // prints Jim
echo $assoc['age']; // prints 29

To add a new element to an indexed array, use [], as follows:

$simple[] = 'new value'; // adds to end of the array

To add a new element to an associative array, add a new key, as follows:

$assoc['telephone'] = '123-4567';

Use the unset command to remove an element from an array. For example,

unset($assoc['age']) // removes 'age' element

Array elements can be any type, including objects or other arrays. For example, this code creates an indexed array where the elements are associative arrays:

$person1 = array('name' => 'Jim', age => 29);
$person2 = array('name' => 'Jill', age => 27);
$people = array($person1, $person2);

In this example, we access an element of the inner array as follows:

echo $people[0]['name']; // prints Jim

Here, $people[0] is the first associative array, so $people[0]['name'] gives the name element of the associative array.

Working with Arrays

Here are some examples of working with arrays with the count(), is_array(), and isset() commands.

$count = count(array(1,2,3)); // 3: the number of elements in the array
is_array($a) // returns true if $a is an array, false otherwise
isset($person1['name']) // true if element exists, false otherwise

See http://php.net/manual/en/ref.array.php for more information about array functions.

Strings

Strings are variables that contain characters, including text, numbers, and symbols. PHP has a number of built-in methods for working with strings. Some of these methods do not work correctly with UTF-8 character sets. The JString class (libraries/joomla/utilities/string.php) contains comparable methods that work correctly with UTF-8 characters. For this reason, you should use the JString methods when operating on strings that might contain UTF-8 characters.

Here are a few examples:

$pos = JString::strpos('abcd', 'bc'), // should be 1
$len = JString::strlen('abc'), // should be 3
$replaced = str_replace('dog', 'cat', 'I love dogs.'), // I love cats.

See http://php.net/manual/en/ref.strings.php for more information about PHP string functions and http://api.joomla.org/Joomla-Platform/Utilities/JString.html for more information about the JString class.

Constants and Current Directory

We can define constants in PHP using the define statement. For example,

define('_JEXEC', 1);

defines the constant _JEXEC with a value of 1. Recall that this constant is used in almost all Joomla files to make sure we are running inside a Joomla application. Once defined, constants cannot be changed. By convention, constants are defined in all uppercase letters.

PHP includes some predefined “magic” constants. One of these, __FILE__, is equal to the full path name of the current file. PHP also includes a function called dirname() that returns the name of the directory for any file (in effect, the part or the full-path name before the last slash).

We can use __FILE__ and dirname() together to get the directory of the current file. For example, the code

define('JPATH_BASE', dirname(__FILE__));

defines the constant JPATH_BASE as the directory name of the current file.

PHP also includes methods called file_exists() that check whether or not a file exists in the file system. See http://php.net/manual/en/ref.filesystem.php for documentation for the file system commands in PHP.

Functions and Methods

Most programming code in Joomla is contained in functions. Most Joomla functions are part of classes. In some cases, functions are created stand-alone and are not part of a class.

Functions that are inside classes are often referred to as methods (to be consistent with other object-oriented programming languages). Many people use the words function and method interchangeably. Note that there is no keyword in PHP for method, only for function.

Function Structure

A function has the following structure:

function <function name> (<function arguments, if any>)
{ // start function code block
   <function code, if any>
} // end function code block

An example of a simple function is as follows:

   public function setLastVisit($timestamp = null)
   {
      // Create the user table object
      $table = $this->getTable();
      $table->load($this->id);
      return $table->setLastVisit($timestamp);
   }

The function’s access modifier is public, which means that it can be called from any class. It has one argument, called $timestamp. The argument has a default value of null, so this method can be called without any arguments. If no default was supplied, you would get an error if you tried to call it with no arguments.

The function has three lines of code. The last line uses the return command to return a value. This means that this function can be called in an assignment statement—for example,

   $x = $user->setLastVisit($myTimestamp);

In this case, the value returned by the function will be saved in the variable called $x. The number and order of the function’s arguments are called the function or method signature.

Function Variable Scope

Variable names inside a function only relate to that function. In the previous example, we call the setLastVisit() method passing the variable $myTimestamp. Inside the function, $myTimestamp is not defined. Instead, that value is known by the name $timestamp. When the function is completed, the variable $timestamp is no longer defined.

We could, if we like, use the same variable name when we call a function. In this case, even though the name is the same, it is really two different variables with two different scopes. One is defined outside the function, the other inside.

Passing Variables by Reference


Warning

This is a potentially confusing subject. When you pass a variable to a function as an argument, the normal behavior is that the variable passed is local to the method. This means that if the method changes the value of that variable, the change is lost when the function finishes.


If you pass a variable to the function by reference, using the “&”, if you change the variable in the function, the changes are visible to the code that called the function.

For example,

function pluralValue($string) {
   $string .= 's';
}
function pluralReference(&$string) {
   $string .= 's';
}
$a = 'cat';
pluralValue($a);
echo $a . " "; // $a is still cat
pluralReference($a);
echo $a . " "; // $a is now cats

In pluralValue() the change we make to the local variable is lost when we return from the function. In pluralReference(), because we include the & in the function signature, changes to the local variable are visible to the calling code.

Including Files and File Types

In a large code base like Joomla, it is necessary to organize the code into multiple files. It is important to understand the different types of PHP files, how they are included into the running program, and what happens when they are included. Almost all Joomla files fall into one of three categories, as follows:

• Class declaration

• Function declaration

• Simple script

Class Declaration Files

In object-oriented programming, the normal way to organize files is to have one file per class. The great majority of files in the Joomla content management system (CMS) and platform do exactly that. They are class files that declare a single class. The structure for a class declaration file is as follows:

class <class name>
{ // start class code block
<class fields, if any>
<class methods, if any>
} // end class code block

Normally, there is a line like one of the following at the start of each file:

defined('JPATH_PLATFORM') or die; // used for Platform files
defined('_JEXEC') or die; // used for CMS files

These ensure that this file is being executed inside Joomla. Often this is followed by one or more include or import statements to include the required class files for this class.

When class declaration files are included using include, require, jimport, or JLoader::register(), the class and its methods are added to working memory but no programming code is executed. The only change is that the class, including its methods and fields, are now available for use by the program that included the file.

Function Declaration Files

A few Joomla files declare functions instead of classes. Examples of this are templates/system/html/modules.php, which provides the basic module chrome functions, and components/com_content/router.php, which provides the ContentBuildRoute() and ContentParseRoute() functions.

These files can only be included by the include or require commands (including include_once and require_once). They do not declare classes, so they cannot be included using the jimport or JLoader::register() methods.

Like class declaration files, function declaration files do not execute any code when they are included. They simply add the declared functions to the working memory so the calling script has them available to call.

Simple Script

Simple script files contain a series of PHP statements. Examples in Joomla include the index.php files for the front end, the back end, and templates. Also, layout files are simple script files.

Like function declaration files, simple script files don’t contain class declarations so they can only be included using the require or include commands (again including require_once and include_once). Unlike the other file types, when simple scripts are included in the running program, their statements are executed immediately. Also, any variables that are in scope at the point where a simple script is included are still in scope inside the script.

Mixed Files

It is also possible to mix simple script statements with function or class declarations in a single file. In this case, the declared function or class is added to working memory and the statements outside the code blocks are executed immediately. These files must be included using include or require commands (including include_once and require_once).

Including Files

The following commands can be used to include other files in the currently running Joomla program:

include: Includes the file. Works for any type of file. Will cause an error if the included file declares a class or function that has already been declared. No error is caused if the file to include cannot be found.

include_once: Same as include except that it checks that this file has not already been included. This can be slow on some servers. For class files, use jimport or JLoader::register() if possible.

require: Same as include except that it causes an error if the file cannot be found.

require_once: Same as require except that it doesn’t try to include a file that has already been included. Again, this can be slow on some servers, so jimport or JLoader::register() are preferred if applicable.

JLoader::register(): Preferred way to load class files. Requires that you know the class name and the file name. Uses the PHP auto-loader mechanism to improve performance.

jimport: Simple way to call JLoader::register() but requires that the file and class names follow the Joomla naming convention. This is the most common way to include Joomla platform files.

Object-Oriented Programming Basics

Joomla is designed using object-oriented programming concepts and design patterns. Here is a brief introduction to object-oriented programming.

Classes and Objects

Classes are the building blocks for programs. A class can be thought of as a template for creating objects of that type. For example, we use the JDocumentHTML class to create an object variable (for example, a variable called $doc) that is a JDocumentHTML object.

Classes typically have fields and methods (also called functions). We can call a method using the syntax

$x = $doc->getHead();

where getHead() is method name of the class. We can access a class field with similar syntax—for example,

$x = $doc->template;

where $template is a field of the class. Notice that we drop the $ when we access the field.

Constructor Method

Most classes define a special method called __construct(). This method is called automatically when a new object of this type is created. It contains code needed to initialize an object—for example, to set default values for an object’s fields.

Creating Objects

Before we can use an object, we must create it. Three techniques are used to create most objects in Joomla:

JFactory::get<name>(): The JFactory class is used to create commonly used global objects, including JApplication, JConfig, JDate, JSession, JLanguage, JDocument, JUser, JCache, JAcl, JDbo, JMailer, JFeedParser, JXMLParser, JXML, JEditor, and JURI. JFactory should normally be used for all objects of these types. For example, the following gets the current JApplication object:

        $app = JFactory::getApplication();

getInstance(): Many Joomla classes provide a getInstance() method. This method typically checks to see if an object of this type already exists. If so, it returns the already created object. If not, it returns a new object. For example,

        $client = JTable::getInstance('Client','BannersTable'),

new: This is used to create objects other than ones that use JFactory or getInstance(). This creates a new instance of an object by calling the object’s constructor. Some class constructors have optional or required arguments. For example,

        $registry = new JRegistry();

Note that the parentheses are optional if no arguments are passed to the constructor.

Standard Class

PHP has a class built in called a standard class. You can create an object of this type as follows:

$person = new stdClass(); // with or without the parentheses

The standard class has built-in methods to create fields. For example, the following code

$person->name = 'Bob';
$person->age = 15;

creates name and age fields and sets their values. We can retrieve the values the same way—for example,

$age = $person->age;

Standard classes are convenient ways to store a list of attributes for an object.

Extends and Inheritance

Inheritance is a fundamental concept of object-oriented programming. You can create a new class as a subclass (or child class) of another class using the extends keyword. For example,

class JDocumentHTML extends JDocument

This means that JDocumentHTML is a subclass of JDocument. So JDocumentHTML automatically inherits all fields and methods of JDocument. For example, if we wanted to create a subclass that was similar to the parent class, but only needed one new method, we would only have to write the one new method. All the other methods will be available. It is as if we copied and pasted all the parent class methods into the child class, except that we don’t have to maintain two copies of the code.

For example, JSite is a subclass of JApplication and therefore inherits all the methods of JApplication. JApplication has a method called getInstance(). If we look at the code for JSite (includes/application.php), we do not see a getInstance() method. However, we can use the getInstance() method with a JSite object. When we do, PHP knows to look for the method in the parent class.

Joomla has many examples of classes that extend other classes. Also, classes can be subclasses of subclasses. For example, JApplication is a subclass of JObject. So JSite has a parent class (JApplication) and a grandparent class (JObject). Class hierarchies can be of any depth.

Method Overriding

When we create a subclass, we can add new methods and fields. We can also change existing methods and fields. This is called overriding. All we do to override a method is to create a method in the subclass with the same name the parent class uses. When we do this, the method in the subclass must have the same access modifier (public, protected, private) and the same method signature (arguments) as the parent class method.

The keyword parent has a special meaning. When we override a method, we can use parent::<method name> to call the method from the parent class. For example,

  parent::loadConfiguration($data);

This can be useful when the subclass method is similar to the parent method. In this case, we might be able to code only the differences and then call the parent’s method.

Public, Protected, Private Modifiers

When we create class methods and fields, we can designate them as public, protected, or private:

• Public means they can be accessed from any other class or script.

• Protected means they can be accessed only from this class or from subclasses of this class.

• Private means they can be accessed only from this class.

Static Methods, Fields, and Variables

Static methods are called from the class itself, not from an object. For example,

$now = JFactory::getDate();

The method getDate() is a static method and is called using the class name + “::” (two colons). Static methods are declared with the static keyword. For example,

public static function getDate($time = 'now', $tzOffset = null)

A static field is a field that is declared with the static keyword and called from the class. For example,

public static $format = 'Y-m-d H:i:s';

If a static field is accessed from outside its class, the following syntax is used: <class name> + :: + <variable name including the “$”>. For example,

$format = JDate::$format;

$this, self, and parent

The special variable $this is used to refer to the current object inside its class. For example,

$model = $this->getModel();

calls the getModel() method of the same class. And the code

$this->filter = $options['filter'];

assigns a value to the filter field of the class from within the same class.

The keyword self is used to call a static method or access a static field of the current class. For example,

$identities = self::getGroupsByUser($userId);

calls the static getGroupsByUser() method of the JAccess class from within that same class. And the code

return self::$_buffer;

returns the value of the static field $_buffer in JDocument from within that class.

The keyword parent calls a method or accesses a field in the parent class. For example,

parent::display();

calls the display() method of the parent class. And the code

return parent::$_buffer;

returns the value of the field $_buffer from the current class’s parent class.

It is important to understand that parent literally means “any super class,” including parent, grandparent, and so on. For example, if class A is the parent of class B and B is the parent of C, then A is the grandparent of C. Say that the field $myfield and method myMethod() are defined in class A and not in class B or C.

In this example, if we are in class C and invoke the parent method using parent::myMethod(), this will execute the code in class A. And if we invoke the field with parent::$myfield, it will pull the field from class A.

Simple Debugging

It is sometimes helpful to be able to look inside a running program and see the values of variables. As discussed in Chapter 2, you can use an integraded development environment (IDE) such as Eclipse or Netbeans with a debugger to do this. If that is more complex than you need, you can also accomplish the same thing by inserting temporary test code into your PHP files.

Viewing Defined Variables

One way to see all variables in scope at a point in the program, along with their set values, is to insert the following code at the desired point in the program:

var_dump(get_defined_vars());
die;

The get_defined_vars() function returns an array of all variables defined at that point in the program. The var_dump() function dumps one or more variables in human-readable format. The die command stops the program at that point so you can see the results in the browser window.

These commands together will stop the program and print out all the variables defined (in scope) at that point in the program along with their values.

Viewing the Stack Trace

Another important part of debugging is answering the question “How did we get here?” Recall from Chapter 2 that the programming “stack” shows the sequence of function calls that got us to the current point in the program (for example, index.php called the dispatch() method of JSite, which in turn called the renderComponent() method of JComponentHelper, and so on).

We can print the stack at any point with the following code:

var_dump(debug_backtrace());
die;

Note that the trace prints out with the current program on top and the original calling program (index.php) on the bottom.

Some Advanced Code Techniques

Most of the code in Joomla is understandable with the basics covered so far. A few advanced techniques are used in some places in the code base.

Using || Instead of If Statements

In a few places in Joomla, you will see something like the following:

$lang->load('tpl_'.$template, JPATH_BASE, null, false, false)
   ||   $lang->load('tpl_'.$template, JPATH_THEMES."/$template", null, false, false)
   ||   $lang->load('tpl_'.$template, JPATH_BASE, $lang->getDefault(),false, false)
   ||   $lang->load('tpl_'.$template, JPATH_THEMES."/$template", $lang->getDefault(), false, false);

This is executing a series of $lang->load() methods separated by the logical or operator ||.

There are two keys to understanding this code: (1) $lang->load() returns true on success and (2) the or operator (||) stops processing after the first boolean true has been returned. This means that as soon as one of the load() methods succeeds, the rest of the code (after the ||) is skipped.

We could accomplish the same result with a series of if statements. However, the code would be longer and more complex.

Method Chaining

PHP now allows method chaining. This means that when a method returns an object, that object can be used to run another method. A simple example is as follows:

if (!JFactory::getUser()->authorise('core.admin')) {

Here we need to check the user’s permissions, so we need a JUser object. We get that with the JFactory::getUser() method. Then we use the results of that method (a JUser object) to call the authorise() method.

We could use the following two lines instead:

$user = JFactory::getUser();
if (!$user->authorise('core.admin')) {

However, if we don’t need the $user variable for anything else in this method, we can save that line of code (and have one less variable) by using method chaining.

PHP Magic Methods

PHP includes a number of “magic” methods that automatically get called at predefined points in programs. All magic method names begin with double underscore (“__”). One example is the __construct() method. This automatically is called whenever we use the new command to create a new object. For example,

$r = new JRegistry();

Another example of a magic method is the __call() method. If it is defined in a function, this method is executed any time an inaccessible method is called. An inaccessible method might be one that is not defined in the class (or its parents) or whose access modifier (for example, private or protected) does not permit it to be called.

One way the __call() method is used is to make aliases for existing methods. For example, in the JDatabase class, we have two methods called quote() and quoteName(). We would like to be able to use alternative names of q() for quote and qn() and nq() for quoteName(). This is implemented with this _call() method in JDataBase:

public function __call($method, $args)
{
   if (empty($args)) {
      return;
   }

   switch ($method)
   {
      case 'q':
         return $this->quote($args[0], isset($args[1]) ? $args[1] : true);
         break;
      case 'nq':
      case 'qn':
         return $this->quoteName($args[0]);
         break;
   }
}

This method is called any time we try to call a method that doesn’t exist in the class. The name of the method is in the first argument ($method) and the remaining arguments for the call are in the array $args.

First, we check that there are arguments. Both quote() and quoteName() must have arguments, so we are not interested in any methods without arguments. So we just return and do nothing in that case.

Then we do a switch command on the method name. If it is q, we call the quote() method passing the first argument and true if there is a second argument. If the method name is 'nq' or 'qn', we call quoteName() passing the first argument.

In this way, we can use q() for quote() and qn() or nq() for quoteName(). Note that we could also provide method aliases by defining methods for these aliases and then running the “real” method inside the alias method. For example, we could define q() as follows:

public function q($text, $escape = true) {
   return $this->quote($text, $escape);
}

Variable Class and Method Names

Another advanced technique used in Joomla is using variables for class and method names. For example, in the JController execute() method, we see this line of code:

$retval = $this->$doTask();

The method name being executed is in the variable $doTask. For example, if $doTask is “display,” then the display() method is called.

One important advantage of this technique is that we don’t have to know in advance the names of all the methods we might want to execute. As long as the method exists, we can use any name we like.

Regular Expressions

Regular expressions are used to do advanced search or search-replace operations on strings. In Joomla, we use regular expressions in a number of places—for example, to filter for special characters, find and replace the “jdoc:include” tags in the document object, and modify internal links when using search-engine-friendly URLs.

The two most common commands in Joomla that use regular expressions are preg_match and preg_replace. As you might guess, preg_match finds matching patterns in a string, and preg_replace does a find-replace in strings.

An example of preg_match is as follows:

$result = preg_match('#.(?:bmp|gif|jpe?g|png)$#i', $url);

Here we test whether the variable $url ends with a period followed by bmp, gif, jpe, jpeg, or png. If so, $result will be true. Note that we could do the same thing with a number of if statements, but it would take a lot more code.

An example of a preg_replace is as follows:

$result = (string) preg_replace('/[^A-Z_]/i', '', $source);

Here we filter a string called $source for nonletter characters. If we find anything other than a letter or underscore, we replace it with an empty space (which in effect removes it from the string). Again, this could be accomplished with different commands, but with more code.

Using regular expressions is a large, complex subject and beyond the scope of this book. Fortunately, there are a number of online resources to help you learn about them.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.75.217