All notes
Php

Basics

Include

StackOverflow. Require include into variable:



// If your included file returned a variable
// include.php
return 'abc';

// Then you can assign it to a variable like so:
$abc = include 'include.php';

# Otherwise, use output buffering.
ob_start();
include 'include.php';
$buffer = ob_get_clean();

Run bash

Stackoverflow.



$old_path = getcwd();
chdir('/my/path/');
$output = shell_exec('./script.sh var1 var2');
chdir($old_path);
echo "<pre>$output</pre>";

Phpinfo


<?php
phpinfo();
// NOTE: dollar sign in EOT should still be escaped. At lease in PHP version before 5.2.
// <a href="http://stackoverflow.com/questions/7804552/how-to-store-php-code-inside-heredoc-variable">How to store php coode in heredoc</a>.
\$var=1
?>

Time and data


$t=time();
echo(date("Y-m-d, l, h:i:sa",$t));

will give something like: 2014-08-20, Wednesday, 03:27:45pm.

Get, Post and Request

"register_globals boolean" decides whether to register EGPCS (Environment, GET, POST, Cookie, Server) variables as globals. For example, if this option is on, then the URL "www.mydomain.com/test.php?id=1" will produce a variable "\$id", and \$_SERVER['DOCUMENT_ROOT'] will have an alias \$DOCUMENT_ROOT. However it is not recommended because it definitely pollutes the global variable set. The super-global variables with respect to EGPCS "\$_ENV", "\$_GET", "\$_POST", "\$_COOKIE" and "\$_SERVER" are often used instead.

print_r: print a variable in a human readable way. "mixed print_r(mixed \$expression [, bool \$return = false])".

Comments

PHP supports 3 kinds of comment styles: C++ one line / multiple lines and Unix shell-style. See the following example:

echo 'Hello world!'; // C++ one line comment style.
echo 'Hello world again!';
/*
	Now this is c++ multiple lines comment style.
*/
echo 'Hello world finally!'; # shell-script style.

The comment will ends at the PHP end tag, e.g.


	<h1>This is an <?php # echo 'simple'; ?> example</h1>
	<p>The header above will say 'This is an  example'.</p>

And the multiple line comments cannot be nested.


<?php
	/* echo 'This is a test'; /* This comment will cause error! */
	*/
?>

Command line


php -S 0.0.0.0:5000

Datatypes

Bool

PHP: boolean.

以下值被认为是 FALSE:

布尔值 FALSE 本身
整型值 0(零)
浮点型值 0.0(零)
空字符串,以及字符串 "0"
不包括任何元素的数组
不包括任何成员变量的对象(仅 PHP 4.0 适用)
特殊类型 NULL(包括尚未赋值的变量)
从空标记生成的 SimpleXML 对象

var_dump((bool) "");        // bool(false)
var_dump((bool) 0);   // bool(false)
var_dump((bool) 0.000);   // bool(false)
var_dump((bool) array());   // bool(false)
var_dump((bool) "0");        // bool(false)
var_dump((bool) NULL);        // bool(false)
var_dump((bool) 1);         // bool(true)
var_dump((bool) "foo");     // bool(true)
var_dump((bool) "false");   // bool(true)

Arrays

Php: Array.


<?php
// PHP 数组可以同时含有 integer 和 string 类型的键名,因为 PHP 实际并不区分索引数组和关联数组。
$array = array(
    "foo" => "bar",
    "bar" => "foo",
    100   => -100,
    -100  => 100,
);
var_dump($array);

$age=array("Bill"=>"35","Steve"=>"37","Peter"=>"43");
foreach($age as $x=>$x_value) {
  echo "Key=" . $x . ", Value=" . $x_value;
  echo "<br>";
}

// 自 PHP 5.4 起
$array = [
    "foo" => "bar",
    "bar" => "foo",
];
?>

此外 key 会有如下的强制转换:


<?php
$array = array(
    1    => "a",
    "1"  => "b",
    1.5  => "c",
    true => "d",
);
var_dump($array);
?>

// 以上例程会输出:

array(1) {
  [1]=>
  string(1) "d"
}

String

Php.net: language types - string.

A string literal can be specified in four different ways:

Single quoted

