GETTING STARTED
A good graphical ide is Netbeans with the php pack. Or install cygwin and the php interpreter
php can be run from the command line:
file: yourscript.php
<?php
echo "hello world";
?>
Then to execute run (assuming php exe is in PATH)
php yourscript.php
To syntax check a script you can run (like lint):
php -l yourscript.php
Notes: The start tag is required. The closing tag of a php block at the end of a file is optional, and in some cases omitting it is helpful when using include() or require() so unwanted whitespace will not occur at the end of files, and you will still be able to add headers to the response later. It is also handy if you use output buffering, and would not like to see added unwanted whitespace at the end of the parts generated by the included files.
Otherwise, everything outside of the tags are interpreted as string literal
<?php ?> tags cannot be nested inside another <?php ?> tag
and ; at end of commands is required
Print out server config
<?php echo phpinfo(); ?>
Print contents of data structure or object
<?php var_dump($somevar); ?>
The log file is defined in php.ini (global php config file)
log_errors = On
error_log = C:\temp\php_error.log
To run as a shell script, add to top of file
#!/usr/bin/env php
TESTING COMPATIBILITY
# test code in multiple php versions
http://3v4l.org/UCALa
PRINTING
To print a string to STDOUT, use:
echo "hello world";
print "hello world";
COMMENTS
# single line comment (Perl style)
// single line comment (Javascript style)
/* multi line comments */
LOGICAL OPERATORS
Example Name Result
$a and $b And TRUE if both $a and $b are TRUE.
$a or $b Or TRUE if either $a or $b is TRUE.
$a xor $b Xor TRUE if either $a or $b is TRUE, but not both.
! $a Not TRUE if $a is not TRUE.
$a && $b And TRUE if both $a and $b are TRUE.
$a || $b Or TRUE if either $a or $b is TRUE.
COMPARISON OPERATORS
Example Name Result
$a == $b Equal TRUE if $a is equal to $b after type
juggling. EG: '' == 0 == false
$a === $b Identical TRUE if $a is equal to $b, and they are of
the same type. (introduced in php 4)
$a != $b Not equal TRUE if $a is not equal to $b after type
juggling.
$a <> $b Not equal TRUE if $a is not equal to $b after type
juggling.
$a !== $b Not identical TRUE if $a is not equal to $b, or they are
not of the same type. (introduced in php 4)
$a < $b Less than
$a > $b Greater than
$a <= $b Less than or equal to
$a >= $b Greater than or equal to
ARITHMETIC OPERATORS
+ Addition
- Subtraction
* Multiplication
/ Division
% Modulus (division remainder)
++ Increment
-- Decrement
NOTE: there is no exponent ** or ^ operator. Use: pow( base, exponent )
ASSIGNMENT OPERATORS
Operator Example Is The Same As
= x=y x=y
+= x+=y x=x+y
-= x-=y x=x-y
*= x*=y x=x*y
/= x/=y x=x/y
.= x.=y x=x.y
%= x%=y x=x%y
ERROR CONTROL OPERATOR
@ can be prepended to value functions to suppress error
For example:
$text = @file_get_contents('non_existent_file');
$value = @$cache[$key];
Warning: use this carefully. You want to see most errors.
A more acceptable (safer) use is for arrays:
# manually check for null values if needed
$value = @$yourarray['non-existent-key'];
do_some_magic($value);
VARIABLES
Notes: There's no equivalent of "use strict" as in perl. Though you can turn on warnings for use of null variables with the error_reporting E_STRICT flag
declaration and assignment
$a = "asdf";
$b = 2;
$c = NULL;
variables are NULL if:
it has been assigned the constant NULL.
it has not been set to any value yet.
it has been unset().
check NULL value with:
is_null()
or $c === NULL
or $c !== NULL
PARSE COMMAND LINE ARGS
for example:
script.php plain-arg --foo --bar=baz 'plain arg 2' -abc
These will be stored in array $argv
$argv[0] is always the name that was used to run the script.
function parseArgs($argv){
array_shift($argv);
$o = array();
foreach ($argv as $a){
if (substr($a,0,2) == '--'){
$eq = strpos($a,'=');
if ($eq !== false){
$o[substr($a,2,$eq-2)] = substr($a,$eq+1); }
else {
$k = substr($a,2);
if (!isset($o[$k])){ $o[$k] = true; }
}
} else if (substr($a,0,1) == '-'){
if (substr($a,2,1) == '='){
$o[substr($a,1,1)] = substr($a,3);
} else { foreach (str_split(substr($a,1)) as $k){
if (!isset($o[$k])){ $o[$k] = true; } }
}
}
else { $o[] = $a; }
}
return $o;
}
use
$args = parseArgs($_SERVER['argv']);
LOOP OVER STARDARD INPUT
<?php
$f = fopen( 'php://stdin', 'r' );
while( ( $line = fgets( $f ) ) !== false ) {
echo $line;
}
fclose( $f );
DEFINE CONSTANTS
define('DS', DIRECTORY_SEPARATOR);
echo DS;
STRINGS
like with perl, double quoted strings interpolate variables
$a = "hello";
print "$a world";
# Outputs: hello world
Use single quotes for better performance, if possible.
Single quotes are literals, variables are not interpreted.
<?php
echo 'this is a simple string';
echo 'You can also have embedded newlines in
strings this way as it is
okay to do';
echo 'Arnold once said: "I\'ll be back"';
// Outputs: Arnold once said: "I'll be back"
echo 'You deleted C:\\*.*?';
// Outputs: You deleted C:\*.*?
echo 'You deleted C:\*.*?';
// Outputs: You deleted C:\*.*?
echo 'This will not expand: \n a newline';
// Outputs: This will not expand: \n a newline
echo 'Variables do not $expand $either';
// Outputs: Variables do not $expand $either
?>
A string is also an array of characters
NOTE: if you get the first char of a string instead of a string,
code is executing $string[0]... an array assumed where there is none
$s = "hello there";
echo $s[3]; # prints l
PHP heredoc syntax (do not indent closing marker)
$str = <<<EOD
Example of string
spanning multiple lines
using heredoc syntax.
EOD;
NOTE: It is no problem for a string to become very large. php imposes no boundary on the size of a string; the only limit is the available memory of the computer on which php is running.
REPLACE STRINGS
str_replace ( mixed $search , mixed $replace , mixed $subject [, int &$count ] )
It's worth skimming over all string manipulation functions:
http://php.net/manual/en/ref.strings.php
INCLUDE FILE
Code must be loaded into global memory space before it can be called. The following calls will scan the currect folder by default if no path information is given.
try to include, ignore if missing or not found
<?php include "somefile.php"; ?>
try to include, die if file missing
<?php require "somefile.php"; ?>
like include, ignore if already included
<?php include_once "somefile.php"; ?>
like require, die if file missing, only include once
<?php require_once "somefile.php"; ?>
For absolute paths, it is sometimes helpful to define constants like:
// which page are we on? eg /some/path/to/script.php
if( ! defined( 'WEB_PATH' ) ) define('WEB_PATH', $_SERVER['PHP_SELF']);
// web root dir. eg /some/path/to
//if( ! defined( 'WEB_ROOT' ) ) define('WEB_ROOT', dirname(WEB_PATH));
if( ! defined( 'WEB_ROOT' ) ) {
$path = dirname(WEB_PATH);
// avoid "//" at root
if ( $path == '/' ) $path = '';
define('WEB_ROOT', $path);
}
// what is the file name only? // eg script.php
if( ! defined( 'WEB_FILE' ) ) define('WEB_FILE', basename(WEB_PATH));
// physical file path (system). eg: /var/www/html/yoursite
if( ! defined( 'ABS_ROOT' ) ) define('ABS_ROOT', dirname(dirname(__FILE__)));
if( ! defined( 'ABS_ROOT' ) ) define('ABS_ROOT', dirname(__FILE__));
NAME VS ID
On an html form element like <input id="" name="" />
ID is used mostly for javascript
NAME is used for form submission
If the name has [], like:
example[]
then php will parse it as an array of repeating elements.
WARNING: php also performs automatic replacement of special chars in names. For example
name="a.b" becomes "a_b" in $_POST
For safest results, stick with these chars for input names:
alpha number _ [ ]
ARRAYS
Arrays and hashes are the same thing. One uses ints, the other strings.
WARNING: some functions will expect sequential indexes (for example fputcsv). php does not automatically 'fill in' missing indexes.
define an array with:
$arr = array();
assign values with:
$arr[] = 134;
$arr[] = 234;
or
$arr = array( 123, 234 );
define hash with:
<?php
$arr = array("foo" => "bar", 12 => true);
echo $arr["foo"]; // bar
echo $arr[12]; // 1
?>
hash/arrays can be nested any way you want :-)
multidimensional array
<?php
$arr = array("somearray" => array(6 => 5, 13 => 9, "a" => 42));
echo $arr["somearray"][6]; // 5
echo $arr["somearray"][13]; // 9
echo $arr["somearray"]["a"]; // 42
?>
print array
print_r($array);
serialize dump as valid php code
var_export( $array );
iterating with index
$array = array(1, 2);
$count = count($array);
for ($i = 0; $i < $count; $i++) {
echo "\nChecking $i: \n";
echo "Bad: " . $array['$i'] . "\n";
echo "Good: " . $array[$i] . "\n";
echo "Bad: {$array['$i']}\n";
echo "Good: {$array[$i]}\n";
}
array iteration with foreach
foreach ($array as $value) {
}
hash iteration
foreach ($array as $key => $value) {
unset($array[$key]);
}
alternate iteration (older syntax)
while ($el = current($arr)) {
$carr[ $el[$x] ] = $el[$y];
next($arr);
}
NOTE: In order to be able to directly modify array elements within the loop precede $value with &. In that case the value will be assigned by reference. Referencing $value is only possible if the iterated array can be referenced (i.e. if it is a variable).
<?php
$arr = array(1, 2, 3, 4);
foreach ($arr as &$value) {
$value = $value * 2;
}
# $arr is now array(2, 4, 6, 8)
unset($value); // break the reference with the last element, may do inside loop
?>
array functions:
pop and returns the last value of the array,
shortening the array by one element.
array_pop ( $array )
shift an element off the beginning of array
array_shift( $array )
add to end
int array_push ( $array , $var [, $var2... ] )
or,
$your_array[] = "new item";
hash specific
array_values, array_keys
more:
http://www.php.net/manual/en/ref.array.php
ARRAY OPERATORS
Example Name Result
$a + $b Union Union of $a and $b.
$a == $b Equality TRUE if $a and $b have the same key/value pairs.
$a === $b Identity TRUE if $a and $b have the same key/value pairs
in the same order and of the same types.
$a != $b Inequality TRUE if $a is not equal to $b.
$a <> $b Inequality TRUE if $a is not equal to $b.
$a !== $b Non-identity TRUE if $a is not identical to $b.
FUNCTIONS
define functions
<?php
# typical function
function a($n){
b($n);
return ($n * $n);
}
variable pass by reference, use &
function b(&$n){
$n++;
}
echo a(5); //Outputs 36
# WARNING, only variables can be passed by reference!
# array( 1,2,3 ) cannot be passed by ref, it must be assigned to var
?>
NOTE: to access a global variable inside a function, you must re-declare it as global:
$a = 1;
function example() {
print $a; // $a not defined
global $a; // now $a points to variable $a in the global scope
print $a; // $a is 1
}
multiple variables can be declared with , operator:
global $a, $b, $c ;
NOTE: php does not support function overloading, nor is it possible to undefine or redefine previously-declared functions.
However php does allow:
default values to be set to primitives
# variable arguments, default set in def
function example($a, $b=0) {
//$b is optional
}
also the type of the arg can be tested
function do_somthing( $data ) {
if ( is_array( $data ) ) {
// do something
} else {
// do something else
}
}
nested functions:
All functions are declared in the global scope, unless defined in a class (then it's class-scoped)
<?php
function foo()
{
function bar()
{
echo "I don't exist until foo() is called.\n";
}
}
/* We can't call bar() yet
since it doesn't exist. */
foo();
/* Now we can call bar(),
foo()'s processesing has
made it accessible. */
bar();
?>
Both variable number of arguments and default arguments are supported in functions. See also the function references for func_num_args(), func_get_arg(), and func_get_args() for more information.
anonymous functions
Only recent versions of php support the concept of closures.
<?php
$greet = function($name)
{
printf("Hello %s\r\n", $name);
};
$greet('World');
$greet('php');
?>
NOTE: Closures may also inherit variables from the parent scope. Any such variables must be declared in the function header. Inheriting variables from the parent scope is not the same as using global variables
$callback = function ($quantity, $product) use ($tax, &$total)
{
$pricePerItem = constant(__CLASS__ . "::PRICE_" .
strtoupper($product));
$total += ($pricePerItem * $quantity) * ($tax + 1.0);
};
return by reference
function &bar()
{
$a = 5;
return $a;
}
get a reference to a defined function
<?php
echo "test";
function test1() {
echo " works";
}
$test2 = 'test1'; # just use string name
$test2();
?>
test if function exists
if(function_exists('testfn') ) {}
GET/POST DATA
<?php
if( $_GET["name"] || $_GET["age"] )
{
echo "Welcome ". $_GET['name']. "<br />";
echo "You are ". $_GET['age']. " years old.";
exit();
}
?>
<html>
<body>
<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="GET">
Name: <input type="text" name="name" />
Age: <input type="text" name="age" />
<input type="submit" />
</form>
</body>
</html>
hashes defined:
$_GET
$_POST
$_REQUEST contains both GET and POST values
$_SERVER contains server/environment data
WARNING: PHP mangles names with ., replaces with _
COOKIES
set cookie
setcookie(name, value, expire, path, domain);
<?php
setcookie("user", "Alex Porter", time()+3600);
?>
read cookie
<html>
<body>
<?php
if (isset($_COOKIE["user"]))
echo "Welcome " . $_COOKIE["user"] . "!<br />";
else
echo "Welcome guest!<br />";
?>
</body>
</html>
SESSIONS
start a session
<?php
session_start();
?>
store session variable
<?php
session_start();
$_SESSION['views'] = 1; // store session data
echo "Pageviews = ". $_SESSION['views']; //retrieve data
?>
test session var if set
<?php
if(isset($_SESSION['views'])) {
$_SESSION['views'] = $_SESSION['views']+ 1;
} else {
$_SESSION['views'] = 1;
}
?>
destroy session var
<?php
unset($_SESSION['cart']);
?>
destroy session
<?php
session_destroy();
?>
MYSQL DATABASE
core functions:
mysqli mysqli_connect ([ string $host = ini_get("mysqli.default_host") [,
string $username = ini_get("mysqli.default_user") [,
string $passwd = ini_get("mysqli.default_pw") [,
string $dbname = "" [,
int $port = ini_get("mysqli.default_port") [,
string $socket = ini_get("mysqli.default_socket") ]]]]]] )
int mysqli_connect_errno ( void )
string mysqli_connect_error ( void )
bool mysqli_select_db ( mysqli $link , string $dbname )
bool mysqli_ping ( mysqli $link )
string mysqli_real_escape_string ( mysqli $link , string $escapestr )
mixed mysqli_query ( mysqli $link , string $query [,
int $resultmode = MYSQLI_STORE_RESULT ] )
string mysqli_error ( mysqli $link )
mixed mysqli_fetch_array ( mysqli_result $result [, int $resulttype = MYSQLI_BOTH ])
MYSQLI_ASSOC, MYSQLI_NUM, or MYSQLI_BOTH.
for assoc array only:
mysqli_fetch_assoc
mixed mysqli_insert_id ( mysqli $link )
bool mysqli_close ( mysqli $link )
example:
<?php
include "lib/global.php";
$mysqli = new mysqli($dbhost, $dbuser, $dbpass, $db);
print "ok";
if(!mysqli->connect_errno) {
$sql = "SELECT * from tblPrize where SerialNumber > ? limit 5";
if($stmt = $mysqli->prepare($sql)) {
// type string, bind by ref to variable
// 'typestrings', $var1, $var2, $var3
// i = int , s = string, d = double, b = blob
// bool mysqli_stmt::bind_param( string $types , mixed &$var1 [, mixed &$... ] )
$stmt->bind_stmt_param("i", $serial);
$serial = 1;
$stmt->execute();
$stmt->bind_result($serial, $prize);
while ($stmt->fetch()) {
echo "$serial, $prize\n";
}
$mysqli->close();
} else {
echo 'Unable to connect';
exit();
}
}
?>
ESCAPING HTML
htmlentities( $s, ENT_QUOTES, 'UTF-8');
This takes an optional third argument charset which defines character set used in conversion. Presently, the ISO-8859-1 character set is used as the default.
http://php.net/manual/en/function.htmlentities.php
An alternate function (less recommended) is
htmlspecialchars()
ENCODE/DECODE URL DATA
urlencode( $s )
urldecode( $s )
Be careful about variables that may match html entities. Things like &, © £ ¤ are parsed by the browser and the actual entity is used instead of the desired variable name. This is an obvious hassle that the W3C has been telling people about for years. The reference is here: Ṡ http://www.w3.org/TR/html4/appendix/notes.html#h-B.2.2.
TRY/CATCH
try {
echo inverse(5) . "\n";
echo inverse(0) . "\n";
} catch (Exception $ex) {
echo 'Caught exception: ' . $ex->getMessage() . "\n";
}
throwing: message [, code]
throw new Exception('2 is not allowed as a parameter', 6);
READ/WRITE FILES
read small file into a string
$file = file_get_contents ('YourFile.txt');
loop over lines
$handle = fopen($YourFile, 'r');
while (($buffer = fgets($handle, 4096)) !== false) {
echo $buffer;
echo "\n";
}
fclose($handle);
WRITE TO FILE
$myFile = "testFile.txt";
$fh = fopen($myFile, 'w') or die("can't open file");
$stringData = "Floppy Jalopy\n";
fwrite($fh, $stringData);
$stringData = "Pointy Pinto\n";
fwrite($fh, $stringData);
fclose($fh);
READ WEBPAGE
#Open a site as file
$read = fopen("http://www.yoursite.com", "r")
or die("Couldn't open file");
/# read the bytes with fread ...
# alt, for small files:
# read whole file
echo file_get_contents("http://127.0.0.1/");
# write to file
file_put_contents ( 'newfile.txt', $your_string );
OBJECT ORIENTED PHP, OOP
Note 'var' keyword is for declaring class member variables in php4, and is no longer needed. It will work in php5, but will raise an E_STRICT warning in php5 up to version 5.3, as of which it has been deprecated. Though I happen to like it. :-)
value objects (like struct in c, POJO in Java)
class Person {
var $id, $first_name, $last_name, $email;
}
populate value object from a hash:
# constructor
public function __construct( $hash = null ) {
if ( $hash ) {
foreach ( $hash as $key => $value ) {
# note: reference to variable $key
$this->$key = $value;
}
}
}
class example
class PersonDAO {
var $conn;
function PersonDAO(&$conn) {
$this->conn =& $conn;
}
function save(&$vo) {
if ($v->id == 0) {
$this->insert($vo);
} else {
$this->update($vo);
}
}
function get($id) {
#execute select statement
#create new vo and call getFromResult
#return vo
}
function delete(&$vo) {
#execute delete statement
#set id on vo to 0
}
#-- private functions
function getFromResult(&vo, $result) {
#fill vo from the database result set
}
function update(&$vo) {
#execute update statement here
}
function insert(&$vo) {
#generate id (from Oracle sequence or automatically)
#insert record into db
#set id on vo
}
}
# access functions and variables in the class with:
$this->your_variable_name;
$this->your_function_name();
public/private/static keywords
// static member variable
private static $verbose = 1;
// static function
public static function something($data) {
//
}
...
Then you can call externally with:
TheClass::something($data);
or call variable with
if ( TheClass::$verbose ) {
//...
}
INCREASE MEMORY
edit php.ini
max_execution_time=1800
max_input_time=1800
memory_limit=128M
or set in .htaccess
php_value max_execution_time 1800
php_value max_input_time 1800
php_value memory_limit 128M
to strip automatic slashes
php_value magic_quotes_gpc off
turn off error reporting
php_value display_errors off
php_value output_buffering 8096
do not stop script if user disconnects
int ignore_user_abort ([ string $value ] )
CHANGE HEADER
<?php
# note: you can't manipulate headers after you write content to the browser
header('Content-type: text/xml');
?>
SMTP WITH PEAR:
<?php
require_once "Mail.php";
$host = "mail.emailsrvr.com";
$username = "yourgmailuser@gmail.com";
$password = "****************";
$from = "test <name@domain.com>";
$to = "Some Person <name@domain.com>";
$subject = "Test email using php SMTP\r\n\r\n";
$body = "This is a test email message";
$headers = array ('From' => $from,
'To' => $to,
'Subject' => $subject);
$smtp = Mail::factory('smtp',
array ('host' => $host,
'auth' => true,
'username' => $username,
'password' => $password));
$mail = $smtp->send($to, $headers, $body);
if (PEAR::isError($mail)) {
echo("<p>" . $mail->getMessage() . "</p>");
} else {
echo("<p>Message successfully sent!</p>");
}
?>
# notes: to send BCC, append email both
to header Bcc: $to
and "to1,$to" string
REFLECTION
print_r( $obj ) -- prints structure of hash
var_dump( $obj ) -- structure of hash, with types
print_r( get_class_methods( $obj ) ) -- gets list of object methods.
print_r( get_class_vars( $obj ) ) -- gets list of public vars
SET DEFAULT TIMEZONE
# store all data internally as GMT:
# local tz 1 \
# local tz 2 + <-> webservice.php <-> gmt tz
# local tz 2 /
date_default_timezone_set('Zulu');
// timestamp to convert (just an example)
// can also use: DateTime( $date_string )
$timestamp = 1240349566;
// FROM GMT TO LOCAL
// set this to the time zone provided by the user
$tz = $_SESSION['tz'];
// create the DateTimeZone object for later
$dtzone = new DateTimeZone($tz);
// create a DateTime object
$dtime = new DateTime();
// set it to the timestamp (php >= 5.3.0)
$dtime->setTimestamp($timestamp);
// convert this to the user's timezone using the DateTimeZone object
$dtime->setTimeZone($dtzone);
// print the time using your preferred format
$time = $dtime->format('g:i A m/d/y');
// FROM LOCAL TO GMT
// time to convert (just an example)
$time = 'Tuesday, April 21, 2009 2:32:46 PM';
// set this to the time zone provided by the user
$tz = $_SESSION['tz'];
// create the DateTimeZone object for later
$dtzone = new DateTimeZone($tz);
// now create the DateTime object for this time and user time zone
$dtime = new DateTime($time, $dtzone);
// print the timestamp
$timestamp = $dtime->format('U');
DATE MATH
strtotime('last Sunday', strtotime('09/01/2010'));
# snap to date starting on sun (week of date)
if( ! defined( 'DATE_FORMAT' ) ) define ('DATE_FORMAT', 'Y-m-d H:i:s');
date_default_timezone_set('Zulu');
$tstart = strtotime($start) ;
$weekday = date('w',$tstart);
if ( $weekday != 0 ) {
$start = date(DATE_FORMAT, strtotime('last Sunday',$tstart));
}
# end snap
JSON
$string = json_encode( $obj );
$obj = json_decode( $string, 1 ); // 1 for hash
$obj will be null on error, more info with:
$intcode = json_last_error()
REDIRECT FUNCTION EXAMPLE:
This should be called before page is rendered, or buffer is flushed any chars echo'd to screen before this call can break redirect if output buffer is flushed
function redirect ( $url ) {
header( 'Location: ' . $url ) ;
exit();
}
SIMPLE PHP PAGE EXAMPLE WITH VIEWS/CONTROLLER
$data = $_REQUEST;
$action = $data['action'];
$postback = $data['postback']; # set in hidden
# validation
if ( $postback ) {
if ( ! @$data['dateStart'] && ! @$data['dateEnd'] ) {
$data['message'] = 'Please select a date range';
$postback = 0;
} else if ( $action == 'report_referral' && ! @$data['reportType'] ) {
$data['message'] = 'Please select a report type';
$postback = 0;
}
}
# controller
switch( $action ) {
case 'report_complete':
echo view_report_search( $data );
if ( $postback ) {
# show search results on postback only
echo view_report_complete( $data );
}
break;
case 'report_billed':
echo view_report_billed( $data );
break;
default:
break;
}
# views
# take data, render to html
function view_report_complete( $data ) {
$html = '';
$html .= '<a href="?action=report_billed">test</a>';
return $html;
}
function view_report_billed( $data ) {
$html = '';
$html .= '2';
return $html;
}
PHP GOTCHAS
There are a couple features in php that are counter intuitive (as compared to other languages).
1. The php interpreter ignores the read/write/execute permission bits on a file. That means anything with a .php extension, or, .php. in the name is an executable file (since Apache allows multiple file extensions). So for example, if someone uploads a file named fake_image.php.gif, it will be executable. This also means: all files uploaded must be renamed, and assigned one extension.
Also, apache supports the idea of multiple file extensions. Depending on how the server is set up, image.php.gif may execute as a php file, because the name contains ".php." Meaning, any uploaded file should be renamed.
2. There is no good way to handle threading on all platforms. At best it is only possible on linux with either:
a. pcntl_fork (on systems where lib is installed)
b. lower level system call using & to force process into background
3. By default arrays are copied by value, not by reference.
Well, more exactly: php does not copy arrays until you modify them - internally, they are always passed by reference, only if you modify them does it create an actual copy.
To pass by reference, you can use a function signature:
function somefunction(&$argument){
print_r($argument);
}
So, if you change somefunction($o) to somefunction(&$o), you can see a small increase in array time.
However, this only works if the argument has been assigned to a variable.
php generally has issues with nesting operations. In old versions of php you coulndn'even t do:
somefunction( array(1,2,3) );
You had to do:
$silly = array(1,2,3);
somefunction( $silly );
Also for looping, if you expect to modify an array, you must use:
foreach ( $things as &$thing ) {
# now you have a reference to item in the array
}
unset ( $thing ); // break last ref
4. Variable scoping rules are not really what you might expect. Most languages have the concept of a hierarchical scoping. In php a function has no concept of a parent scope, they only exist in the global scope.
$variable1 = 1;
function a () {
# i can't see $variable1
$variable2 = 1;
function nested_example () {
# i can't see $variable2
# it's not global either
}
}
All functions are registered under a global namespace.
The only communication to a function (outside of the arguments) is via global declaration or $this for objects
$variable1 = 1;
function b () {
global $variable1
# now i can see $variable1
}
5. Functions can't be redefined, or undefined. In javascript, the opposite is true.
6. Including files:
If a relative path is defined in an include, it's relative to the including script's path, not the included path's script. This means that if you include the same file in two different scripts, the relative paths used in the included file may be wrong.
You can use __FILE__ and dirname (__FILE__ ) to get the absolute location of an included script.
from docs:
If a path is defined whether absolute (starting with a drive letter or \ on Windows, or / on Unix/Linux systems) or relative to the current directory (starting with . or ..) the include_path will be ignored altogether. For example, if a filename begins with ../, the parser will look in the parent directory to find the requested file.
dirname(__FILE__) gets the directory of the file being included while dirname($_SERVER['SCRIPT_FILENAME']) gets the directory of the file including it. The script simply finds the difference in how far off the base directory the two are and prints the appropriate number of '../' before the URL.
NOTE: dirname(__FILE__) can be replaced by __DIR__ in php greater than or equal to 5.3.0
or, keep all includes in the same directory.
7. There's no 'strict' variable definition. the most you can have is warnings if a varible has been used without being defined. That means it's harder to see if a variable is mistyped. You can turn on E_STRICT and view error messages, though depending on the libararies you use, the log can fill up with so much text that it's hard to see the worthwhile messages.
8. You'd think there would be an 8, but there isn't. That in itself is very counter-intuitive. :)
9. false == 0 == null; To compare equality more strictly, you must use ===
10. order of operations on ternary a?b:x is counter intuitive, ? is left associative. Always use parans around the entire thing, or avoid altogether.
# won't work
echo " ... " . $test?1:0 . " ... ";
# prints: 1
# ok
echo " ... " . ($test?1:0) . " ... ";
# prints: ... 0 ...
11. "magic quotes" aren't really magic, just a mistake in the language design. Drop this in the .htaccess file to disable them:
php_value magic_quotes_gpc off
otherwise, php will corrupt all your quote data by added backslashes to it. You'll start to see strings like this show up: "And that\\\'s not good" :)
12. php automatically mangles names of variable data in forms. For example, if you have an HTML form with <input name="x.1"> this will show up as a variable "x_1" when the form is submitted. Stick with alphanum and underscore to be safe.
13: Unlike most languages, php functions may return more than one type of data.
this becomes relevant, for example, as functions like strpos return:
false (no match), and
0 (beginnging of string)
but:
false == 0
If you are coming from a strictly typed langauge, it can be confusing that a function in php can return two different types of values: a boolean, or an int. Every other language returns -1 as a 'false' value
14: Also there is no option of "overloading" the function by different types. Just pass in the two different types, and check for them inside the function, manually. for example:
function example( $a = null ) {
if ( $a === null ) {
// function was called without argument
} else if ( is_array( $a) ) {
// do somethign
} else {
// do somethign else
}
}
Though often it's clean to use the rule of thumb:
a function can have one argument (an array/hash), and return one array/hash.
For example
avoid:
function avoidthis ( $a , $b , $c , $d , $e , $f );
better:
function avoidthis ( $data = array() );
// where $data['a'], $data['b'] contain values of different types
PHP SECURITY CONSIDERATIONS
1. Don't trust user input. Without some consideration, don't allow data the user submits to be used for:
including files
echoing contents of files
data piped straight to command line util
data piped straight to db
dynamically executing php functions
echoing directly to a web page
Ideally this data needs to be:
A. scrubbed (restricted to a known set of characters)
B. Restricted to known length.
C. and escaped for the context it is used in.
Avoid using any information that is supplied by the user that is related to a filesystem, rather manage the filesystem yourself and map the user data to the file with a database.
Remember that a chunk of data is really two things:
1. a peice of information
2. a representation in a given context (html, sql, javascript, php, ...)
2. Be careful with functions like $response = file_get_contents($url); Not only will it retrieve a URL, but it will retrieve any file on the system.
3. Always rename files that are uploaded (rename with file extension). Maintain a "whitelist" of safe file types: *.txt, *.gif, *.jpg, etc.
A good graphical ide is Netbeans with the php pack. Or install cygwin and the php interpreter
php can be run from the command line:
file: yourscript.php
<?php
echo "hello world";
?>
Then to execute run (assuming php exe is in PATH)
php yourscript.php
To syntax check a script you can run (like lint):
php -l yourscript.php
Notes: The start tag is required. The closing tag of a php block at the end of a file is optional, and in some cases omitting it is helpful when using include() or require() so unwanted whitespace will not occur at the end of files, and you will still be able to add headers to the response later. It is also handy if you use output buffering, and would not like to see added unwanted whitespace at the end of the parts generated by the included files.
Otherwise, everything outside of the tags are interpreted as string literal
<?php ?> tags cannot be nested inside another <?php ?> tag
and ; at end of commands is required
Print out server config
<?php echo phpinfo(); ?>
Print contents of data structure or object
<?php var_dump($somevar); ?>
The log file is defined in php.ini (global php config file)
log_errors = On
error_log = C:\temp\php_error.log
To run as a shell script, add to top of file
#!/usr/bin/env php
TESTING COMPATIBILITY
# test code in multiple php versions
http://3v4l.org/UCALa
PRINTING
To print a string to STDOUT, use:
echo "hello world";
print "hello world";
COMMENTS
# single line comment (Perl style)
// single line comment (Javascript style)
/* multi line comments */
LOGICAL OPERATORS
Example Name Result
$a and $b And TRUE if both $a and $b are TRUE.
$a or $b Or TRUE if either $a or $b is TRUE.
$a xor $b Xor TRUE if either $a or $b is TRUE, but not both.
! $a Not TRUE if $a is not TRUE.
$a && $b And TRUE if both $a and $b are TRUE.
$a || $b Or TRUE if either $a or $b is TRUE.
COMPARISON OPERATORS
Example Name Result
$a == $b Equal TRUE if $a is equal to $b after type
juggling. EG: '' == 0 == false
$a === $b Identical TRUE if $a is equal to $b, and they are of
the same type. (introduced in php 4)
$a != $b Not equal TRUE if $a is not equal to $b after type
juggling.
$a <> $b Not equal TRUE if $a is not equal to $b after type
juggling.
$a !== $b Not identical TRUE if $a is not equal to $b, or they are
not of the same type. (introduced in php 4)
$a < $b Less than
$a > $b Greater than
$a <= $b Less than or equal to
$a >= $b Greater than or equal to
ARITHMETIC OPERATORS
+ Addition
- Subtraction
* Multiplication
/ Division
% Modulus (division remainder)
++ Increment
-- Decrement
NOTE: there is no exponent ** or ^ operator. Use: pow( base, exponent )
ASSIGNMENT OPERATORS
Operator Example Is The Same As
= x=y x=y
+= x+=y x=x+y
-= x-=y x=x-y
*= x*=y x=x*y
/= x/=y x=x/y
.= x.=y x=x.y
%= x%=y x=x%y
ERROR CONTROL OPERATOR
@ can be prepended to value functions to suppress error
For example:
$text = @file_get_contents('non_existent_file');
$value = @$cache[$key];
Warning: use this carefully. You want to see most errors.
A more acceptable (safer) use is for arrays:
# manually check for null values if needed
$value = @$yourarray['non-existent-key'];
do_some_magic($value);
VARIABLES
Notes: There's no equivalent of "use strict" as in perl. Though you can turn on warnings for use of null variables with the error_reporting E_STRICT flag
declaration and assignment
$a = "asdf";
$b = 2;
$c = NULL;
variables are NULL if:
it has been assigned the constant NULL.
it has not been set to any value yet.
it has been unset().
check NULL value with:
is_null()
or $c === NULL
or $c !== NULL
PARSE COMMAND LINE ARGS
for example:
script.php plain-arg --foo --bar=baz 'plain arg 2' -abc
These will be stored in array $argv
$argv[0] is always the name that was used to run the script.
function parseArgs($argv){
array_shift($argv);
$o = array();
foreach ($argv as $a){
if (substr($a,0,2) == '--'){
$eq = strpos($a,'=');
if ($eq !== false){
$o[substr($a,2,$eq-2)] = substr($a,$eq+1); }
else {
$k = substr($a,2);
if (!isset($o[$k])){ $o[$k] = true; }
}
} else if (substr($a,0,1) == '-'){
if (substr($a,2,1) == '='){
$o[substr($a,1,1)] = substr($a,3);
} else { foreach (str_split(substr($a,1)) as $k){
if (!isset($o[$k])){ $o[$k] = true; } }
}
}
else { $o[] = $a; }
}
return $o;
}
use
$args = parseArgs($_SERVER['argv']);
LOOP OVER STARDARD INPUT
<?php
$f = fopen( 'php://stdin', 'r' );
while( ( $line = fgets( $f ) ) !== false ) {
echo $line;
}
fclose( $f );
DEFINE CONSTANTS
define('DS', DIRECTORY_SEPARATOR);
echo DS;
STRINGS
like with perl, double quoted strings interpolate variables
$a = "hello";
print "$a world";
# Outputs: hello world
Use single quotes for better performance, if possible.
Single quotes are literals, variables are not interpreted.
<?php
echo 'this is a simple string';
echo 'You can also have embedded newlines in
strings this way as it is
okay to do';
echo 'Arnold once said: "I\'ll be back"';
// Outputs: Arnold once said: "I'll be back"
echo 'You deleted C:\\*.*?';
// Outputs: You deleted C:\*.*?
echo 'You deleted C:\*.*?';
// Outputs: You deleted C:\*.*?
echo 'This will not expand: \n a newline';
// Outputs: This will not expand: \n a newline
echo 'Variables do not $expand $either';
// Outputs: Variables do not $expand $either
?>
A string is also an array of characters
NOTE: if you get the first char of a string instead of a string,
code is executing $string[0]... an array assumed where there is none
$s = "hello there";
echo $s[3]; # prints l
PHP heredoc syntax (do not indent closing marker)
$str = <<<EOD
Example of string
spanning multiple lines
using heredoc syntax.
EOD;
NOTE: It is no problem for a string to become very large. php imposes no boundary on the size of a string; the only limit is the available memory of the computer on which php is running.
REPLACE STRINGS
str_replace ( mixed $search , mixed $replace , mixed $subject [, int &$count ] )
It's worth skimming over all string manipulation functions:
http://php.net/manual/en/ref.strings.php
INCLUDE FILE
Code must be loaded into global memory space before it can be called. The following calls will scan the currect folder by default if no path information is given.
try to include, ignore if missing or not found
<?php include "somefile.php"; ?>
try to include, die if file missing
<?php require "somefile.php"; ?>
like include, ignore if already included
<?php include_once "somefile.php"; ?>
like require, die if file missing, only include once
<?php require_once "somefile.php"; ?>
For absolute paths, it is sometimes helpful to define constants like:
// which page are we on? eg /some/path/to/script.php
if( ! defined( 'WEB_PATH' ) ) define('WEB_PATH', $_SERVER['PHP_SELF']);
// web root dir. eg /some/path/to
//if( ! defined( 'WEB_ROOT' ) ) define('WEB_ROOT', dirname(WEB_PATH));
if( ! defined( 'WEB_ROOT' ) ) {
$path = dirname(WEB_PATH);
// avoid "//" at root
if ( $path == '/' ) $path = '';
define('WEB_ROOT', $path);
}
// what is the file name only? // eg script.php
if( ! defined( 'WEB_FILE' ) ) define('WEB_FILE', basename(WEB_PATH));
// physical file path (system). eg: /var/www/html/yoursite
if( ! defined( 'ABS_ROOT' ) ) define('ABS_ROOT', dirname(dirname(__FILE__)));
if( ! defined( 'ABS_ROOT' ) ) define('ABS_ROOT', dirname(__FILE__));
NAME VS ID
On an html form element like <input id="" name="" />
ID is used mostly for javascript
NAME is used for form submission
If the name has [], like:
example[]
then php will parse it as an array of repeating elements.
WARNING: php also performs automatic replacement of special chars in names. For example
name="a.b" becomes "a_b" in $_POST
For safest results, stick with these chars for input names:
alpha number _ [ ]
ARRAYS
Arrays and hashes are the same thing. One uses ints, the other strings.
WARNING: some functions will expect sequential indexes (for example fputcsv). php does not automatically 'fill in' missing indexes.
define an array with:
$arr = array();
assign values with:
$arr[] = 134;
$arr[] = 234;
or
$arr = array( 123, 234 );
define hash with:
<?php
$arr = array("foo" => "bar", 12 => true);
echo $arr["foo"]; // bar
echo $arr[12]; // 1
?>
hash/arrays can be nested any way you want :-)
multidimensional array
<?php
$arr = array("somearray" => array(6 => 5, 13 => 9, "a" => 42));
echo $arr["somearray"][6]; // 5
echo $arr["somearray"][13]; // 9
echo $arr["somearray"]["a"]; // 42
?>
print array
print_r($array);
serialize dump as valid php code
var_export( $array );
iterating with index
$array = array(1, 2);
$count = count($array);
for ($i = 0; $i < $count; $i++) {
echo "\nChecking $i: \n";
echo "Bad: " . $array['$i'] . "\n";
echo "Good: " . $array[$i] . "\n";
echo "Bad: {$array['$i']}\n";
echo "Good: {$array[$i]}\n";
}
array iteration with foreach
foreach ($array as $value) {
}
hash iteration
foreach ($array as $key => $value) {
unset($array[$key]);
}
alternate iteration (older syntax)
while ($el = current($arr)) {
$carr[ $el[$x] ] = $el[$y];
next($arr);
}
NOTE: In order to be able to directly modify array elements within the loop precede $value with &. In that case the value will be assigned by reference. Referencing $value is only possible if the iterated array can be referenced (i.e. if it is a variable).
<?php
$arr = array(1, 2, 3, 4);
foreach ($arr as &$value) {
$value = $value * 2;
}
# $arr is now array(2, 4, 6, 8)
unset($value); // break the reference with the last element, may do inside loop
?>
array functions:
pop and returns the last value of the array,
shortening the array by one element.
array_pop ( $array )
shift an element off the beginning of array
array_shift( $array )
add to end
int array_push ( $array , $var [, $var2... ] )
or,
$your_array[] = "new item";
hash specific
array_values, array_keys
more:
http://www.php.net/manual/en/ref.array.php
ARRAY OPERATORS
Example Name Result
$a + $b Union Union of $a and $b.
$a == $b Equality TRUE if $a and $b have the same key/value pairs.
$a === $b Identity TRUE if $a and $b have the same key/value pairs
in the same order and of the same types.
$a != $b Inequality TRUE if $a is not equal to $b.
$a <> $b Inequality TRUE if $a is not equal to $b.
$a !== $b Non-identity TRUE if $a is not identical to $b.
FUNCTIONS
define functions
<?php
# typical function
function a($n){
b($n);
return ($n * $n);
}
variable pass by reference, use &
function b(&$n){
$n++;
}
echo a(5); //Outputs 36
# WARNING, only variables can be passed by reference!
# array( 1,2,3 ) cannot be passed by ref, it must be assigned to var
?>
NOTE: to access a global variable inside a function, you must re-declare it as global:
$a = 1;
function example() {
print $a; // $a not defined
global $a; // now $a points to variable $a in the global scope
print $a; // $a is 1
}
multiple variables can be declared with , operator:
global $a, $b, $c ;
NOTE: php does not support function overloading, nor is it possible to undefine or redefine previously-declared functions.
However php does allow:
default values to be set to primitives
# variable arguments, default set in def
function example($a, $b=0) {
//$b is optional
}
also the type of the arg can be tested
function do_somthing( $data ) {
if ( is_array( $data ) ) {
// do something
} else {
// do something else
}
}
nested functions:
All functions are declared in the global scope, unless defined in a class (then it's class-scoped)
<?php
function foo()
{
function bar()
{
echo "I don't exist until foo() is called.\n";
}
}
/* We can't call bar() yet
since it doesn't exist. */
foo();
/* Now we can call bar(),
foo()'s processesing has
made it accessible. */
bar();
?>
Both variable number of arguments and default arguments are supported in functions. See also the function references for func_num_args(), func_get_arg(), and func_get_args() for more information.
anonymous functions
Only recent versions of php support the concept of closures.
<?php
$greet = function($name)
{
printf("Hello %s\r\n", $name);
};
$greet('World');
$greet('php');
?>
NOTE: Closures may also inherit variables from the parent scope. Any such variables must be declared in the function header. Inheriting variables from the parent scope is not the same as using global variables
$callback = function ($quantity, $product) use ($tax, &$total)
{
$pricePerItem = constant(__CLASS__ . "::PRICE_" .
strtoupper($product));
$total += ($pricePerItem * $quantity) * ($tax + 1.0);
};
return by reference
function &bar()
{
$a = 5;
return $a;
}
get a reference to a defined function
<?php
echo "test";
function test1() {
echo " works";
}
$test2 = 'test1'; # just use string name
$test2();
?>
test if function exists
if(function_exists('testfn') ) {}
GET/POST DATA
<?php
if( $_GET["name"] || $_GET["age"] )
{
echo "Welcome ". $_GET['name']. "<br />";
echo "You are ". $_GET['age']. " years old.";
exit();
}
?>
<html>
<body>
<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="GET">
Name: <input type="text" name="name" />
Age: <input type="text" name="age" />
<input type="submit" />
</form>
</body>
</html>
hashes defined:
$_GET
$_POST
$_REQUEST contains both GET and POST values
$_SERVER contains server/environment data
WARNING: PHP mangles names with ., replaces with _
COOKIES
set cookie
setcookie(name, value, expire, path, domain);
<?php
setcookie("user", "Alex Porter", time()+3600);
?>
read cookie
<html>
<body>
<?php
if (isset($_COOKIE["user"]))
echo "Welcome " . $_COOKIE["user"] . "!<br />";
else
echo "Welcome guest!<br />";
?>
</body>
</html>
SESSIONS
start a session
<?php
session_start();
?>
store session variable
<?php
session_start();
$_SESSION['views'] = 1; // store session data
echo "Pageviews = ". $_SESSION['views']; //retrieve data
?>
test session var if set
<?php
if(isset($_SESSION['views'])) {
$_SESSION['views'] = $_SESSION['views']+ 1;
} else {
$_SESSION['views'] = 1;
}
?>
destroy session var
<?php
unset($_SESSION['cart']);
?>
destroy session
<?php
session_destroy();
?>
MYSQL DATABASE
core functions:
mysqli mysqli_connect ([ string $host = ini_get("mysqli.default_host") [,
string $username = ini_get("mysqli.default_user") [,
string $passwd = ini_get("mysqli.default_pw") [,
string $dbname = "" [,
int $port = ini_get("mysqli.default_port") [,
string $socket = ini_get("mysqli.default_socket") ]]]]]] )
int mysqli_connect_errno ( void )
string mysqli_connect_error ( void )
bool mysqli_select_db ( mysqli $link , string $dbname )
bool mysqli_ping ( mysqli $link )
string mysqli_real_escape_string ( mysqli $link , string $escapestr )
mixed mysqli_query ( mysqli $link , string $query [,
int $resultmode = MYSQLI_STORE_RESULT ] )
string mysqli_error ( mysqli $link )
mixed mysqli_fetch_array ( mysqli_result $result [, int $resulttype = MYSQLI_BOTH ])
MYSQLI_ASSOC, MYSQLI_NUM, or MYSQLI_BOTH.
for assoc array only:
mysqli_fetch_assoc
mixed mysqli_insert_id ( mysqli $link )
bool mysqli_close ( mysqli $link )
example:
<?php
include "lib/global.php";
$mysqli = new mysqli($dbhost, $dbuser, $dbpass, $db);
print "ok";
if(!mysqli->connect_errno) {
$sql = "SELECT * from tblPrize where SerialNumber > ? limit 5";
if($stmt = $mysqli->prepare($sql)) {
// type string, bind by ref to variable
// 'typestrings', $var1, $var2, $var3
// i = int , s = string, d = double, b = blob
// bool mysqli_stmt::bind_param( string $types , mixed &$var1 [, mixed &$... ] )
$stmt->bind_stmt_param("i", $serial);
$serial = 1;
$stmt->execute();
$stmt->bind_result($serial, $prize);
while ($stmt->fetch()) {
echo "$serial, $prize\n";
}
$mysqli->close();
} else {
echo 'Unable to connect';
exit();
}
}
?>
ESCAPING HTML
htmlentities( $s, ENT_QUOTES, 'UTF-8');
This takes an optional third argument charset which defines character set used in conversion. Presently, the ISO-8859-1 character set is used as the default.
http://php.net/manual/en/function.htmlentities.php
An alternate function (less recommended) is
htmlspecialchars()
ENCODE/DECODE URL DATA
urlencode( $s )
urldecode( $s )
Be careful about variables that may match html entities. Things like &, © £ ¤ are parsed by the browser and the actual entity is used instead of the desired variable name. This is an obvious hassle that the W3C has been telling people about for years. The reference is here: Ṡ http://www.w3.org/TR/html4/appendix/notes.html#h-B.2.2.
TRY/CATCH
try {
echo inverse(5) . "\n";
echo inverse(0) . "\n";
} catch (Exception $ex) {
echo 'Caught exception: ' . $ex->getMessage() . "\n";
}
throwing: message [, code]
throw new Exception('2 is not allowed as a parameter', 6);
READ/WRITE FILES
read small file into a string
$file = file_get_contents ('YourFile.txt');
loop over lines
$handle = fopen($YourFile, 'r');
while (($buffer = fgets($handle, 4096)) !== false) {
echo $buffer;
echo "\n";
}
fclose($handle);
WRITE TO FILE
$myFile = "testFile.txt";
$fh = fopen($myFile, 'w') or die("can't open file");
$stringData = "Floppy Jalopy\n";
fwrite($fh, $stringData);
$stringData = "Pointy Pinto\n";
fwrite($fh, $stringData);
fclose($fh);
READ WEBPAGE
#Open a site as file
$read = fopen("http://www.yoursite.com", "r")
or die("Couldn't open file");
/# read the bytes with fread ...
# alt, for small files:
# read whole file
echo file_get_contents("http://127.0.0.1/");
# write to file
file_put_contents ( 'newfile.txt', $your_string );
OBJECT ORIENTED PHP, OOP
Note 'var' keyword is for declaring class member variables in php4, and is no longer needed. It will work in php5, but will raise an E_STRICT warning in php5 up to version 5.3, as of which it has been deprecated. Though I happen to like it. :-)
value objects (like struct in c, POJO in Java)
class Person {
var $id, $first_name, $last_name, $email;
}
populate value object from a hash:
# constructor
public function __construct( $hash = null ) {
if ( $hash ) {
foreach ( $hash as $key => $value ) {
# note: reference to variable $key
$this->$key = $value;
}
}
}
class example
class PersonDAO {
var $conn;
function PersonDAO(&$conn) {
$this->conn =& $conn;
}
function save(&$vo) {
if ($v->id == 0) {
$this->insert($vo);
} else {
$this->update($vo);
}
}
function get($id) {
#execute select statement
#create new vo and call getFromResult
#return vo
}
function delete(&$vo) {
#execute delete statement
#set id on vo to 0
}
#-- private functions
function getFromResult(&vo, $result) {
#fill vo from the database result set
}
function update(&$vo) {
#execute update statement here
}
function insert(&$vo) {
#generate id (from Oracle sequence or automatically)
#insert record into db
#set id on vo
}
}
# access functions and variables in the class with:
$this->your_variable_name;
$this->your_function_name();
public/private/static keywords
// static member variable
private static $verbose = 1;
// static function
public static function something($data) {
//
}
...
Then you can call externally with:
TheClass::something($data);
or call variable with
if ( TheClass::$verbose ) {
//...
}
INCREASE MEMORY
edit php.ini
max_execution_time=1800
max_input_time=1800
memory_limit=128M
or set in .htaccess
php_value max_execution_time 1800
php_value max_input_time 1800
php_value memory_limit 128M
to strip automatic slashes
php_value magic_quotes_gpc off
turn off error reporting
php_value display_errors off
php_value output_buffering 8096
do not stop script if user disconnects
int ignore_user_abort ([ string $value ] )
CHANGE HEADER
<?php
# note: you can't manipulate headers after you write content to the browser
header('Content-type: text/xml');
?>
SMTP WITH PEAR:
<?php
require_once "Mail.php";
$host = "mail.emailsrvr.com";
$username = "yourgmailuser@gmail.com";
$password = "****************";
$from = "test <name@domain.com>";
$to = "Some Person <name@domain.com>";
$subject = "Test email using php SMTP\r\n\r\n";
$body = "This is a test email message";
$headers = array ('From' => $from,
'To' => $to,
'Subject' => $subject);
$smtp = Mail::factory('smtp',
array ('host' => $host,
'auth' => true,
'username' => $username,
'password' => $password));
$mail = $smtp->send($to, $headers, $body);
if (PEAR::isError($mail)) {
echo("<p>" . $mail->getMessage() . "</p>");
} else {
echo("<p>Message successfully sent!</p>");
}
?>
# notes: to send BCC, append email both
to header Bcc: $to
and "to1,$to" string
REFLECTION
print_r( $obj ) -- prints structure of hash
var_dump( $obj ) -- structure of hash, with types
print_r( get_class_methods( $obj ) ) -- gets list of object methods.
print_r( get_class_vars( $obj ) ) -- gets list of public vars
SET DEFAULT TIMEZONE
# store all data internally as GMT:
# local tz 1 \
# local tz 2 + <-> webservice.php <-> gmt tz
# local tz 2 /
date_default_timezone_set('Zulu');
// timestamp to convert (just an example)
// can also use: DateTime( $date_string )
$timestamp = 1240349566;
// FROM GMT TO LOCAL
// set this to the time zone provided by the user
$tz = $_SESSION['tz'];
// create the DateTimeZone object for later
$dtzone = new DateTimeZone($tz);
// create a DateTime object
$dtime = new DateTime();
// set it to the timestamp (php >= 5.3.0)
$dtime->setTimestamp($timestamp);
// convert this to the user's timezone using the DateTimeZone object
$dtime->setTimeZone($dtzone);
// print the time using your preferred format
$time = $dtime->format('g:i A m/d/y');
// FROM LOCAL TO GMT
// time to convert (just an example)
$time = 'Tuesday, April 21, 2009 2:32:46 PM';
// set this to the time zone provided by the user
$tz = $_SESSION['tz'];
// create the DateTimeZone object for later
$dtzone = new DateTimeZone($tz);
// now create the DateTime object for this time and user time zone
$dtime = new DateTime($time, $dtzone);
// print the timestamp
$timestamp = $dtime->format('U');
DATE MATH
strtotime('last Sunday', strtotime('09/01/2010'));
# snap to date starting on sun (week of date)
if( ! defined( 'DATE_FORMAT' ) ) define ('DATE_FORMAT', 'Y-m-d H:i:s');
date_default_timezone_set('Zulu');
$tstart = strtotime($start) ;
$weekday = date('w',$tstart);
if ( $weekday != 0 ) {
$start = date(DATE_FORMAT, strtotime('last Sunday',$tstart));
}
# end snap
JSON
$string = json_encode( $obj );
$obj = json_decode( $string, 1 ); // 1 for hash
$obj will be null on error, more info with:
$intcode = json_last_error()
REDIRECT FUNCTION EXAMPLE:
This should be called before page is rendered, or buffer is flushed any chars echo'd to screen before this call can break redirect if output buffer is flushed
function redirect ( $url ) {
header( 'Location: ' . $url ) ;
exit();
}
SIMPLE PHP PAGE EXAMPLE WITH VIEWS/CONTROLLER
$data = $_REQUEST;
$action = $data['action'];
$postback = $data['postback']; # set in hidden
# validation
if ( $postback ) {
if ( ! @$data['dateStart'] && ! @$data['dateEnd'] ) {
$data['message'] = 'Please select a date range';
$postback = 0;
} else if ( $action == 'report_referral' && ! @$data['reportType'] ) {
$data['message'] = 'Please select a report type';
$postback = 0;
}
}
# controller
switch( $action ) {
case 'report_complete':
echo view_report_search( $data );
if ( $postback ) {
# show search results on postback only
echo view_report_complete( $data );
}
break;
case 'report_billed':
echo view_report_billed( $data );
break;
default:
break;
}
# views
# take data, render to html
function view_report_complete( $data ) {
$html = '';
$html .= '<a href="?action=report_billed">test</a>';
return $html;
}
function view_report_billed( $data ) {
$html = '';
$html .= '2';
return $html;
}
PHP GOTCHAS
There are a couple features in php that are counter intuitive (as compared to other languages).
1. The php interpreter ignores the read/write/execute permission bits on a file. That means anything with a .php extension, or, .php. in the name is an executable file (since Apache allows multiple file extensions). So for example, if someone uploads a file named fake_image.php.gif, it will be executable. This also means: all files uploaded must be renamed, and assigned one extension.
Also, apache supports the idea of multiple file extensions. Depending on how the server is set up, image.php.gif may execute as a php file, because the name contains ".php." Meaning, any uploaded file should be renamed.
2. There is no good way to handle threading on all platforms. At best it is only possible on linux with either:
a. pcntl_fork (on systems where lib is installed)
b. lower level system call using & to force process into background
3. By default arrays are copied by value, not by reference.
Well, more exactly: php does not copy arrays until you modify them - internally, they are always passed by reference, only if you modify them does it create an actual copy.
To pass by reference, you can use a function signature:
function somefunction(&$argument){
print_r($argument);
}
So, if you change somefunction($o) to somefunction(&$o), you can see a small increase in array time.
However, this only works if the argument has been assigned to a variable.
php generally has issues with nesting operations. In old versions of php you coulndn'even t do:
somefunction( array(1,2,3) );
You had to do:
$silly = array(1,2,3);
somefunction( $silly );
Also for looping, if you expect to modify an array, you must use:
foreach ( $things as &$thing ) {
# now you have a reference to item in the array
}
unset ( $thing ); // break last ref
4. Variable scoping rules are not really what you might expect. Most languages have the concept of a hierarchical scoping. In php a function has no concept of a parent scope, they only exist in the global scope.
$variable1 = 1;
function a () {
# i can't see $variable1
$variable2 = 1;
function nested_example () {
# i can't see $variable2
# it's not global either
}
}
All functions are registered under a global namespace.
The only communication to a function (outside of the arguments) is via global declaration or $this for objects
$variable1 = 1;
function b () {
global $variable1
# now i can see $variable1
}
5. Functions can't be redefined, or undefined. In javascript, the opposite is true.
6. Including files:
If a relative path is defined in an include, it's relative to the including script's path, not the included path's script. This means that if you include the same file in two different scripts, the relative paths used in the included file may be wrong.
You can use __FILE__ and dirname (__FILE__ ) to get the absolute location of an included script.
from docs:
If a path is defined whether absolute (starting with a drive letter or \ on Windows, or / on Unix/Linux systems) or relative to the current directory (starting with . or ..) the include_path will be ignored altogether. For example, if a filename begins with ../, the parser will look in the parent directory to find the requested file.
dirname(__FILE__) gets the directory of the file being included while dirname($_SERVER['SCRIPT_FILENAME']) gets the directory of the file including it. The script simply finds the difference in how far off the base directory the two are and prints the appropriate number of '../' before the URL.
NOTE: dirname(__FILE__) can be replaced by __DIR__ in php greater than or equal to 5.3.0
or, keep all includes in the same directory.
7. There's no 'strict' variable definition. the most you can have is warnings if a varible has been used without being defined. That means it's harder to see if a variable is mistyped. You can turn on E_STRICT and view error messages, though depending on the libararies you use, the log can fill up with so much text that it's hard to see the worthwhile messages.
8. You'd think there would be an 8, but there isn't. That in itself is very counter-intuitive. :)
9. false == 0 == null; To compare equality more strictly, you must use ===
10. order of operations on ternary a?b:x is counter intuitive, ? is left associative. Always use parans around the entire thing, or avoid altogether.
# won't work
echo " ... " . $test?1:0 . " ... ";
# prints: 1
# ok
echo " ... " . ($test?1:0) . " ... ";
# prints: ... 0 ...
11. "magic quotes" aren't really magic, just a mistake in the language design. Drop this in the .htaccess file to disable them:
php_value magic_quotes_gpc off
otherwise, php will corrupt all your quote data by added backslashes to it. You'll start to see strings like this show up: "And that\\\'s not good" :)
12. php automatically mangles names of variable data in forms. For example, if you have an HTML form with <input name="x.1"> this will show up as a variable "x_1" when the form is submitted. Stick with alphanum and underscore to be safe.
13: Unlike most languages, php functions may return more than one type of data.
this becomes relevant, for example, as functions like strpos return:
false (no match), and
0 (beginnging of string)
but:
false == 0
If you are coming from a strictly typed langauge, it can be confusing that a function in php can return two different types of values: a boolean, or an int. Every other language returns -1 as a 'false' value
14: Also there is no option of "overloading" the function by different types. Just pass in the two different types, and check for them inside the function, manually. for example:
function example( $a = null ) {
if ( $a === null ) {
// function was called without argument
} else if ( is_array( $a) ) {
// do somethign
} else {
// do somethign else
}
}
Though often it's clean to use the rule of thumb:
a function can have one argument (an array/hash), and return one array/hash.
For example
avoid:
function avoidthis ( $a , $b , $c , $d , $e , $f );
better:
function avoidthis ( $data = array() );
// where $data['a'], $data['b'] contain values of different types
PHP SECURITY CONSIDERATIONS
1. Don't trust user input. Without some consideration, don't allow data the user submits to be used for:
including files
echoing contents of files
data piped straight to command line util
data piped straight to db
dynamically executing php functions
echoing directly to a web page
Ideally this data needs to be:
A. scrubbed (restricted to a known set of characters)
B. Restricted to known length.
C. and escaped for the context it is used in.
Avoid using any information that is supplied by the user that is related to a filesystem, rather manage the filesystem yourself and map the user data to the file with a database.
Remember that a chunk of data is really two things:
1. a peice of information
2. a representation in a given context (html, sql, javascript, php, ...)
2. Be careful with functions like $response = file_get_contents($url); Not only will it retrieve a URL, but it will retrieve any file on the system.
3. Always rename files that are uploaded (rename with file extension). Maintain a "whitelist" of safe file types: *.txt, *.gif, *.jpg, etc.
No comments:
Post a Comment