PHP tips and tricks
  Skien, Norge, June 7th 2007
Agenda

  Tips and Tricks from PHP
     No need for anything else than standard distribution
     All for PHP 5
     ( but lots of it is also valid in PHP 4 )

     The month of PHP functions
Who is speaking?

    Damien Séguy
       Nexen Services, eZ publish silver partner for hosting
       PHP / MySQL services
       Redacteur en chef of www.nexen.net
       Phather of an plush Elephpant
    http://www.nexen.net/english.php
Nod when you know about it
Random stuff


  rand() and mt_rand()
  array_rand() : extract info from an array
    extract keys!

  shuffle() : shuffle an array before deal
  str_shuffle() : shuffle a string
Random stuff

                                Array
 <?php                          (
 $a = range('a','d');               [0]   =>   c
 shuffle($a);                       [1]   =>   d
                                    [2]   =>   b
 print_r($a);                       [3]   =>   a
                                )
 print_r(array_rand($a,3));     Array
                                (
 print str_shuffle('abcdef');       [0]   => 0
 // eabdcf                          [1]   => 1
 ?>                                 [2]   => 3
                                )
Arrays combinaisons

       array_combine() : turn two arrays into one
         Inverse to array_keys() and array_values()
 <?php
 $a = array('green', 'red', 'yellow');
 $b = array('avocado', 'apple', 'banana');
 $c = array_combine($a, $b);
                     Array
 print_r($c);
                     (
 ?>
                         [green] => avocado
                         [red]    => apple
                         [yellow] => banana
                     )
Arrays combinaisons

         array_combine() : turn two arrays into one
         PDO::FETCH_KEY_PAIR :
         combine 2 columns in a hash

 <?php
 $html = file_get_contents("http://www.php.net/");

 //'<a href="http://php.net">PHP</a>';
 if (preg_match_all(
 '#<a href="(http://[^"/?]+/).*?>(.*?)</a>#s', $html, $r)) {
     $liste = array_combine($r[2], $r[1]);
 }
 print_r($liste);

 ?>
Arrays as SQL

        array_count_values() : makes easy stats
        Works like a GROUP BY and COUNT()

<?php
   $array = array(1, "hei", 1, "takk", "hei");
   print_r(array_count_values($array));
?>
                                     Array
          sort       r   u           (
                     r   u               [1] => 2
                                         [hei] => 2
           k    k   kr  uk
                                         [takk] => 1
           a    a   ar  ua           )
Arrays as SQL

                                        Array
                                        (
     array_multisort() : sort several       [0]   =>   2
     arrays at once                         [1]   =>   3
     Works like a ORDER BY                  [2]   =>   4
                                            [3]   =>   5
<?php                                   )
$ar1 = array(5,4,3,2);                  Array
$ar2 = array('a','b','c','d');          (
array_multisort($ar1, $ar2);                [0]   =>   d
array_multisort($ar1,                       [1]   =>   c
           SORT_ASC,SORT_STRING,            [2]   =>   b
           $ar2);                           [3]   =>   a
?>                                      )
Fast dir scans



   scandir(‘/tmp’, true);
     Include name sorting

     Replace opendir, readdir, closedir and a loop!

   glob(‘*.html’);
   Simply move the loop out of sight
Fast dir scans

Array
(
    [0]   =>   sess_um8rgjj10f6qvuck91rf36srj7
    [1]   =>   sess_u58rgul68305uqfe48ic467276
    [2]   =>   mysql.sock
    [3]   =>   ..          <?php
    [4]   =>   .           print_r(scandir('/tmp/', 1));
)                          print_r(glob('/tmp/sess_*'));
Array                      ?>
(
    [0]   => /tmp/sess_um8rgjj10f6qvuck91rf36srj7
    [1]   => /tmp/sess_u58rgul68305uqfe48ic467276
)
URL operations


  parse_url()
    break down into details

    do not make any check

  parse_str()
    split a query string

    separate and decode, as long as it can

    Fill up an array or globals
URL