Only two special chars: a literal single quote (\'), a literal backslash (\\).

All other instances of backslash will be treated as a literal backslash: this means that the other escape sequences you might be used to, such as \r or \n, will be output literally as specified rather than having any special meaning.

Unlike the double-quoted and heredoc syntaxes, variables and escape sequences for special characters will not be expanded when they occur in single quoted strings.

Double quoted

qiguang.net.

Heredoc, Nowdoc

Nowdocs are to single-quoted strings what heredocs are to double-quoted strings. A nowdoc is specified similarly to a heredoc, but no parsing is done inside a nowdoc. The construct is ideal for embedding PHP code or other large blocks of text without the need for escaping.   


$foo = 'bar';

$here = <<<HERE
    I'm here, $foo!
HERE;

$now = <<<'NOW'
    I'm now, $foo!
NOW;

// Result:
// $here is "I'm here, bar!", while $now is "I'm now, $foo!".

$str=<<<EOT
<?php
	...
?>
EOT; # End here.
echo htmlentities($str);

However, Nowdoc support was added in PHP 5.3.0. In old version, remember to escape '$' in php with '\'.

backslash


// Using single quotes
$string = 'abc\\def';

// Using double quotes
$string = "abc\\\\def";

// And HereDoc has the same effect as Double quotes.

StackOverflow.

htmlspecialchars, htmlentities

Compared to htmlentities (which transforms all html entities, see below), only part of chars are transformed in htmlspecialchars.

The translations performed by htmlspecialchars are:

'&' (ampersand) becomes '&amp;'
'"' (double quote) becomes '&quot;' when ENT_NOQUOTES is not set.
"'" (single quote) becomes '&#039;' (or &apos;) only when ENT_QUOTES is set.
'<' (less than) becomes '&lt;'
'>' (greater than) becomes '&gt;'    

This is being encoded with htmlentities:

implode( array_values( get_html_translation_table( HTML_ENTITIES ) ), "\t" ):

" & < >
¡ ¢ £ ¤ ¥ ¦ § ¨ © ª « ¬ ­ ® ¯ ° ± ² ³ ´ µ ¶ · ¸ ¹ º » ¼ ½ ¾ ¿ À Á Â Ã Ä Å Æ Ç È É Ê Ë Ì Í Î Ï Ð Ñ Ò Ó Ô Õ Ö × Ø Ù Ú Û Ü Ý Þ ß à á â ã ä å æ ç è é ê ë ì í î ï ð ñ ò ó ô õ ö ÷ ø ù ú û ü ý þ ÿ Œ œ Š š Ÿ ƒ ˆ ˜ Α Β Γ Δ Ε Ζ Η Θ Ι Κ Λ Μ Ν Ξ Ο Π Ρ Σ Τ Υ Φ Χ Ψ Ω α β γ δ ε ζ η θ ι κ λ μ ν ξ ο π ρ ς σ τ υ φ χ ψ ω ϑ ϒ ϖ       ‌ ‍ ‎ ‏ – — ‘ ’ ‚ “ ” „ † ‡ • … ‰ ′ ″ ‹ › ‾ ⁄ € ℑ ℘ ℜ ™ ℵ ← ↑ → ↓ ↔ ↵ ⇐ ⇑ ⇒ ⇓ ⇔ ∀ ∂ ∃ ∅ ∇ ∈ ∉ ∋ ∏ ∑ − ∗ √ ∝ ∞ ∠ ∧ ∨ ∩ ∪ ∫ ∴ ∼ ≅ ≈ ≠ ≡ ≤ ≥ ⊂ ⊃ ⊄ ⊆ ⊇ ⊕ ⊗ ⊥ ⋅ ⌈ ⌉ ⌊ ⌋ ⟨ ⟩ ◊ ♠ ♣ ♥ ♦    

This is being encoded with htmlspecialchars.

implode( array_values( get_html_translation_table( HTML_SPECIALCHARS ) ), "\t" ):

" & < > 

Language Reference

Variables

Basics


$var = 'Bob';
$Var = 'Joe';
echo "$var, $Var";      // outputs "Bob, Joe"
var_dump($var);

$4site = 'not yet';     // invalid; starts with a number
$_4site = 'not yet';    // valid; starts with an underscore
$täyte = 'mansikka';    // valid; 'ä' is (Extended) ASCII 228.

// Assign by reference.
$foo = 'Bob';              // Assign the value 'Bob' to $foo
$bar = &$foo;              // Reference $foo via $bar.
$bar = &(24 * 7);  // Invalid; references an unnamed expression.

// Detect if a variable has been already initialized.
isset(var);

Predefined Variables

Register_globals

In PHP 4.2.0 and later, the default value for the PHP directive register_globals is off.
To get DOCUMENT_ROOT you'll use $_SERVER['DOCUMENT_ROOT'] instead of $DOCUMENT_ROOT.

Superglobals

Superglobals
built-in variables that are always available in all scopes. There is no need to do global $variable; to access them within functions or methods.
$GLOBALS : References all variables available in global scope.
$_SERVER
$_GET
$_POST
$_FILES : HTTP File Upload variables.
$_COOKIE
$_SESSION
$_REQUEST
$_ENV

// GLOBALS
function test() {
    $foo = "local variable";

    echo '$foo in global scope: ' . $GLOBALS["foo"] . "\n";
    echo '$foo in current scope: ' . $foo . "\n";
}
$foo = "Example content";
test();
// Output:
// $foo in global scope: Example content
// $foo in current scope: local variable

Other predefined variables

$php_errormsg: The previous error message.
$argc: The number of arguments passed to script.
$argv: Array of arguments passed to script.

Variable Scope

Global


$a = 1; // Global scope.

// $a will be available in b.inc.
include 'b.inc';

function fun1()
{
    global $a; // 1. declare global within functions.
    echo $a;
}

function fun2()
{
    echo $GLOBALS['a']; // 2. Access via $GLOBALS.
} 

Static

Static declarations are resolved in compile-time.
References are not stored statically, nor globally.


// Useless function. $a will be initialized to 0 in every call.
function countCall()
{
    $a = 0;
    echo $a;
    $a++;
}

// Now it works.
function countCall()
{
    static $a = 0; // Initialized only in first call.
    echo $a;
    $a++;
}

Constants


define("CONSTANT", "Hello world.");
echo CONSTANT; // outputs "Hello world."
echo Constant; // outputs "Constant" and issues a notice.

echo PHP_BINARY;

Magic Constants

__LINE__
__FILE__
__DIR__ : Equivalent to dirname(__FILE__). Doesn't have the trailing slash unless it is the root dir.
__FUNCTION__ : Inludes the namespace, e.g. Foo\Bar.
__CLASS__
__TRAIT__
__METHOD__ : Class method name.
__NAMESPACE__

Control Structures

Require

require is identical to include except upon failure it will also produce a fatal E_COMPILE_ERROR level error. In other words, it will halt the script whereas include only emits a warning (E_WARNING) which allows the script to continue.

Classes


class MyClass
{
  public $prop1 = "I'm a class property!";

  // Constructor.
  public function __construct()
  {
      echo 'The class "', __CLASS__, '" was initiated!';
  }

  // Destructor. 
  public function __destruct()
  {
      echo 'The class "', __CLASS__, '" was destroyed.';
  }

  // Another magic method.
  public function __toString()
  {
      echo "Using the toString method: ";
      return $this->getProperty();
  }
}
// Unlike C++, We don't need a semicolon here.

// Create a new object.
$obj = new MyClass;

echo $obj;
 
// Destroy the object, manually.
unset($obj);

Inheritance


class MyOtherClass extends MyClass
{
  public function __construct()
  {
      parent::__construct(); // Calling parent constructor.
      echo "A new constructor in " . __CLASS__ . ".<br />";
  }
 
  public function newMethod()
  {
      echo "From a new method in " . __CLASS__ . ".<br />";
  }
}

Static member functions.


class MyClass
{
  public static $count = 0;
 
  public static function plusOne()
  {
      return "The count is " . ++self::$count . ".<br />";
  }
}
 
do {
  // Call plusOne without instantiating MyClass
  echo MyClass::plusOne();
} while ( MyClass::$count < 10 );

Namespaces

Namespace names PHP and php, and compound names starting with these names (like PHP\Classes) are reserved for internal language use and should not be used in the userspace code.

The only code construct allowed before a namespace declaration is the declare statement, for defining encoding of a source file. In addition, no non-PHP code may precede a namespace declaration, including extra whitespace:


<html> <!-- This is what causes fatal error. -->
<?php
declare(encoding='UTF-8'); // Only this is allowed before namespace.
namespace MyProject; // fatal error - namespace must be the first statement in the script
?>

The same namespace may be defined in multiple files, allowing splitting up of a namespace's contents across the filesystem.

Multiple namespaces in the same file

Simple combination syntax:


namespace MyProject;

const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */  }

