PHP Notes --------- PHP Hypertext Processor. Politically Harmonious Perl. Perl, but Humane and Palatable. Perl-like, but less Haunting and Peculiar. Perl lite, less Heaving less Puking. (ok, ok, Perl is not nearly that bad...) People-Happy Perl. $variables $ + letter|_ + letter|number|_ ... [a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]* CScs - case sensitive names $a = 1; $A = 2; assert($a == 1); $$variableVariables $$symbol $a = 42; $q = 'a'; assert($$q == 42); There are no "var" (ala JS) statements, just assign to declare (unusual) Errors ------ @function() (* soften: no warning or error message is output) function() or die(msg) (* harden: fatal error if returning false) Habitat ------- Equivalent: XML-legal unless php.ini: short_open_tag = off unless php.ini: short_open_tag = off <% echo $x; %> if php.ini: asp_tags = on <%= $x; %> if php.ini: asp_tags = on Equivalent: echo 'stuff\\etc.'; echo('stuff\\etc.'); print 'stuff\\etc.'; print('stuff\\etc.'); ?>stuff\etc. <?='hello world'?> Source Files ------------ include($sPath) require($sPath) require_once($sPath) function __autoload($classname) { require_once("$classname.php"); } Comments -------- Equivalent: echo ""; // comment echo ""; /* comment */ echo ""; # comment Types ----- boolean $b true or TRUE or false or FALSE integer $i... or $n... 256 or 0400 or 0x100 "12" + 3 === 15 (-JS - would be "123") float (* about 13 digits accuracy) string $s $s = 'string'; $s = 'one line and a lot of spaces'; $s = "one line\n and a lot of spaces"; $s (* backslash only needs doubling before a single quote or end of string) (* backslash before any character other than ' or \ is literal and vis) "\n\r\t\\\$\"\0377\xFF" Heredoc (monstrous multi-line string literal) (yes it extrapolates $vars) ------- (* not recommended because it thwarts the single most important structural aspect of human-readable code: indentation) (* The heredoc terminator is a LINE and not a character sequence. The terminating LINE must contain the symbol or the symbol plus a ; but NO WHITE SPACE of any kind, including indentation, or space before or after the ; or comments) $query = <<integer --------- $i = (integer)$x; or (int) $i = $x + 0; (-JS) $i = intval($x); ->float ------- $x = (float)$z; or (real) or (double) settype($x=$z,'float'); (4.2, preferred) settype($x=$z,'double'); (deprecated, but ancient) ->boolean --------- $b = (boolean)$z; or (bool) settype($b=$z,'boolean'); ->string -------- $s = (string)$x; $s = $x . ""; $s = "$x"; $s = strval($z); settype($s=$za'string'); when comparing anything with a string? (array) (object) Scope ----- all vars in a function are (b) local unless declared "global $xxx" very common error if you ahem use global variables fortunately newer PHP gives you a warning instead of a silent NULL (declaration works at the start of the function, can it be elsewhere?) Global Scope, etc. Operators --------- $o = new(classorsomething) $z = $a[$z] $n++ $n-- ~ - (int) (float) (string) (array) (object) @ instanceof ! * / % + - . << >> < <= > >= == != === !== & ^ | $b = $b && $b $b = $b || $b $z = ($b ? $z : $z) (b very loose binding, always outer-parenthesize) = += -= *= /= .= %= &= |= ^= <<= >>= and xor or Reserved words -------------- file:///C:/rfc/PHP%20Manual.htm#reserved __CLASS__ __FILE__ __FUNCTION__ __LINE__ __METHOD__ and array() as break case cfunction class const continue declare default die() do echo() else elseif empty() enddeclare endfor endforeach endif endswitch endwhile eval() (? there is no way to trap an eval(syntax error) is there?) exception exit() extends for foreach function global if include() include_once() isset() list() new old_function or php_user_filter print() require() require_once() return() static switch unset() use var while xor Arrays ------ $a = array(1,2,'three'); reset($a); while (list($k,$v) = each($a)) { $j .= "$k->$v "; } assert($j == "0->1 1->2 2->three "); is a comma after the last element in a literal ignored? Null element? array(0,1,2,) $a = array(0 => 'zero', 1 => 'one'); $a = array('zero' => 0, 'one' => 1); $a = array(0 => array('English' => 'zero', 'Spanish' => 'cero')); $a = array('zero', 'one'); assert($a[0] == 'zero'); assert($a[1] == 'one'); Equivalent: $a = array(0 => 'zero', 1 => 'one'); $a = array('zero', 'one'); unset($a); $a[0]='zero'; a[1]='one'; unset($a); $a[]='zero'; a[]='one'; Equivalent: $a[] = $x; $a[] = $y; $n = key($a)+1; //? how (else) to get [] index? $n = array_push($a, $x, $y); Equivalent: $a['key'] = 'value'; Perl stuff you can't do in PHP: ($x, $y) = array('x', 'y'); Interpoloation -------------- echo "Terminated line.\n"; echo "A variable value is $value.\n"; echo 'Not a variable $value, just a literal dollar sign' echo "This member value is $this->value.\n"; echo "This member value is {$this->value}.\n"; echo "This member value is {$this->arr[1][2]}.\n"; // braces required? echo "This member value is {$this->arr['a']['b']}.\n"; // braces required? echo "This return value is {$this->memberf('x')}.\n"; "{${$name}}"; bad: ${o->member} "this works $a[key] only if there's no define('key',...)" "this works {$a['key']} best" "this fails $a['key'] trips up parser" (? why doesn't this work: "blah blah {f($x)} blah blah" ?) good: "\n"; bad?: '\n'; // (?) and is Perl different about this? Iffies and Loopies ------------------ Similar: foreach ($a as $v) { echo $v; } foreach ($a as $k => $v) { echo "$k => $v\n"; } for ($i=0 ; $i < count($a) ; $i++) { $v = $a[i]; echo $v; } reset($a); while (($v=current($a)) !== FALSE) { // break if array contains FALSE? ... next($a); } reset ($a); while (list($k,$v) = each ($a)) { // nonempty arrays never convert to FALSE? ... } switch ($z) { (ala JS, ala C except strings allowed) case z: ... break; case z ... break; default: ... break; } if ($z) { ... } elseif { (ala Perl except not Lary's tacky "elsif") ... } else { ... } Object ------ class foo { var $v; // member variable function foo() { // constructor } function f($x) { // member function } } o = new foo; o->v = 2; o->f(3); (?) no literal object, as PHP array(...) or JavaScript {a:0, b:1,...} oh wait, there's this: o = (object)array('a' => 0, 'b' => 1); assert(o->a === 0); assert(o->b === 1); OOP version 4-only features --------------------------- is_a($o, 'C'); // is $Z of class C? Or a class extending C? (deprecated ==> instanceof) === means: same class, same property values -- essentially equivalent assignment clones (no destructors) (get_parent_class() is parent of the instance NOT of the function you're in) (var_export() useless) OOP version 4 & 5 features (and 6...) -------------------------- classname as constructor (ala C++) (beware name conflicts) explicit $this inside methods class Child extends Parent {} manual base class construction: $this->ParentClassName(...); var $property=CONSTANTEXPRESSION; $this always explicit (b) (unlike C++) ClassName::method() parent::method() == means: same class, same property values -- essentially equivalent new classname new classname(constructor args) stdClass is_subclass_of($o, 'C'); // is $Z of a class extending C? (deprecated) __set() __get() (v4: 2 params, v5: 1 param) __call() (v4: 3 params, v5: 2 param) __sleep() __wakeup() (no automatic base class construction) (no multiple extension (inheritance) though v5 has multiple implements) OOP version 5-only features (and 6...) --------------------------- new self or new parent (v5 only?) assign and pass by *reference* (v5 only?) const === only if referring to the same physical instance assignment refers (b) abstract interface, implements instanceof self::method() static::method() // spooky __construct() __destruct() __autoload (web only, not command line) __toString() __isset() __unset() var_export() outputs ClassName::__set_state(array(...)) call private protected public (aka var) clone __clone() method (ala C++ copy constructor) final static get_declared_interfaces() interface_exists('I') property_exists('C', 'property') property_exists($o, 'property') Functions --------- function names are CcIi!! Function Call ------------- $y = f($x); Function Definition (PHP3: define above call, PHP4: any order) ------------------- (CcIi - function names are case insensitive) function f() { // definition } function f() { return $y; // return value } function f($x) { // parameter } function f($x = 'default'); // default parameter value } function f() { // variable number of parameters $a = func_get_args(); } function f(&$x) { // input/output parameter (pass by ref) $x .= 'appendage'; // (ala Perl) } if ($b) { function g() { // conditional definition } } function f() { function g() { // nested } } unlike JavaScript, PHP cannot undefine or redeclare functions Functions, Built-In ------------------- addcslashes addslashes array_join --> join() $b = array_key_exists($key, $a); //~ in_array($value,$a) array_merge($a, $a, ...) array_merge_recursive($a, $a, ...); // tree merge // example in manual is evil $n = array_push($a, $x, ...); array_slice(); // passive excerpting array_splice() // destructive excerpting chop trims trailing whitespace $s = chr($n) (* ASCII encode, strlen($s) == 1) (~ord()) (+P) $n = count($a); // (= sizeof()) // count('nonarray') == 1 count(NULL) == 0 $b = define($s, $v); // $v is simple (boolean,integer,float,string) // (u C, Java) $zreturn = eval($s); // unlike JS returns NULL unless $s has "return ...;" ~~~~ exit($rc); // (? no more html either? whence $rc on the web?) $a = explode($separator, $s); list($s,$s) = explode($separator, $s): $a = explode($separator, $s, $nmax); // (? pattern or chars?) // faster than split() or preg_split() regexp's flush(); (tip: flush(); echo ''; if a lot more to come) $x = func_get_arg($i); // 0 <= $i < func_num_args() $a = func_get_args(); // $n = func_num_args(); // # arguments actually passed by caller $x = getmicrotime(); // microsecond-resolution (subtract to time) $s = get_class($x); $s = gettype($x); // ala JavaScript typeof() returns a string: "boolean" "integer" "double" "string" "array" "object" "resource" "NULL" "unknown type" $s = htmlentities($s); '<' -> '$lt;' and all possible &xxx; $s = html_entity_decode($s) $s = htmlspecialchars($s); '<' -> '$lt;' '"' "'" '&' '>' $b = in_array($value, $a); //~ array_key_exists($key, $a) $b = in_array($value, $a, $type_strict); $s = implode($sglue, $a); // same as join() $b = is_array($x); // gettype($x) === "array" $b = isset($x); // $x === NULL $s = join($sglue, $a); // same as implode() length --> strlen($s), count($a) lower case -> strtolower($s) $b = mqsql_close($db); mysql_connect(); $hdlQuery = mysql_db_query($db, $query, [$hdlConnection]) mysql_db_name() (= mysql_result()) mysql_dbname() (x mysql_result()) mysql_error $array = mysql_fetch_array($hdlQuery, MYSQL_ASSOC, _NUM, _BOTH); $aarray = mysql_fetch_assoc($hdlQuery) (=mysql_fetch_array($h,MYSQL_ASSOC)) $x = $aarray['nameColumn']; (4.0.3) (b with MYSQL_BOTH if any column names are numbers, then the _NUM numeric indices will be clobbered) $narray = mysql_fetch_row($hdlQuery) (=mysql_fetch_array($h,MYSQL_NUM)) $x = $narray[indexColumn]; $object = mysql_fetch_object($hdlQuery) $x = $object.nameColumn; $structure = mysql_fetch_field($hdlQuery, $indexColumn) $lengths = mysql_fetch_lengths($hdlQuery) $hdlQuery = mysql_query($query, [$hdlConnection]) $x = mysql_result($hdlQuery, $row, [$column]) $n = mysql_num_rows() $n = ord($s) (* ASCII decode, 1st char only) (~ chr()) (+P) $s = phpversion(); $nmatches = preg_match("/$regexp/", $s[, &a[, $nflags[, $noffset]]]); //contrast strpos() $s = preg_replace($rold, $snew, $s, $mreps); // $old e.g. '/the/' $s = preg_replace($aold, $snew, $s, $mreps); // $old e.g. array('/the/','/The/') $s = preg_replace($aold, $anew, $s, $mreps); // arrays of old and new $a = preg_replace($rold, $snew, $a, $mreps); // arrays of in and out // $mreps defaults -1=infty (ala Perl 'g' option) // "$1" or "\\1" in $new refers to the // 1st parenthesized submatch in $old // $old = '/blah/s' so . includes \n // $old = '/blah/i' for case insensitivity // $old = '/blah/g' illegal - omit $nreps instead // problems with $ as start-of-string? assert(preg_replace('/(a)(b)(c)/', "$3$2$1", 'abc') == 'cba'); preg_replace(,,,&$nreps) optional output, number of replacements preg_replace_callback($old, "fcallback", $s, $mreps[, &$nreps]); function fcallback($sold) { return $snew; } $a = preg_split("/$regexp/", $s[, $nlimit[, $nflags]]); print_r($z); $s = print_r($z, TRUE); (4.3) $x = round($x) $x = round($x,nfrac) (4) (* 2 makes cents, -3 for 1000s) $b = settype($x,'boolean'); settype($x,'integer'); settype($x,'float'); settype($x,'double'); settype($x,'string'); settype($x,'array'); settype($x,'object'); settype($x,'null'); (4.2) $n = sizeof($a); // (= count()) $a = split($spat, $s, $nmax); // (bs) no /'s in $spat, e.g.: '[-_]' $a = spliti($spat, $s, $nmax); list($s,$s) = split($separator, $s); // wowee, shades of Perl or what $s = sprintf($sformat, x, x, ...); $numvars = sscanf($s, $sformat, $var1, $var2, ...) $n0f = strpos($stringlooong, $stringshort)[, $noffset]); $n = strcasecmp($s1,$s2); CcIi $n = strcmp($s1,$s2); CScs $s = stripslashes($s) $s = stripcslashes($s) (* decodes C language \n etc.) $s = strip_tags($s) $s = strip_tags($s, ''); // exceptions - tags NOT to strip $n = strlen($s) $s = strtolower($s); $s = strtoupper($s); $s = str_replace($sold, $snew, $s); $s = str_replace($aold, $anew, $s); // array of replacments $a = str_split($s, [ $n ] ) $s = substr($s, $istart); $s = substr($s, $istart, $ilength); $i = substr_compare($slong, $sshort, $istart, $nlength, $bcasesensitive); (5) substr_count $s = substr_replace($s, $snew, $istart, $length); (4) $s - trim($s) (* whitespace from both left and right) (unlike MySQL) typeof --> gettype(), get_class() $s = ucfirst($s); // Capitalize first letter $s = ucwords($s); // Capitalize First Letter Of Every Word upper case -> strtoupper($s) Misc ---- functions must be defined before called (temporally, like JS?) statements must end in ; (unlike JS, like Perl) regular expressions are only in strings, not slashes (unlike JS, unlike Perl) Tips ---- Everyone who uses PHP should probably write a function like this: function bold($s) { return "$s"; } And they should never use it. It's so neat and tidy when PHP syntax is beginning to make sense, who could shelve it. But like a paperweight for Father's Day, you can like without compulsion to use. All functions should improve human readability. That one never will. But wait, let's do the like-thing a bit. There are many features in that short function that can be absorbed just by looking at it. All the trimmings of a function definition are there, the name, parameters, the braces, the return value. And the purpose is so crystal clear. Bonus, there's the exotic interpolation feature. (Isn't that a glamorous term? Compared to some others in programming.) There's magic in the way that $s variable comes to life inside the double-quoted string. Any language but PHP (and its rich uncle Perl) would make you work harder. Ok, the reason you should never use a function like this is it either obscures without adding meaning, or it misses a chance to add meaning. The code bold($x) may look tidy, but it raises questions to a fluent PHP reader. "$x" To the trained PHP eye, that's as plain as day. If there is good reason to make a function do this, then you should not call it bold(). Take the opportunity to do what HTML always dreamed of doing but never really could: articulate meaning in your code. Call it emphasize(), or give some clue why you're emphasizing here, danger() or price(). Good naming considers all uses. If you have only one so far, that's another reason not to invent a function yet. Troubleshooting --------------- Warning: Cannot send session cache limiter - headers already sent some PHP code is in the body element when it should be before the tag syntax error, unexpected T_ENCAPSED_AND_WHITESPACE ... syntax error, unexpected '.' goofed up strings, forgetting dots or quotes or quote-escapes or something or missing { } matching for interpolation syntax error, unexpected ';' too many '(' open parens? Parse error: parse error, unexpected '=' = instead of == or === perhaps? syntax error, unexpected '}' in .../path/filename... on line NNN syntax error, unexpected '}', expecting ',' or ';' syntax error, unexpected T_ECHO, expecting ',' or ';' syntax error, unexpected T_STRING missing ; on the line above missing , on the line above missing ' (close-single-quote) way above missing or too many parentheses? maybe not... syntax error, unexpected T_STRING, expecting T_VARIABLE missing $ as in var p; -> var $p; syntax error, unexpected T_STRING quote mixup: $s='This can't be happening.' $s=""; syntax error, unexpected T_CONSTANT_ENCAPSED_STRING missing , in array literal: array('a'=>1 'b'=>2) or function parens: f'x' syntax error, unexpected $end in ... Missing '}' -- unterminated curly-brace Or it's complaining about the ?> Look for an unexpected ?> Here's an example of legit use going bad when commented! NO: preg_replace('/<.*?>/', '' , $terms_title); YES: // preg_replace('/<.*?>/', '' , $terms_title); Anyway, another reason to use strip_tags() parse error, unexpected $end in ... Look for a missing close-curly brace '}' PHP Notice: Undefined variable (or other symptom when a variable is NULL or unchanges myseriously) need global $variable; ? (this goof is VERY common) (90% of midlevel bugs are caused by it) PHP Notice: Undefined index $value = $a[$key] ==> $value = array_key_exists($key, $a) ? $a[$key] : ''; PHP Notice: Undefined offset PHP Notice: Use of undefined constant z - assumed 'z' z ==> $z z ==> z() syntax error, unexpected T_INC syntax error, unexpected T_DEC z++ ==> $z++ $formfield isn't working register_globals? _GET[] isn't working _POST[] isn't working won't mysql_connect() == broken? === instead? gotcha: 7331 == 'leet' "The requested operation has failed" (popup starting Apache) "Cannot load c:/php/php5apache2.dll into server: The specified module could not be found" (from "httpd -t" command line) PHP 5.1.6 not compatible with Apache 2.2.3. (works with Apache 2.0.59) http://www.sitepoint.com/article/php-amp-mysql-1-installation/2 php.ini settings don't take effect make sure you have the right php.ini restart apache Warning: Cannot modify header information - headers already sent by (output started at ...filename...:linenumber) in ...filename... on line linenumber remove blank lines circa the output-started filename/linenumber ? nothing can come before ? Warning: Invalid argument supplied for foreach() foreach($notarray as $z) { } Fatal error: Function name must be a string $func() --> func() 1210 (HY000): Incorrect arguments to EXECUTE Mismatch in PREPARE versus EXECUTE number of parameters and/or type? not sure Compilation failed: nothing to repeat at offset 0 bad: preg_replace("/?.*/", "", $THISURL); // ? is a dangling repeater good: preg_replace("/\\?.*/", "", $THISURL); // ? is literal ?Mysteries? ----------- How to figure out what index $a[] will assign to? How to get the output of print_r() into a string? DDooodooohead Mistakes -> Solutions ---------------------------------- $CONSTANT -> CONSTANT variable -> $variable "sum " . a+b -> "sum " . (a+b) (at least for a-b it's true) function f() { $x==? } -> function f() { global $a; $x==! } $func() -> func() Review ------ http://www-128.ibm.com/developerworks/opensource/library/os-php-flexobj/?ca=dgr-lnxw01DynamicPHP http://particletree.com/notebook/on-php-and-libraries/ (digg) Keith Roberts' email about "most used and useful extensions" http://www.php.net/tips.php @@@@ NULL ---- (b) '' == NULL '' !== NULL NULL === NULL (unlike SQL, similar to JavaScript?) Legend ====== (* ...) (x ...) deprecated in favor of ... (4.0.3) started in version 4.0.3 (-JS) unlike JavaScript (+P) like Pascal (b) bomb (gotcha) (b ...) bomb with explanation (?...) mysteries to resolve Bugs Reported ------------- Bugs To Report -------------- mysqli_report() is bizarre. Seems to affect either future requests, or same requests BEFORE it's called. Spooky, haven't psyched it out. Plus it seems to generate exceptions (which is not documented) and they are dysfunctional, at least in 5.2.5: mysqli_report(MYSQLI_REPORT_ALL); try { $resulti = $mysqli->query("SELECT * FROM t WHERE id!=666"); } catch (mysqli_sql_exception $e) { assert(!isset($e)); } Suggestions ----------- From Scott Dale: Yep - for PHP I'd put array management, function call syntax, include mechanism, conversion functions, mysql_* library, globals and super globals, string functions, and on. JackDanials stuff is not dense enough which is why I like your stuff. SD Examples -------- mysql_list_processes mysql_query, fetch_array, num_fields, num_rows, field_name, etc. mysql_query, get meta information, column names, widths, types? contrast mysql_list_fields() columns with query SHOW COLUMNS rows? and show the mysql_field_name and mysql_fetch_field ways too? four ways to get the column field (fifth if you count mysql_fieldname) 2nd Edition ----------- $_SERVER['HTTP_HOST'] domain as in the URL, e.g. www.visibone.com $_SERVER['SERVER_NAME'] domain configured by web server, e.g. visibone.com $_SERVER['SCRIPT_NAME'] no suffixes, exhumes index.php $_SERVER['PHP_SELF'] will have /suffix, exhumes index.php $_SERVER['REQUEST_URI'] will have /suffix and ?suffix (ref http://php.about.com/od/learnphp/qt/_SERVER_PHP.htm) $_SERVER['PATH_INFO'] has only the /suffix with the / $_SERVER['QUERY_STRING'] has only the ?suffix without the ? $_SERVER['argv'][0] is the first "part" of the ?suffix without the ? mysqli_fetch_object DOES exist! (Even used in non-verbose data_seek example) so don't snowflake mysql_fetch_object error_log($sMessage); // httpd log, e.g. error_log error_log($sMessage, 1, $sEmail); error_log($sMessage, 2); // when --enable-debugger error_log($sMessage."\n", 3, $sFilePath); max_execution_time=0 -> add to list in Form example (T-Z page, lower left corner) array versus object? (unlike Perl, they're not the same?) references? comment syntaxes? //... /*...*/ #... "upload example" in table of contents for page 7 (ebk 26) name="Upload" --> name="submit" value="Upload" PHP types, integers, $i $ii $ii -> $iii $iv //ghostly shades of Perl, thx Norbert Rennert array traversal methods (foreach, for, etc.) on array page remove var_export() call (with bad paren!) from file upload example (t-z page) uploads don't work checklist: set form enctype set form action (even if same php file!) see ini settings Functions I've wished were there -------------------------------- readfile, fgets