<?php
$url = 'http://login:pass@www.site.com/
         path/file.php?a=2+&b%5B%5D=
         %E5%AF%B9%E4%BA%86%EF%BC%81#ee';
$d = parse_url($url);
print_r($d);

parse_str($d["query"]);
var_dump($GLOBALS["b"]);
?>
URL

(
    [scheme] => http
    [host] => www.site.com
    [user] => login
    [pass] => pass
    [path] => /path/file.php
    [query] => a=2&b%5B%5D=%E5%AF%B9%E4%BA%86%EF%BC%81
    [fragment] => ee
)
array(1) {
  [0]=>
  string(9) "     "
}
URL validations


   scheme : list your own
   host : checkdnsrr() to check
   path : realpath() + doc root (beware of mod_rewrite)
   query : parse_str()
     beware of the second argument!

     don’t handle &amp;
URL rebuilding

     http_build_query()
          rebuild your query

          takes into account encoding and arrays

     <?php
     print http_build_query(
           array_merge($_GET ,
           array(' de ' => '                 ')));
     ?>

     +de+=%E5%AF%B9%E4%BA%86%EF%BC%81
URL testing

 <?php
    get_headers('http://localhost/logo.png');
 ?>

     Array
     (
         [0]   =>   HTTP/1.1 200 OK
         [1]   =>   Date: Mon, 12 Feb 2007 02:24:23 GMT
         [2]   =>   Server: Apache/1.3.33 (Darwin) PHP/5.2.1
         [3]   =>   X-Powered-By: eZ publish
         [4]   =>   Last-Modified: Fri, 30 Sep 2005 09:11:28 GMT
         [5]   =>   ETag: "f6f2a-dbb-433d0140"
         [6]   =>   Accept-Ranges: bytes
         [7]   =>   Content-Length: 3515
         [8]   =>   Connection: close
         [9]   =>   Content-Type: image/png
     )
PHP is dynamic

    Variables variables
    <?php
      $x = 'y';
      $y = 'z';
      $z = 'a';

      echo $x;  // displays y
      echo $$x;  // displays z
      echo $$$x; // displays a
    ?>
Variable constants

      Still one definition
      Dynamic constant value
  <?php
    define ("CONSTANT", 'eZ Conference');
    echo CONSTANT;
    echo constant("CONSTANT"); 
  ?>


      See the runkit to change constants...
Juggling with variables

     Compact() and extract()
 <?php 
  $x = 'a'; $y = 'b'; 
  $z = compact('x','y');   
 // $z = array('x'=> 'a', 'y' => 'b'); 

   $r = call_user_func_array('func', $z); 
 // calling func($x, $y); 

   extract($r); 
 // $x = 'c'; $y = 'd'; $t = 'e';
   list($x, $y, $t) = array_values($r);
 ?>
Variable functions

 <?php
  $func = 'foo'; $foo = 'bar';   $class = 'bb';

  $func($foo); // calling foo with bar
  call_user_func($func, $foo);// same as above

  call_user_func(array($class, $func), $foo); 
                        // now with objects!
  $class->$func($foo); // same as above
 ?>
Variable functions

 <?php
  $func = 'f';
  // a function
  // beware of langage construct such as empty()

  $func = array('c','m');
  // a static call to class c

  $func = array($o,'m');
  // a call to object o

  call_user_func($func, $foo);
 ?>
Object magic


  __autoload() : load classes JIT
  __sleep() and __wakeup()
    Store object and ressources in sessions
  __toString()   : to turn an object to a string
    __toArray() : get_object_vars($object);
    __toInteger() : may be?
Output buffering


   Avoid ‘already sent’ bug
   Clean it :   tidy
   Compress it : gz           <?php
                              ob_start("ob_gzhandler");
   Cache it                   echo "Hellon";
                              setcookie("c", "v");
                              ob_end_flush();
                              ?>