namespace AnotherProject;

const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */  }

Bracketed syntax (and unnamespaced code):


namespace MyProject {

const CONNECT_OK = 1;
class Connection { /* ... */ }
function connect() { /* ... */  }
}

namespace MyProject2 {
...
}

namespace { // global code
session_start();
$a = MyProject\connect();
echo MyProject\Connection::start();
}

Using namespaces

file1.php


<?php
namespace Foo\Bar\subnamespace;

const FOO = 1;
function foo() {}
class foo
{
    static function staticmethod() {}
}
?>

<?php
namespace Foo\Bar;
include 'file1.php';

const FOO = 2;
function foo() {}
class foo
{
    static function staticmethod() {}
}

/* Unqualified name */
foo(); // resolves to function Foo\Bar\foo
foo::staticmethod(); // resolves to class Foo\Bar\foo, method staticmethod
echo FOO; // resolves to constant Foo\Bar\FOO

/* Qualified name */
subnamespace\foo(); // resolves to function Foo\Bar\subnamespace\foo
subnamespace\foo::staticmethod(); // resolves to class Foo\Bar\subnamespace\foo,
                                  // method staticmethod
echo subnamespace\FOO; // resolves to constant Foo\Bar\subnamespace\FOO
                                  
/* Fully qualified name */
\Foo\Bar\foo(); // resolves to function Foo\Bar\foo
\Foo\Bar\foo::staticmethod(); // resolves to class Foo\Bar\foo, method staticmethod
echo \Foo\Bar\FOO; // resolves to constant Foo\Bar\FOO
?>

