PHP tips/tricks/HOWTOs
HOWTO: Install PHP
OS-specific instructions follow; see below for general information about switches and environment variables.
OS X 10.5 Leopard
Install, via port, libxml2, libxslt, libiconv, gd2 (+no_x11), freetype, sqlite3.
Download from:
<http://uk.php.net/get/php-5.3.0.tar.gz/from/a/mirror>
Configure with:
$ export PHP_ROOT=/usr/local/php-5.x.y
$ ./configure --prefix=$PHP_ROOT \
--enable-fastcgi --with-xsl=/Ports --with-libxml-dir=/Ports \
--with-gd=/Ports --with-jpeg-dir=/Ports --with-pdo-sqlite=/Ports \
--without-sqlite --without-sqlite3 --with-freetype-dir=/Ports \
--with-ttf=/Ports --enable-calendar --with-zlib=/Ports --with-iconv \
--with-openssl --enable-discard-path --enable-bcmath --with-curl
$ make
$ make install
$ cp php.ini-recommended $PHP_ROOT/lib/php.ini
$ jed $PHP_ROOT/lib/php.ini # set extension_dir to $PHP_ROOT/php-config --extension-dir
OS-specific notes (see below for general notes):
-
This doesn't install the MySQL library, because it's a pain. If you want MySQL, then add:
--with-mysql=$MYSQL --with-pdo-mysql=$MYSQLWhere
$MYSQLis where the MySQL client libraries and header files are installed. (e.g.$HOME/localor/usr--you can't install MySQL into separate "binary" and "shared" directories.) These are installed as part of the MySQL server distribution, but if you only want to install the client libraries, download the source and configure with--without-server. Do not install the library itself and header files into separate directories (i.e. do not use--exec-prefix)--the PHP configure script can't deal with these being in separate directories. If compiling with some versions of OS X (10.5.0, 10.5.4, 10.5.5 and 10.5.6 seem to be affected, at least), replace
/usr/include/iconv.hwith MacPorts' version before configuring, to preventiconvlink errors.
Ubuntu 10.04
Install the likely module suspects:
libjpeg62-dev libxslt1-dev libcurl4-openssl-dev libssl-dev
libsqlite3-dev libgd2-noxpm libpng12-dev libfreetype6-dev
libmysqlclient16-dev # optional?
Download from:
<http://php.net/downloads.php>
Configure with:
$ export PHP_ROOT=/usr/local/php-5.x.y
# For PHP 5.3.0
$ ./configure --prefix=$PHP_ROOT --with-xsl=/usr \
--with-libxml-dir=/usr --with-gd --with-pdo-sqlite=/usr \
--without-sqlite3 --without-sqlite --with-freetype-dir=/usr \
--enable-calendar --with-zlib --with-iconv --with-openssl \
--with-jpeg-dir=/usr/lib --with-png-dir=/usr/lib --enable-bcmath \
--disable-xmlreader --disable-xmlreader --enable-mbstring \
--without-pear --with-config-file-scan-dir=/usr/local/etc/php.d
--with-mysql --with-pdo-mysql # these two optional?
# For PHP 5.2.x
$ ./configure --prefix=$PHP_ROOT \
--enable-fastcgi --with-xsl=/usr --with-libxml-dir=/usr \
--with-gd --with-pdo-sqlite=/usr --without-sqlite \
--with-freetype-dir=/usr --with-ttf=/usr --enable-calendar \
--with-zlib --with-iconv --with-openssl --enable-discard-path \
--with-jpeg-dir=/usr/lib --with-png-dir=/usr/lib --with-mysql \
--with-pdo-mysql --enable-bcmath --with-curl
$ make
$ make install
# For PHP 5.3.0
$ cp php.ini-development $PHP_ROOT/lib/php.ini
# or
$ cp php.ini-production $PHP_ROOT/lib/php.ini
# For PHP 5.2.x
$ cp php.ini-recommended $PHP_ROOT/lib/php.ini
# set extension_dir to $PHP_ROOT/bin/php-config --extension-dir
$ jed $PHP_ROOT/lib/php.ini
OS-specific notes (see below for general notes):
- Note that for some reason the
--with-jpeg-dirand--with--dirdirectory parameters specify the location of their respective libraries, not the root. (I don't know why either of these is necessary; for some reason the bundled GD doesn't come with JPEG and PNG libraries.)
SunOS (not recently tested)
Install libxml2, libxslt, gd, libjpeg, libpng, zlib (configure zlib with --shared, otherwise you'll get link errors), then:
$ lconfigure --with-apxs2=$LOCAL/bin/apxs \
--with-xsl=$LOCAL --with-libxml-dir=$LOCAL --with-gd=$LOCAL \
--with-jpeg-dir=$LOCAL --with-png-dir=$LOCAL --with-zlib-dir=$LOCAL \
--enable-debug --with-mysql=/usr/local/mysql --enable-calendar
(Might also need to ln -s $HOME/local/include to $LOCAL/include--one
of the dependencies couldn't find the include files from the
architecture-independent directory.)
Windows/win32 (not recently tested)
Get Apache running first.
Download the "ZIP package".
-
Add something like the following to httpd.conf:
LoadModule php5module "C:/server/php-5.2.4/php5apache22.dll" PHPIniDir "c:/server/php-5.2.4"
(Probably:) Copy php.ini-recommended to php.ini, and tweak as required. (If enabling modules, be sure to set extension_dir!)
Add your PHP directory to PATH, so that various supporting DLLs (e.g. libmysql.dll, libeay32.dll) can be loaded automatically. (How to modify the PATH.)
-
(optional) Install the Zend debugger
i. Download site. (The "cygwin_nt-i386" version works fine with the regular Windows binaries.)
i. Put the ZendDebugger.dll from the 52x_comp (thread-safe) directory into your PHP extensions directory. (Probably C:\server\php-5.2.4\ext.)
i. Modify
php.ini, as described in theREADME.txt.i. Restart Apache. A phpinfo() call should mention the debugger.
i. (After all this, couldn't get breakpoints working.)
-
(optional) Install the Xdebug debugger
i. Download site.
i. Put the php_xdebug-2.0.0-5.2.2.dll into the PHP extensions directory. (Probably C:\server\php-5.2.4\ext.)
i. Add the following to
php.ini:zend_extension_ts=c:/server/php-5.2.4/ext/php_xdebug-2.0.0-5.2.2.dll xdebug.remote_enable = On xdebug.remote_host=10.171.99.124i. Restart Apache. A phpinfo() call should mention the debugger.
i. More info
General Installation Notes
-
$PHP_ROOTspecifies the root of your PHP installation and will probably be something like$ export PHP_ROOT=$HOME/local-linux/php-5.2.6or
$ export PHP_ROOT=/usr/local/php-5.3.0After PHP is installed with
make install,$PHP_ROOT/bin/phpwill be your PHP binary. You may want to remove
--without-pearif you need PEAR.You can also drop the
--without-sqliteto use the bundled sqlite3. (In this case you also don't need to install sqlite3 via port.)The directory specified by
--prefixdetermines where PHP is installed. The php and php-cgi binaries can be safely moved to other locations, however a few scripts have this location hardcoded, and won't work if the binaries are moved (phpize,pear).--enable-discard-pathsupposedly eliminates a security problem.--with-curlprovidescurlsupport. This is potentially unnecessary. (Zend_Http_Clientdoes not use it.)--enable-pearand--disable-xmlare incompatible:pearrequiresxml.-
- Zend_OpenId requires
--enable-bcmath. - ZendRestClient_Result requires
--enable-simplexml.
- Zend_OpenId requires
--enable-mbstringis needed formb_encoding_convert. Is this really necessary? It seems to make the PHP binary a whole lot bigger!
HOWTO: Install Generic PECL Extension
(See below for instructions for specific extensions.)
Configure, build and install:
$ $PHP_ROOT/bin/phpize
$ ./configure --with-php-config=$PHP_ROOT/bin/php-config
$ make
$ mkdir -p $($PHP_ROOT/bin/php-config --extension-dir)
$ cp modules/*.so $($PHP_ROOT/bin/php-config --extension-dir)
Or, in one line:
$ $PHP_ROOT/bin/phpize && \
./configure --with-php-config=$PHP_ROOT/bin/php-config && \
make && \
mkdir -p $($PHP_ROOT/bin/php-config --extension-dir) && \
cp modules/*.so $($PHP_ROOT/bin/php-config --extension-dir)
Modify php.ini files as appropriate, adding the line
extension=new_module.so
You do not need to specify the full pathname. At a minimum, you'll probably want to modify:
$ $EDITOR $PHP_ROOT/lib/php.ini
Some common modules:
-
APC - Note that the APC
distribution has a file
apc.phpthat provides some cache statistics that you may wish to install on your server. -
memcache - Note that
the memcache distribution has a file
memcache.phpthat provides some cache statistics that you may wish to install on your server. Unlikeapc.phpit includes its own HTTP authentication system, so if you're adding this to a directory that already password protected (by Apache, say), you'll probably want to remove this.
HOWTO: Install Xdebug
Download from:
<http://www.xdebug.org/download.php>
Configure, compile and install as above.
When editing php.ini and add the line:
zend_extension=/full/path/xdebug.so
(Xdebug itself can actually be installed anywhere on the filesystem.)
HOWTO: Install memcached
Download and install libmemcached (not the same as the libmemcache-dev
Debian package!):
<http://tangent.org/552/libmemcached.html>
Download:
<http://pecl.php.net/package/memcached/>
Configure, make and install as above.
HOWTO: Run your own version of PHP on Dreamhost (not recently tested)
Install libxml2, libxslt, then:
$ lconfigure --enable-fastcgi --with-xsl=$LOCAL \
--with-libxml-dir=$LOCAL --with-gd --with-ttf=/usr \
--with-freetype-dir=/usr --enable-calendar
(Uses their gd, ttf, freetype, etc.)
To install:
$ make install
Stripping the binary will save a lot of memory (optional):
$ strip `which php`
Note that this doesn't install the full command-line version (cli). To get that you need to
$ make install-cli
however the command-line version has the same filename--this installs a new "php" binary over the top of your old one. (? I think this changed around 5.2.3.)
To get Dreamhost's Apache to run your php under FastCGI, you need
these lines in your .htaccess:
# Remove the default action for *.php files.
RemoveHandler php
# For some reason the following really does need to be called
# dispatch.fcgi. The contents of dispatch.fcgi:
#
# #!/usr/bin/env bash
#
# exec ./php
#
# DOCUMENT_ROOT/cgi is symlinked to $LOCAL/bin. Dreamhost's config
# seems to have already configured fastcgi-script for *.fcgi.
Action php-fastcgi /cgi/dispatch.fcgi
AddType php-fastcgi html
AddType php-fastcgi php
HOWTO: Handle standard input and output
TIP: Predefined variables
http://php.net/reserved.variables
TIP: Object oriented programing/inheritance
TIP: String concatenation/string operators
Use "." for concatenation; see the PHP manual for more.
HOWTO: Break out of a loop
Use "break".
TIP: Documentation of control structures
http://php.net/manual/en/language.control-structures.php
Includes the alternative syntax.
TIP: Regular expression example
if (!preg_match("/^foo/", "some string")) {
# ...
}
GOTCHA: ODBC
This doesn't work in PHP:
$sth = odbc_prepare($dbh, $sql);
foreach (...) {
$res = odbc_execute($sth, $arg);
...
}
(The prepared statement gets mashed somewhere--move the odbc_prepare()
into the loop...)
GOTCHA: MDB2's SQLite supports SQLite2, not SQLite3!
True! You need to use PDO.
HOWTO: Set the include path from the command line
i.e. the equivalent of PERL5LIB, PYTHONPATH,
RUBYLIB, etc.:
$ php -d include_path=$PHPLIB
HOWTO: Create a static constructor
This doesn't seem to be possible in PHP; the best way is to do something like:
Foo::$bar = "hullo, world"!;
class Foo {
public static $bar;
}
HOWTO: Static (class) variables
class Foo {
static $bar = null;
function quux() {
return self::$bar;
}
}
HOWTO: Retrieve multiple values/process checkboxes, and multiple selects
Give the variable a name that ends in "[]". If there are multiple keys with the same value, and the keys end in "[]", PHP creates an array of values for that value. i.e. if the HTML looks like
<select multiple name="beer[]">
<option value="warthog">Warthog</option>
<option value="guinness">Guinness</option>
<option value="stuttgarter">Stuttgarter</option>
</select>
and the user selects multiple beers, then
gettype($_REQUEST["beer"]) == "array"
See:
http://www.php.net/variables.external
HOWTO: "apply" the PHP way
Use call_user_func_array():
call_user_func_array("foo", array(1, 2, 3));
Note that this can also be used to call a method:
call_user_func_array(array($obj, $method), array(1, 2, 3));
HOWTO: Create MySQL-compatible date string format
date("Y-m-d H:i:s")
HOWTO: Convert XHTML entities to XML
If you need to convert e.g. ’ to ’ do something like:
$table = array(
'Á' => 'Á',
'á' => 'á',
...
);
$s = strtr($s, $table);
The Wikipedia source contains an entity conversion table.
TIP: Error control operator (@)
@ as a prefix suppresses any warning or error that might otherwise be
emitted.
Note that this works with both method calls and assignments:
$res = @$doc->loadXML($string);
$foo = @$GET_["foo"];
(Other error handling functions.)
HOWTO: Convert a UTF-8/Unicode string to XML/HTML entities
Use
[mb_encode_numericentity](http://php.net/manual/en/function.mb-encode-numericentity.php). The exact arguments seem somewhat hard to come by; this is my current best effort:
$map = array(
0x0000, 0x001f, 0, 0xffff,
0x0026, 0x0026, 0, 0xffff, // &
0x003c, 0x003c, 0, 0xffff, // <
0x003e, 0x003e, 0, 0xffff, // >
0x007f, 0xffff, 0, 0xffff
);
mb_encode_numericentity($s, $map, 'utf-8');
GOTCHA: error_log() quotes backlashes
echo("\\hello\\") -> \hello\
error_log("\\hello\\") -> \\hello\\
WART:
odbc_execute($sth, $a);
If any of the element of $a begin and end with a single quote, the bit
in between is interpreted as a filename, the contents of which are
inserted.
WART:
Very strange arguments in php.ini:
; Define the probability that the 'garbage collection' process is started
; on every session initialization.
; The probability is calculated by using gc_probability/gc_divisor,
; e.g. 1/100 means there is a 1% chance that the GC process starts
; on each request.
session.gc_probability = 1
session.gc_divisor = 1000
WART:
Include is a "special language construct", which means that these two things are not equivalent:
if ($condition)
include $this;
else
include $that;
and
if ($condition) {
include $this;
} else {
include $that;
}
WART:
array_filter() and array_map() take their arguments in opposite order:
array array_filter ( array input [, callback callback] )
array array_map ( callback callback, array arr1 [, array ...] )
WART:
imageepsbbox returns an array of four values giving the bottom left
and top right coordinates of a given string.
imagettfbbox returns an array of eight values, giving the coordinates
of all four corners of a given string.
WART:
parse_str() parses--guess what?--a query string. (Also, the inverse
is http_build_query().)
More unfortunately-named pairs:
-
htmlspecialchars()/htmlspecialchars_decode() -
htmlentities()/html_entity_decode()
WART:
The insanity of:
isset($foo)
empty($foo)
is_null($foo)
$foo
(Could possibly add array_key_exists() and defined() to this list too.)
Note also that empty(trim($foo)) doesn't work--the argument to empty()
needs to be a variable, not an expression.
See also:
http://php.net/types.comparisons
WART:
include() is relative to the original file, not the included file.
See:
http://bugs.php.net/bug.php?id=9673
You can include() relative to the included file with:
include(dirname(__FILENAME__) . "/../$filename");
HOWTO: Interpolate complex array/object references
Like this:
echo "This works: {$obj->values[3]->name}";
See:
http://php.net/manual/en/language.types.string.php#language.types.string.parsing.complex
FAQ: How to call parent constructor
parent::__construct(...);
FAQ: How to use a custom statement class with PDO?
Comment describing how to extend PDOStatement (not tested).
FAQ: Why does addition/subtraction not work! (Operator precedence)
The operators "+", "-" and "." have the same precedence. This means that e.g.
error_log("elapsed time = " . $t1 - $t0)
doesn't do what you expect--it evaluates as
error_log(("elapsed time = " . $t1) - $t0)
(This is the same as Perl.)
(The full operator precedence table. Note the Perl-like low precedence "and", "xor", "or".)
GOTCHA: parse_ini_file() returns unexpected results
"true", "on", "yes", "1" are converted to "1" (the number 1, as a string).
"false", "off", "no" are converted to "" (the empty string).
"0" is not converted, and is returned as "0" (the number 0, as a string).
Because of this behaviour, and the way values are compared, when
checking for a boolean value via parse_ini_file() (i.e. whether some
setting is true or false), you should simply use if ($value) { ... }
instead of trying to be clever with if ($value == true) { ... },
etc.
GOTCHA: Array iterators pass by value, not reference
$data = array(array(), array());
print_r($data);
foreach ($data as $d) {
$d[0] = "qqq";
}
print_r($data);
GOTCHA: Arithmetic comparison: 0.0 !== 0
0.0 == 0, but 0.0 !== 0. For some reason this isn't listed in the type
comparison table.
HOWTO: Pretty-print an array
print_r(), var_export() and the like output a line per key => value
pair. If you want a few key => value pairs per line, try something
like the following ($table is the original array):
$a = array();
foreach ($table as $k => $v) {
$a[] = sprintf("%11s => %9s,", "'{$k}'", "'{$v}'");
}
for ($i = 0; $i < count($a); $i++) {
echo $a[$i], " ";
if (($i + 1) % 5 === 0) {
echo "\n";
}
}
(Quick hack, doesn't handle ' in either the key or value, for example.)
HOWTO: Extend PDO and use __call() within functions
This doesn't work, and is a bug, at least as of PHP 5.2.5.
It can be fixed by applying a patch and re-compiling.
ERROR: Install fails with libgcrypt error
This happens if you're building with XSL (--with-xsl) and libgcrypt
isn't available. You need to install both libgcrypt and its
dependency libgpg-error:
(Or add --without-xsl to your ./configure line.)
ERROR: "Unable to load dynamic library XXX"
(Followed by "The specified module could not be found", and where XXX actually exists.)
PHP seems to produce this error fairly indiscriminately if the module can't
be loaded for any reason at all, not just in the case where the apparently
missing module doesn't exist on the filesystem. For example, it can happen
if you neglect to include a dependency of the named module, such as if you
load php_pdo_oci.dll without loading php_pdo.dll.
It can also happen if an external dependency can't be found (database
DLLs?) or the wrong version is being found (Apache DLLs? Windows
DLLs?). (The PATH is searched for DLLs, but DLLs can come from other
places as well, such as Apache's bin directory.)
If you're having trouble with php_mysql.dll, make sure that
libmySQL.dll can be found.
If you're having trouble with php_pdo_oci.dll, make sure the Oracle
client libraries can be found.
If you're having trouble with php_openssl.dll, make sure libeay32.dll
can be found, and that the wrong version (Apache's?) isn't being
found.
FAQ: What's the syntax for PDO DSNs?
- MySQL
- Oracle
- Other databases - load the PDO documentation, select the driver you want, the select the "next" page using the navigation at the top or bottom.
Username and password are specified as follows:
$dbh = new PDO($dsn, $username, $password);
HOWTO: eval() a string as if it were a PHP file
i.e. a function like include_string($string) to parallel
include($filename).
eval($string) evaluates $string as if it were PHP code. If you want to
eval a string that looks like a PHP file (i.e. a string that contains
<?php and ?>), do:
function include_string($string) {
eval('?>' . $string . '<?php ');
}
(Astonishing that this works. What is the parser/interpreter doing there?!)
This is documented, somewhat misleadingly, on the eval manpage.
ERROR: "MDB2 Error: unknown error"
This less than helpful message may be emitted if a pragma command fails.
(You do get slightly more helpful error messages if there's an error in your
SQL proper.) For example, this error will be emitted if you set the charset
to a character set that doesn't exist. To diagnose the problem, it might
help to do a var_dump() on the database handle or statement
handle--sometimes useful information is embedded there.
HOWTO: Upload large files
Despite appearances, the largest file you can upload is affected by several
php.ini settings:
upload_max_filesize-
post_max_size -
memory_limit(possibly)
It's possible that since the uploaded file needs to be encoded, which increases their size, these limits need to be larger than you think.
TIP: Information about the FastCGI version of PHP
See sapi/cgi/README.FastCGI in the source.
HOWTO: Serialize a DOMNode or DOMElement to a string
i.e. the equivalent of toString() or asString() in other
implementations.
Use the saveXML() method on the associated document:
echo $doc->saveXML($node);
Or, if you don't have the owner document handy:
echo $node->ownerDocument->saveXML($node);
FAQ: Where's the inverse of strftime?
As far as I can tell, there isn't one.
strtotime,
date_parse or--if you're using
WordPress--mysql2date might do in some circumstances.
HOWTO: Access raw POST data
Use php://input:
$data = file_get_contents("php://input");
The POSTed data is URL-encoded, so you may need to decode it first:
$data = urldecode(file_get_contents("php://input"));
HOWTO: Use Zend_Mail with Google Mail's SMTP server
$config = array(
'auth' => 'login',
'username' => "XXXX@gmail.com",
'password' => "XXXX",
'ssl' => 'ssl', // not 'tls'
'port' => 465
);
$transport = new Zend_Mail_Transport_Smtp('smtp.gmail.com', $config);
$mail = new Zend_Mail();
$mail->setBodyText('This is the text of the mail.');
$mail->setFrom('sender@test.com', 'Some Sender');
$mail->addTo('mjs@beebo.org', 'Some Recipient');
$mail->setSubject('TestSubject');
$mail->send($transport);
See configuring other mail clients.
HOWTO: Convert an object to an array
Convert an object (i.e. $user->name) to an array (i.e. $user["name"]):
$arr = (array) $obj;
If you have nested objects you'll need to convert it manually:
function object_to_array($obj) {
if (!is_object($obj) && !is_array($obj)) {
return $obj;
}
else {
$a = array();
foreach ($obj as $k => $v) {
$a[$k] = object_to_array($v);
}
return $a;
}
}
(Might be able to use json_encode/json_decode as well.)
HOWTO: Log reliably
file_put_contents("/tmp/log", var_export($foo, true), FILE_APPEND | LOCK_EX);
HOWTO: Dump stack reliably
$a = array();
foreach (debug_backtrace() as $s) {
$a[] = array(
"file" => $s["file"],
"link" => $s["line"]
);
}
rawlog($a);
FAQ: How can I prevent content from being cached?
It's up to the browser whether it obeys this, but you might have have success with:
header("Pragma: no-cache");
header("Cache-Control: private, no-cache, no-cache=\"Set-Cookie\", proxy-revalidate");
(From Google Analytics headers, I think.)
FAQ: Why use array_key_exists to check if a key exists?
i.e. why not use isset()? The reason is that isset() can return true if
the thing you're checking isn't an array at all, but a string:
$foo = "asdf";
$v = isset($foo['qq']); // $v is true!
This is because the string 'qq' is cast to the number 0, and $foo[0]
is the first letter of the string $foo.
TIP: Quick code to convert SQL with bound parameters to a straight string
$sql = "SELECT * FROM entry WHERE email = ?";
$args = array("michael@example.com");
foreach ($args as $a) {
$sql = preg_replace("/\?/", is_numeric($a) ? $a : "\"" . $a . "\"", $sql, 1);
}
// $sql = "SELECT * FROM entry WHERE email = 'michael@example.com'";
(If you're doing this to figure out what SQL code is being executed against the database it may be faster to turn on MySQL query logging.)
FAQ: What's the deal with PHP's time functions?
Some things to know:
- A "Unix timestamp" or "epoch" refers to the number of seconds since
1970-01-01 00:00:00 UTC. (i.e. a point in time in a specific time zone.)
A Unix timestamp is never timezone-specific; if you call
time()at the same moment on computers in different time zones, you get exactly the same value back. -
mktime/gmmktime- Passed an array giving whose values are day, month, year, etc., returns a Unix timestamp.mktimeinterprets its argument as a local time, whilstgmmktimeinterprets its argument as a time in the time zone UTC. (That is, given the same inputgmmktimereturns the same results everywhere;mktimereturns timezone-specific results.) Note that in this case, thegm-prefix affects how the input is interpreted. -
strftime/gmstrftime- Passed a Unix timestamp and format string, and returns a string. Instrftime's case, the string is the time according to the current timezone, whilstgmstrftimereturns the time in the UTC timezone. (Given the same input,gmstrftimereturns the same time in all timezones (though not necessarily the same string--the actual string may be different if the locale is different) whilststrftimereturns timezone-specific results.) Note that in this case, thegm-prefix affects the output string. -
strptime- Inverse ofstrftime/gmstrftime: passed a time string and a format string, and returns an array representing the local time. (This not a great return value; it would have been better to return a Unix timestamp.) The time string is interpreted as a local time; there is nogm-equivalent, or even any way to simulate one, since it ignores the value ofdate_default_timezone_set. Note that you can impose a timezone on the input string if it contains a timezone abbreviation or offset (e.g.Sun 26 Apr 2009 21:50:35 BST) which the format string reads with%zor%Z. -
date/gmdate- Passed a Unix timestamp and a format string, returns a string. As withstrftime/gmstrftime, thegm-prefix affects whether the result is a representation of the time in the current timezone or in the UTC timezone. Note that the format string is completely different to that ofstrftime/gmstrftime! (One reason to use this set of functions is for the useful date format constants.) There is no inverse of this function. -
strtotime- Passed a string in "US English date format", and returns a Unix timestamp. Note that there is no way to override the US date format!strtotime("03/04/2008")is the 4th of March 2008. Note that this function will parse relative times, liketomorrowandnext monday; this is about the only reason to use it. - How does PHP know what your current timezone is? It tries a few
different places, including the
TZenvironment variable and thedate.timezoneini option. (Seedate_default_timezone_getfor more information.)
ERROR: "make test" fails with "Unable to load dynamic library"
Run with:
$ TEST_PHP_ARGS=-n make test
FAQ: What's going on with my static properties?
There's only ever one instance of class-static variables (or static properties)--even if the class is extended. (The derived classes do not get their own copies of the variable--it's shared with the parent and all other classes that are derived from the same base.
That is, if you have
class Base {
public static $data;
}
class Derived extends Base {
}
then Base::$data and Derived::$data refer to the same variable. (Within
both methods, self::$data similarly refers to the same thing.)
FAQ: How to run individual/selected PHP tests?
To test the /usr/local/php-5.3.0/bin/php binary using the phpt files in
ext/xsl/tests,
$ TEST_PHP_EXECUTABLE=/usr/local/php-5.3.0/bin/php sapi/cli/php run-tests.php ext/xsl/tests
(Can replace the directory with individual files as well.)
FAQ: How to compile from svn checkout?
See http://www.php.net/svn.php.
Note if you're building on a virtual machine, you may wish to do the
checkout on the virtual machine, rather than on the host. This is because
the buildconf script seems to run svn under some circumstances, and if
the version of svn on the virtual machine is older than the version which
checkout out the source, it will fail.
FAQ: How to debug with gdb?
If you have a broken test that you want to debug with gdb, you'll probably
still have the *.php file in a tests directory. (If the test fails,
run-tests.php keeps the generated parts.) In that case, you can debug
with gdb via something like:
$ gdb --args sapi/cli/php ext/xsl/tests/*method1.php
HOWTO: Install pear
[Edit: I don't recommend doing this anymore. pear causes a lot of
confusion and problems when installed with PHP, or separately. (In fact it
doesn't seem to be possible to install it separately, the INSTALL file
notwithstanding.)]
There's a few problems with the bundled pear: it gets confused, and it
also wants to install iself once for every PHP binary installed. It seems
to be slightly better to install pear separately (although there's
problems with this approach as well...).
- Download
go-pear.phpfrom http://pear.php.net/go-pear. - Start the installer with
php go-pear.php. - Change the "Installation prefix" to
/usr/local. - Don't let it edit
php.ini.
HOWTO: Install PHPUnit
- Download from http://pear.phpunit.de/get/.
- Once extracted, copy the
PHPUnitdirectory somewhere like/usr/local/lib/php. - Rename
phpunit.phptophpunit, and then amend it so that it usesset_include_path()to add/usr/local/lib/phpto theinclude_path. - Copy
phpunitto/usr/local/bin/phpunit. - Enjoy!
FAQ: Xdebug doesn't "break"
If Xdebug seems to be working fine (e.g. it's listed in phpinfo()),
and your client (e.g. NetBeans) isn't complaining that it couldn't
connect then the problem could be that it's being loaded as an
extension instead of a zend_extension. (Note that if you load it
"twice", first as an extension and once as an zend_extension, the
first will take precedence, and you won't be given any warning that
anything went wrong. More
info.)
HOWTO: Troubleshoot Xdebug problems
Check whether the xdebug extension appears in phpinfo() output
Check that it's being loaded via zend_extension
Comment out this line, and see that it isn't loaded, to make sure
it's not being loaded by an extension line somewhere else.
Check that you can connect to the client from the server
You should be able to telnet mel.beebo.org 9000 and have something
accept your connection. (There doesn't seem to be any "ping" command
or similar that is guaranteed to generate a response, unfortunately.)
Check that the server is responding as expected
It's probably easiest and most reliable to use the command-line
debugclient that comes with Xdebug
for this. (Compilation
instructions; it's a
standalone executable; you don't need to install it with make
install.)
When you run it, it will start listening on port 9000. Configure Xdebug with something like:
xdebug.remote_enable = 1
xdebug.remote_host = mel.beebo.org
Load a URL like
http://beebo.local/?XDEBUG_SESSION_START=netbeans-xdebug and Xdebug
should attempt to connect to the debugclient--you'll see a message.
In the client, enter
status -i qqqq
and you should receive a response from the server. (The -i qqqq is
merely to identify the session; the value shouldn't be important.)
If you next enter
step_into -i qqqq
you should receive a response from Xdebug indicating that it has stopped, the filename and line number, etc. (If it doesn't stop, see the above FAQ!)