Caching

    auto_prepend :
      if ( filemtime($cache)+3600 < time()) {
          include($cachefile);     exit;
      }
      ob_start();
    auto_append :
        $content = ob_get_contents(); 
        file_put_contents('cache', $contents);
        ob_end_flush();

    Auto-caching upon 404 error pages
Connexion handling



  PHP maintains the connexion status
     0 Normal; 1 Aborted; 2 Timeout

  ignore_user_abort() to make a script without interruption
  connexion_status() to check status
Register for shutdown


     Function executed at script shutdown
     Correct closing of resources
     More convenient than ignore_user_abort() a library
     In OOP, better use __destruct()
     Storing calculated variables
Variables export

      var_export() : recreate PHP code for a variable

  <?php
                                              array (
                                                0 => 5,
  $array = array(5,4,3,2);
                                                1 => 4,
                                                2 => 3,
  file_put_contents('file.inc.php',
                                                3 => 2,
     '<?php $x = '.
                                              )
    var_export($array, true).
   '; ?>'
  );
  ?>
Assertions


     Include tests during execution
     Assertion are an option (default is on) :
     Most clever way than removing than echo/var_dump
     Common practice in other languages
       Programmation by contract
Assertions

<?php
assert_options(ASSERT_CALLBACK,'assert_callback');
function assert_callback($script,$line, $message){
   echo 'There is something strange 
         in your script <b>', $script,'</b> : 
         line <b>', $line,'</b> :<br />'; exit;
  }

   assert('is_integer( $x );' );
  assert('($x >= 0) && ($x <= 10); 
           //* $x must be from 0 to 10' );
  echo "0 <= $x <= 10";
?>
Debugging



  get_memory_usage()
    memory_limit is now on by default

    Better memory handling

    The fake growth of memory needs

  get_peak_memory_usage()
Debugging


  get_included_files()
  get_defined_constants/functions/vars()
  get_declared_classes()
  get_debug_backtrace()
    function stack and their arguments

    file and line calling
Debugging

   array(2) {
   [0]=>
   array(4) {
       ["file"] => string(10) "/tmp/a.php"
       ["line"] => int(10)
       ["function"] => string(6) "a_test"
       ["args"]=>
         array(1) { [0] => &string(6) "friend" }
   }
   [1]=>
   array(4) {
       ["file"] => string(10) "/tmp/b.php"
       ["line"] => int(2)
       ["args"] =>
         array(1) { [0] => string(10) "/tmp/a.php" }
       ["function"] => string(12) "include_once"
     }
   }
Slides

  http://www.nexen.net/english.php
  damien.seguy@nexen.net
  http://www.nexenservices.com/
Everyone
  loves
  PHP

Php tips-and-tricks4128

  • 1.
    PHP tips andtricks Skien, Norge, June 7th 2007
  • 2.
    Agenda Tipsand Tricks from PHP No need for anything else than standard distribution All for PHP 5 ( but lots of it is also valid in PHP 4 ) The month of PHP functions
  • 3.
    Who is speaking? Damien Séguy Nexen Services, eZ publish silver partner for hosting PHP / MySQL services Redacteur en chef of www.nexen.net Phather of an plush Elephpant http://www.nexen.net/english.php
  • 4.
    Nod when youknow about it
  • 5.
    Random stuff rand() and mt_rand() array_rand() : extract info from an array extract keys! shuffle() : shuffle an array before deal str_shuffle() : shuffle a string
  • 6.
    Random stuff Array <?php ( $a = range('a','d'); [0] => c shuffle($a); [1] => d [2] => b print_r($a); [3] => a ) print_r(array_rand($a,3)); Array ( print str_shuffle('abcdef'); [0] => 0 // eabdcf [1] => 1 ?> [2] => 3 )
  • 7.
    Arrays combinaisons array_combine() : turn two arrays into one Inverse to array_keys() and array_values() <?php $a = array('green', 'red', 'yellow'); $b = array('avocado', 'apple', 'banana'); $c = array_combine($a, $b); Array print_r($c); ( ?> [green] => avocado [red] => apple [yellow] => banana )
  • 8.
    Arrays combinaisons array_combine() : turn two arrays into one PDO::FETCH_KEY_PAIR : combine 2 columns in a hash <?php $html = file_get_contents("http://www.php.net/"); //'<a href="http://php.net">PHP</a>'; if (preg_match_all( '#<a href="(http://[^"/?]+/).*?>(.*?)</a>#s', $html, $r)) {     $liste = array_combine($r[2], $r[1]); } print_r($liste); ?>
  • 9.
    Arrays as SQL array_count_values() : makes easy stats Works like a GROUP BY and COUNT() <?php $array = array(1, "hei", 1, "takk", "hei"); print_r(array_count_values($array)); ?> Array sort r u ( r u [1] => 2 [hei] => 2 k k kr uk [takk] => 1 a a ar ua )
  • 10.
    Arrays as SQL Array ( array_multisort() : sort several [0] => 2 arrays at once [1] => 3 Works like a ORDER BY [2] => 4 [3] => 5 <?php ) $ar1 = array(5,4,3,2); Array $ar2 = array('a','b','c','d'); ( array_multisort($ar1, $ar2); [0] => d array_multisort($ar1, [1] => c SORT_ASC,SORT_STRING, [2] => b $ar2); [3] => a ?> )
  • 11.
    Fast dir scans scandir(‘/tmp’, true); Include name sorting Replace opendir, readdir, closedir and a loop! glob(‘*.html’); Simply move the loop out of sight
  • 12.
    Fast dir scans Array ( [0] => sess_um8rgjj10f6qvuck91rf36srj7 [1] => sess_u58rgul68305uqfe48ic467276 [2] => mysql.sock [3] => .. <?php [4] => . print_r(scandir('/tmp/', 1)); ) print_r(glob('/tmp/sess_*')); Array ?> ( [0] => /tmp/sess_um8rgjj10f6qvuck91rf36srj7 [1] => /tmp/sess_u58rgul68305uqfe48ic467276 )
  • 13.
    URL operations parse_url() break down into details do not make any check parse_str() split a query string separate and decode, as long as it can Fill up an array or globals
  • 14.
    URL <?php $url = 'http://login:pass@www.site.com/ path/file.php?a=2+&b%5B%5D= %E5%AF%B9%E4%BA%86%EF%BC%81#ee'; $d = parse_url($url); print_r($d); parse_str($d["query"]); var_dump($GLOBALS["b"]); ?>
  • 15.
    URL ( [scheme] => http [host] => www.site.com [user] => login [pass] => pass [path] => /path/file.php [query] => a=2&b%5B%5D=%E5%AF%B9%E4%BA%86%EF%BC%81 [fragment] => ee ) array(1) { [0]=> string(9) " " }
  • 16.
    URL validations scheme : list your own host : checkdnsrr() to check path : realpath() + doc root (beware of mod_rewrite) query : parse_str() beware of the second argument! don’t handle &amp;
  • 17.
    URL rebuilding http_build_query() rebuild your query takes into account encoding and arrays <?php print http_build_query( array_merge($_GET , array(' de ' => ' '))); ?> +de+=%E5%AF%B9%E4%BA%86%EF%BC%81
  • 18.
    URL testing <?php get_headers('http://localhost/logo.png'); ?> Array ( [0] => HTTP/1.1 200 OK [1] => Date: Mon, 12 Feb 2007 02:24:23 GMT [2] => Server: Apache/1.3.33 (Darwin) PHP/5.2.1 [3] => X-Powered-By: eZ publish [4] => Last-Modified: Fri, 30 Sep 2005 09:11:28 GMT [5] => ETag: "f6f2a-dbb-433d0140" [6] => Accept-Ranges: bytes [7] => Content-Length: 3515 [8] => Connection: close [9] => Content-Type: image/png )
  • 19.
    PHP is dynamic Variables variables <?php $x = 'y'; $y = 'z'; $z = 'a'; echo $x;  // displays y echo $$x;  // displays z echo $$$x; // displays a ?>
  • 20.
    Variable constants Still one definition Dynamic constant value <?php   define ("CONSTANT", 'eZ Conference');   echo CONSTANT;   echo constant("CONSTANT");  ?> See the runkit to change constants...
  • 21.
    Juggling with variables Compact() and extract() <?php   $x = 'a'; $y = 'b';   $z = compact('x','y');    // $z = array('x'=> 'a', 'y' => 'b');  $r = call_user_func_array('func', $z);  // calling func($x, $y);  extract($r);  // $x = 'c'; $y = 'd'; $t = 'e'; list($x, $y, $t) = array_values($r); ?>
  • 22.
    Variable functions <?php  $func = 'foo'; $foo = 'bar'; $class = 'bb';  $func($foo); // calling foo with bar call_user_func($func, $foo);// same as above  call_user_func(array($class, $func), $foo);  // now with objects! $class->$func($foo); // same as above ?>
  • 23.
    Variable functions <?php $func = 'f'; // a function // beware of langage construct such as empty() $func = array('c','m'); // a static call to class c $func = array($o,'m'); // a call to object o call_user_func($func, $foo); ?>
  • 24.
    Object magic __autoload() : load classes JIT __sleep() and __wakeup() Store object and ressources in sessions __toString() : to turn an object to a string __toArray() : get_object_vars($object); __toInteger() : may be?
  • 25.
    Output buffering Avoid ‘already sent’ bug Clean it : tidy Compress it : gz <?php ob_start("ob_gzhandler"); Cache it echo "Hellon"; setcookie("c", "v"); ob_end_flush(); ?>
  • 26.
    Caching auto_prepend : if ( filemtime($cache)+3600 < time()) {     include($cachefile);     exit; } ob_start(); auto_append :   $content = ob_get_contents();    file_put_contents('cache', $contents);   ob_end_flush(); Auto-caching upon 404 error pages
  • 27.
    Connexion handling PHP maintains the connexion status 0 Normal; 1 Aborted; 2 Timeout ignore_user_abort() to make a script without interruption connexion_status() to check status
  • 28.
    Register for shutdown Function executed at script shutdown Correct closing of resources More convenient than ignore_user_abort() a library In OOP, better use __destruct() Storing calculated variables
  • 29.
    Variables export var_export() : recreate PHP code for a variable <?php array ( 0 => 5, $array = array(5,4,3,2); 1 => 4, 2 => 3, file_put_contents('file.inc.php', 3 => 2, '<?php $x = '. ) var_export($array, true). '; ?>' ); ?>
  • 30.
    Assertions Include tests during execution Assertion are an option (default is on) : Most clever way than removing than echo/var_dump Common practice in other languages Programmation by contract
  • 31.
    Assertions <?php assert_options(ASSERT_CALLBACK,'assert_callback'); function assert_callback($script,$line, $message){    echo 'There is somethingstrange  in your script <b>', $script,'</b> :  line <b>', $line,'</b> :<br />'; exit; } assert('is_integer( $x );' );   assert('($x >= 0) && ($x <= 10);  //* $x must be from 0 to 10' );   echo "0 <= $x <= 10"; ?>
  • 32.
    Debugging get_memory_usage() memory_limit is now on by default Better memory handling The fake growth of memory needs get_peak_memory_usage()
  • 33.
    Debugging get_included_files() get_defined_constants/functions/vars() get_declared_classes() get_debug_backtrace() function stack and their arguments file and line calling
  • 34.
    Debugging array(2) { [0]=> array(4) { ["file"] => string(10) "/tmp/a.php" ["line"] => int(10) ["function"] => string(6) "a_test" ["args"]=> array(1) { [0] => &string(6) "friend" } } [1]=> array(4) { ["file"] => string(10) "/tmp/b.php" ["line"] => int(2) ["args"] => array(1) { [0] => string(10) "/tmp/a.php" } ["function"] => string(12) "include_once" } }
  • 35.
    Slides http://www.nexen.net/english.php damien.seguy@nexen.net http://www.nexenservices.com/
  • 36.