namespace keyword and __NAMESPACE__ constant


<?php
namespace MyProject;

function get($classname)
{
    $a = __NAMESPACE__ . '\\' . $classname;
    return new $a;
}
?>

namespace keyword is the equivalent of the self operator for classes.


<?php
namespace MyProject;

use blah\blah as mine; // see "Using namespaces: Aliasing/Importing"

blah\mine(); // calls function MyProject\blah\mine()
namespace\blah\mine(); // calls function MyProject\blah\mine()

namespace\func(); // calls function MyProject\func()
namespace\sub\func(); // calls function MyProject\sub\func()
$b = namespace\CONSTANT; // assigns value of constant MyProject\CONSTANT to $b
?>

Aliasing/Importing

Similar to the symbolic links of unix-based filesystems.


use My\Full\Classname as Another, My\Full\NSname;

$obj = new Another; // instantiates object of class My\Full\Classname
NSname\subns\func(); // calls function My\Full\NSname\subns\func

// Importing is performed at compile-time, and so does not affect dynamic class, function or constant names.
$a = 'Another';
$obj = new $a;      // instantiates object of class Another

Fall back to global


namespace A\B\C;
class Exception extends \Exception {}

$a = new Exception('hi'); // $a is an object of class A\B\C\Exception
$b = new \Exception('hi'); // $b is an object of class Exception

$c = new ArrayObject; // fatal error, class A\B\C\ArrayObject not found

Function Reference

Var and Type related extensions

Arrays

array_merge


 = array("color" => "red", 2, 4);
 = array("a", "b", "color" => "green", "shape" => "trapezoid", 4);
 = array_merge(, );
print_r();

// Result:
Array
(
    [color] => green
    [0] => 2
    [1] => 4
    [2] => a
    [3] => b
    [shape] => trapezoid
    [4] => 4
)

 = array();
 = array(1 => "data");
 = array_merge(, );

// Result is re-numbered:
Array
(
    [0] => data
)

///// Compare to + operator:
 = array(0 => 'zero_a', 2 => 'two_a', 3 => 'three_a');
 = array(1 => 'one_b', 3 => 'three_b', 4 => 'four_b');
 =  + ;
var_dump();

// Result (The keys from the first array will be preserved. If an array key exists in both arrays, then the element from the first array will be used and the matching key's element from the second array will be ignored):

array(5) {
  [0]=>
  string(6) "zero_a"
  [2]=>
  string(5) "two_a"
  [3]=>
  string(7) "three_a"
  [1]=>
  string(5) "one_b"
  [4]=>
  string(6) "four_b"
}

Redirect in PHP

References: StackOverflow.


// Core code.
header('Location: '.$newURL);
exit(); // See below for explanation.

Status codes

TheDailyWTF page gave an example that a bot/crawler may neglect HTTP headers and bypass all security check, finally delete all web pages.


// The old code which has a security issue.
if(!isset($_SESSION['usr_id']) || !isset($_SESSION['usr_name']))
{
	header('Location: index.php');
}

// Add die() here.
if(!isset($_SESSION['usr_id']) || !isset($_SESSION['usr_name']))
{
	header('Location: index.php');
	exit();
}

Use exit() or die()?

commenter @tgape in the WTF story says "exit()" should be used instead of "die()":
If there is a die immediately after a header redirect, the code will always hit it, and your error logs will fill up with useless "errors".

Alternatives


<meta http-equiv="Location" content="http://example.com/">

Or a Javascript redirect.