interactive prompt, for quickly testing code
run (with no args):
python
# this starts an interactive shell
print "hi"
use:
ctrl-c to stop execution
ctrl-d to exit
introspection/reflection
# will print out object methods in the shell
dir()
#example
import struct
dir()
dir(struct)
line comment
#
mulitline comment
"""
you can use pydoc style quotes,
though it's kinda a hack
"""
continue long lines
this is a long line \
that will be continued
combine two lines
print "hi" ; print "there"
tab/spaces:
best practice is (apparently) to use spaces instead of tabs
Note: This seems counter intuitive to me. No one seems to agree on how many spaces to use. PEP 8 recommends 4 spaces, and Google recommends 2 spaces. Personally, I think it makes more sense to use \t and let everyone set their own tabstop.
print
print "hello world"
concatinate string
# with space
a = "hello", "world"
print a
# hello world
# without space
print "hello" + "world"
helloworld
WARNING: python3 has apparently changed this basic function syntax. :-)
You'll need to use parens with python3: print(string)
variables, no declaration needed
# simple
a = 1
# can assign a list to a list
a,b,c = 1,2,3
#can chain
a = b = c = 1
python assumes all function variables are local. to access the global scope use
global varname
basic strings
s = 'A string constant'
s = "another constant"
There is no difference between ' and " (unlike in Perl and PHP). Typically is seems like python code I see tends to prefer ' (easier to type?)
multi line strings use a triple-quote syntax:
s = """
This is
your string
"""
analogue of php require_once (include)
EXAMPLE
#### (file: config.py)
# can be nested data structure
constant1 = "value1"
constant2 = "value2"
#### (consumer.py)
# note, no .py extension.
import config
# note, by default, everything is under the namespace:
print config.constant1
print config.constant2
better - wrap with try/except
# create file named modulename.py
# then in second script run
try:
import modulename
except ImportError:
print 'importing modulename failed'
command line args
import sys
# 1 is first arg
a = sys.argv[1]
function
def concat(a, b):
return a + b;
functions can be called with named arguments
concat('1', '2')
or
concat( a = '1', b = '2' )
functions can also set default values
def example( a, b = 0 ):
return a + b;
nested functions
you can define function in a function and return it:
def example():
def ret():
print "hi"
return ret
t = example()
t()
#hi
more on strings
a = 'string'
a = "string"
a = """string"""
a = '''string'''
# unicode
a = u'strng'
# binary
a = b'strng'
# regular expression
regex = r"(\w)"
string formatting
WARN: python3 changes this syntax:
a = 5
b = "hello"
buf = "A = %d\n , B = %s\n" % (a, b)
print buf
# prints:
# A = 5
# , B = hello
c = 10
buf = "C = %d\n" % c
print buf
C = 10
You could as well use format:
>>> print "This is the {}th tome of {}".format(5, "knowledge")
This is the 5th tome of knowledge
note: % will be deprecated in python 3.1
# string manipulation
# to lower case
a.lower()
# replace
a.replace( find, start, [num_of_times] )
# starts with string
a.startswith( "/" )
# ends with string
a.startswith( "/" )
# regular expressions
import re
# substitute
re.sub(r"(\w)(\w+)(\w)", yourreplacement, yourstr)
# match
if re.search('http', yourstr) != None:
int
b = 2
float
b = 2.0
booleans
True, False
null value
None
conditional
if a < b:
do_something();
elif a < c:
do_something_else()
else:
default_case()
logical operators (these do what you'd expect)
and
or
not
# don't forget and type && || ! :-)
main hook
if __name__ == "__main__":
main()
exit program:
import sys
sys.exit(2)
#another example
if sys.argv[1] == '':
print "usage is ./yourprogram.py site url "
sys.exit(2)
array
empty list
a = []
with values
a = ['spam', 'eggs', 100, 1234]
# length
len(a)
#note: multidimensional arrays work as you'd expect
# whitespace between elements is ignored:
# valid syntax:
a = [1,
2,
3,
4
]
test if value is in array
has_spam = 'spam' in s
loops
for n in [1,2,3]:
print n
list/array methods:
list.append(item)
list.extend(List)
list.insert(i, item)
list.remove(item)
list.pop(i)
list.index(item)
list.count(item)
list.sort() # in place
list.reverse()
hash/dictionary
stock = {
"key": "value",
"key2": 2
}
stock['key3'] = 2
# remove item
del stock['key3']
nested data structure
# nest arrays and
a = [ {'a': 1}, {'a': 2} ]
print(a[1]['a'])
#prints: 2
loop over dictionary/hash
d = {'x': 1, 'y': 2, 'z': 3}
# loop over keys, read into var 'key'
for key in d:
print key, 'corresponds to', d[key]
# loop over key and value
for key, value in d.iteritems():
print key, 'corresponds to', value
breaking out of a loop:
break exists loop
continue skips iteration
cast
int()
float()
str()
chr()
unichr()
ord()
hex()
oct()
tuple (invariant data, like a constant struct)
coord = (2,3)
set (like a dictionary with no data)
a = { 'a', 'b' }
while loop
while link != '':
# do something
files
f = open('doo.txt')
while line = f.readLine()
print line
f.close()
user input
name = raw_input("enter your name:")
array slice
select all items j <= k < j
a[i:j]
-1 counts starting from end of list
replace list subset with another
a[1:2] = [1,2,3,4]
concatenate lists
a = a + b
tuples
pack data together as a single unit
a = ('GOOG', 100, 635.2)
access like array
set
like array keys, no duplicates
s = set([3,4,5])
operations
| union
& intersection
- difference (subtract)
^ nand
place holder
if you need to stick something in a code block for syntax check
does nothing but fill space
if 1:
pass
test if string contains substring
x = 'hello'
y = 'll'
y in x
# True
index of string
>>> print "hello".find('h')
0
>>> print "hello".find('ss')
-1
exceptions
try:
do_somthing()
except:
print "error: your error "
full syntax
except NameError, IndexError as msg:
print "error", msg
raising execptions (throw)
raise ValueError('invalid number')
print error # older syntax
try:
doX()
catch Exception, e:
print e
generator
use instead of return
yield
the function maintains persistent state and pauses at the yeild line
to grok: it's a static function with static global variables.
lamba
for short anon function, no (), no return statement, one line
square = lambda x: x ** 2
print square(2)
Object Oriented Programming in Python
For me, OOP in Python is difficult to use compared to Java/C#. To me it just feels like OOP was bolted onto Python as an after-thought. Or probably more accurately, it copied from a language which bolted OOP on as an after-thought. OOP was not present in the pre 1.0 releases of Python.
Overall, I really wish Python had (a) explicit variable declarations like `var x` and (b) implicit self. The scoping rules also feel screwy (why do we need `global`? If can see a variable in a parent scope, why can't Python?)
Otherwise, you might initially think if you write a set of functions that access global variables, all you need to do to convert them into a class, is to indent them all and add a class name to the top. For example, this syntax would make sense to me:
# i'm a function accessing a global variable
a = 1
def get_a():
return a
# now i'm a class
class your_class:
a = 1 # now an instance variable
def get_a():
return a
This is simple and makes sense to me. Unfortunately it won't work at all. :-) Python forces you to rewrite every single function signature and variable reference.
After struggling with Python's approach, IMO the easiest way to understand understand OOP in Python is to realize that: Python is NOT really an OOP language, any more than Perl is. It's a multi-paradigm language which happens to provide a little OOP "syntax sugar." But it's really bitter tasting sugar. :-)
As a result, the OOP "object.function" syntax is largely redundant. It's passing an object reference around as the first argument, and has a very lightweight syntax manipulation that just converts this syntax:
obj.f(a) -> f(obj, a)
IOW, it's just moving the "obj" to inside the function. That's not OOP; that's just a regular expression.
Anyway, accepting the screwy OOP syntax, here's an object example:
class Test:
# instance variable
your_variable = ''
# static variable
your_static = ''
# constructor
def __init__(self, a):
# no class scope of variables. must use explicit self.
self.your_variable = a
Test.your_static = a
# like perl class
def your_method( self, a ):
self.your_variable = a
# ...
initialize class
# NOTE: no 'new' keyword
# this is less painful
t = Test()
extending another class
class Test( BaseClass ):
#...
execute shell command
import subprocess
p = subprocess.Popen('ls', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
for line in p.stdout.readlines():
print line,
retval = p.wait()
older method (prints output)
os.system(cmd_string)
modules:
save as yourfile.py
import yourfile
call as:
yourfile.function()
import indivdual functions into script namespace
from yourfile import *
from yourfile import f1, f2
urllib vs urllib2
generally you should use the newest lib 2
urlib (old) has the encode function
urllib.urlencode({'abc':'d f', 'def': '-!2'})
'abc=d+f&def=-%212'
in python 3, everything has been merged into urllib
easy install for modules
# shell level installer
wget http://peak.telecommunity.com/dist/ez_setup.py
python ez_setup.py
# cache downloade files with
easy_install -b /path/to/build/dir/
# install from cache
easy_install /path/to/build/dir/
install pip to install new modules. like PCAN for Pearl
new versions of python (>3.4) already include pip
for old versions download
https://bootstrap.pypa.io/get-pip.py
run
python get-pip.py
add python Scripts/ to PATH, if it's not already
#verbose output
pip -vvv install flask
better parsing of command line args
# allow a hook for cli
if __name__ == "__main__":
opt = OptionParser()
opt.add_option("-d", "--database", help="EZCONNECT string", action="store",
type="string", dest="db")
opt.add_option("-n", "--requests", help="number of requests", action="store",
type="int", dest="requests", default=10)
opt.add_option("-c", "--concurrency", help="number of concurrent connections",
action="store", type="int", dest="concurrency", default=1)
opt.add_option("-s", "--sql", help="SQL query or PL/SQL block",
action="store", type="string", dest="sql")
opt.add_option("-b", "--bind", help="dictionary of bind parameters",
action="store", type="string", dest="bind")
(options, args) = opt.parse_args()
bench = Orabench(options)
bench.run()
python debugger
within a python file:
import pdb
...
pdb.set_trace() begin the debugger at this line when the file is run normally
start debug mode
python -m pdb <name>.py [args] begin the debugger
help [command] view a list of commands, or view help for a specific command
control execution
l(ist) list 11 lines surrounding the current line
w(here) display the file and line number of the current line
n(ext) execute the current line
s(tep) step into functions called at the current line
r(eturn) execute until the current functionṡs return is encountered
b[#] create a breakpoint at line [#]
b list breakpoints and their indices
c(ontinue) execute until a breakpoint is encountered
clear[#] clear breakpoint of index [#]
q(uit) exit the debugger
changing variables / interacting with code
p <name> print value of the variable <name>
! <expr> execute the expression <expr>
operators
Operator Description Example
+ Addition - Adds values on either side of the operator a + b will give 30
- Subtraction - Subtracts right hand operand from left hand operand a - b will give -10
* Multiplication - Multiplies values on either side of the operator a * b will give 200
/ Division - Divides left hand operand by right hand operand b / a will give 2
% Modulus - Divides left hand operand by right hand operand and returns remainder b % a will give 0
** Exponent - Performs exponential (power) calculation on operators a**b will give 10 to the power 20
// Floor Division - The division of operands where the result is the quotient in which the digits after the decimal point are removed. 9//2 is equal to 4 and 9.0//2.0 is equal to 4.0
== Checks if the value of two operands are equal or not, if yes then condition becomes true. (a == b) is not true.
!= Checks if the value of two operands are equal or not, if values are not equal then condition becomes true. (a != b) is true.
<> Checks if the value of two operands are equal or not, if values are not equal then condition becomes true. (a <> b) is true. This is similar to != operator.
> Checks if the value of left operand is greater than the value of right operand, if yes then condition becomes true. (a > b) is not true.
< Checks if the value of left operand is less than the value of right operand, if yes then condition becomes true. (a < b) is true.
>= Checks if the value of left operand is greater than or equal to the value of right operand, if yes then condition becomes true. (a >= b) is not true.
<= Checks if the value of left operand is less than or equal to the value of right operand, if yes then condition becomes true. (a <= b) is true.
= Simple assignment operator, Assigns values from right side operands to left side operand c = a + b will assigne value of a + b into c
+= Add AND assignment operator, It adds right operand to the left operand and assign the result to left operand c += a is equivalent to c = c + a
-= Subtract AND assignment operator, It subtracts right operand from the left operand and assign the result to left operand c -= a is equivalent to c = c - a
*= Multiply AND assignment operator, It multiplies right operand with the left operand and assign the result to left operand c *= a is equivalent to c = c * a
/= Divide AND assignment operator, It divides left operand with the right operand and assign the result to left operand c /= a is equivalent to c = c / a
%= Modulus AND assignment operator, It takes modulus using two operands and assign the result to left operand c %= a is equivalent to c = c % a
**= Exponent AND assignment operator, Performs exponential (power) calculation on operators and assign value to the left operand c **= a is equivalent to c = c ** a
//= Floor Dividion and assigns a value, Performs floor division on operators and assign value to the left operand c //= a is equivalent to c = c // a
& Binary AND Operator copies a bit to the result if it exists in both operands. (a & b) will give 12 which is 0000 1100
| Binary OR Operator copies a bit if it exists in eather operand. (a | b) will give 61 which is 0011 1101
^ Binary XOR Operator copies the bit if it is set in one operand but not both. (a ^ b) will give 49 which is 0011 0001
~ Binary Ones Complement Operator is unary and has the efect of 'flipping' bits. (~a ) will give -61 which is 1100 0011 in 2's complement form due to a signed binary number.
<< Binary Left Shift Operator. The left operands value is moved left by the number of bits specified by the right operand. a << 2 will give 240 which is 1111 0000
>> Binary Right Shift Operator. The left operands value is moved right by the number of bits specified by the right operand. a >> 2 will give 15 which is 0000 1111
and Called Logical AND operator. If both the operands are true then then condition becomes true. (a and b) is true.
or Called Logical OR Operator. If any of the two operands are non zero then then condition becomes true. (a or b) is true.
not Called Logical NOT Operator. Use to reverses the logical state of its operand. If a condition is true then Logical NOT operator will make false. not(a and b) is false.
in Evaluates to true if it finds a variable in the specified sequence and false otherwise. x in y, here in results in a 1 if x is a member of sequence y.
not in Evaluates to true if it does not finds a variable in the specified sequence and false otherwise. x not in y, here not in results in a 1 if x is not a member of sequence y.
is Evaluates to true if the variables on either side of the operator point to the same object and false otherwise. x is y, here is results in 1 if id(x) equals id(y).
is not Evaluates to false if the variables on either side of the operator point to the same object and true otherwise. x is not y, here is not results in 1 if id(x) is not equal to id(y).
Python Operators Precedence. The following lists all operators from highest precedence to lowest.
Operator Description
** Exponentiation (raise to the power)
~ + - Ccomplement, unary plus and minus (method names for the last two are +@ and -@)
* / % // Multiply, divide, modulo and floor division
+ - Addition and subtraction
>> << Right and left bitwise shift
& Bitwise 'AND'
^ | Bitwise exclusive `OR' and regular `OR'
<= < > >= Comparison operators
<> == != Equality operators
= %= /= //= -= += *= **= Assignment operators
is is not Identity operators
in not in Membership operators
not or and Logical operators
Saturday, November 21, 2015
Quick Language Reference: PHP
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.
Monday, November 9, 2015
"Fixing" the Python Interactive Shell Prompts
I like the concept of interactive shells for quickly testing new code. The only issue I've had with the Python shell is the prompt (the >>> and ...) is a complete nuisance if you want to copy code out of the shell after testing it. I can't even copy and paste something back into the same shell. :-)
Also I think it would make more sense -- if there was any prompt at all -- that # should be added to the standard output and print statements. That way, if the code was copied into a program, the testing output would just be ignored as comments. (In some cases it could actually be useful as a comment, if it gives an example of data structure or function output)
So, I added a quick config file to "fix" the prompt noise.
Create a file such as ~/.pythonrc.py
And add this to the file:
Then run this before starting the `python` interactive shell (or drop it in your ~/.profile)
Also I think it would make more sense -- if there was any prompt at all -- that # should be added to the standard output and print statements. That way, if the code was copied into a program, the testing output would just be ignored as comments. (In some cases it could actually be useful as a comment, if it gives an example of data structure or function output)
So, I added a quick config file to "fix" the prompt noise.
Create a file such as ~/.pythonrc.py
And add this to the file:
import sys
# this is a patch so you can directly copy to/from the shell
# just remember to add a new line after a def as usual.
# clear those puppies!
sys.ps1 = ""
sys.ps2 = ""
# add a logger that prints output as a comment.
class Logger(object):
def __init__(self):
self.terminal = sys.stdout
def write(self, s):
if s == '\n': # compress
return
lines = s.split("\n")
for line in lines:
if len(line) > 0:
self.terminal.write("# "+line+"\n")
#self.terminal.write("\n") # optional space
def flush(self):
pass
sys.stdout = Logger()
Then run this before starting the `python` interactive shell (or drop it in your ~/.profile)
export PYTHONSTARTUP=~/.pythonrc.pyWhen you start python shell, the prompts are gone. Then you will have an interactive terminal you can copy code directly from (and to itself):
Python 2.7.6 (default, Jun 22 2015, 18:00:18)
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information
def just_a_test(s):
print s
just_a_test('works')
# works
Sunday, November 1, 2015
Self Healing Technology is Here
The idea of self-healing technology seems futuristic, though I noticed it already exists in smartphones.
Though I didn't take a photo of the screen initially for reference, so I couldn't tell exactly how much better it had improved. So, I took a picture for reference, and repeated the freezing process. The second time around, the bad spot was again about half the size.
After a week, I checked again -- lo and behold -- the phone was completely healed:
I gave my son my old Motorola Atrix 2 phone a couple years ago, and he uses it like a mini game platform. (Interestingly, he uses the old smartphone much more than his Game Boy). As a result, it's been dropped a couple hundred times, and even flown across the room a few times as well. The thing appears to be nearly indestructable.
One day I noticed the screen had a lot of dead pixels after a bad fall. I thought the phone was just about shot, but wondered if there was a way to fix them. So I did a little research and learned, suprisingly, the dead pixels REPAIR THEMSELVES.
I also read that freezing the phone helped speed up the process. I was a bit skeptical, but wanted to try the experiment.
I took out the battery, put the phone in a zip lock bag, and froze it over night. The next day, I thawed it out in a towel (to avoid condensation). After I turned it back on, the bad pixels were remarkably better. What used to be a giant black streak on the phone was much less than half the size (smaller).
Though I didn't take a photo of the screen initially for reference, so I couldn't tell exactly how much better it had improved. So, I took a picture for reference, and repeated the freezing process. The second time around, the bad spot was again about half the size.
After a week, I checked again -- lo and behold -- the phone was completely healed:
Apparently, if you just wait six months, the liquid crystals in the screen will fix themselves, but freezing seems to speed up the process.
Seems like freaky Skynet technology to me. This is the first time I've ever seen a piece of technology heal itself. :-)
Simple Graphical Interface for FluidSynth
I had a Korg Triton synthesizer for a long time, and was thinking of getting a new synth for fun. Though I noticed really everything for a synthesizer can be done in open source software now. For example, you can download free .sf2 soundfont files (some of which sound more realistic than my Korg). On Linux, you can use jack and fluidsynth to do the midi synthesis. You can even do sequencing in Rosegarden, or standard multitrack recording in Ardour or Audacity.
The only physical piece of hardware you need is a usb midi device. So for maybe under $100, you can get what would easily be a $1000 synth (if you were buying a traditional hardware synth). :-)
The only downside, fluidsynth is by default a command line program.
There are some graphical front end programs for it, but I found them to be difficult to use for what I needed. I typically use a synth for multitrack overdubs, or just playing around on, less for midi sequencing. So, I wanted an interface that looked similar to a classic synth. For example: I wanted to to see all the soundfont files as "voices" and then easily cycle through the instruments in each soundfont -- with one key press. Or, to search through the soundfont files, for example, to see all "organ" voices at a glance.
So... I gave up on finding a simple graphical interface that worked for me, and I just spent a few days writing exactly what I wanted. Also, it was a nice excuse to poke around Python. I don't use it very often. Also I thought it would be easier for others to take apart or extend.
The source code (single file) is at git hub:
https://github.com/sevkeifert/fluidsynth-gui
The graphical interface looks like this:
The second tab (some level controls):
Features:
- Put all your sound fonts in a folder, and select the folder. Then, if you press the Up/Down arrows (on the sound font list) you'll quickly cycle through the voices. If you press the Left/Right arrows, you'll quickly cycle through the available instruments contained in the soundfont.
- There's also a search filter at bottom. (You can also search while the sountfont list has the focus, and this adds a search filter at bottom.) For example, if you type "moog," the list will be filtered to only items that contain "moog" in the name. When searching, SPACE is a wildcard. ESC clears the search box.
- If you organize the fonts in a folder, you can also search and navigate the folders from directly inside the Sound Font listing.
- You can load up to 16 sound fonts on your 16 midi channels.
- On the second tab, you can set levels for gain/reverb/chorus.
- All control settings will be restored if you close and restart the app.
The interface is as simple as I could make it. :-)
You'll need to setup fluidsynth first before using this gui.
In theory it should work on Windows, Mac and Linux (it just uses fluidsynth's socket interface). I only have used it with xubuntu 14.04, FluidSynth version 1.1.6 so far.
Future/Planned Features ... ;-)
- Add Checkbox that enables "More cowbell"
- Add new volume controls that go to "11" for extra "umph" when needed
--
On the other hand, if you only have one soundfont, you can use the existing GUI Qsynth instead. In comparison, Qsynth looks like:
Though switching between soundfonts in Qsynth requires a few more steps. You'll need to do this for every soundfont:
Setup -> Soundfonts -> Open
Monday, August 24, 2015
Handy shortcuts for Vim
Here are a couple Bash shortcuts that have ended up being fairly useful for me.
Typically if I'm on a Linux command line, I'll need to open files by either the content of the file, or partitial file names. For example, I might want to quickly open all the files that contain the string "Foo." That, or I don't want to type a/very/long/path/to/some_file.txt. I'll end up piping the output of `find` or `grep` into an editor repeatedly. So I just made a couple short aliases that save on typing. I'm not sure why I hadn't added these years ago :-)
The shortcuts look at everything under the current directory.
Of course, you can customize these to work with any editors or filetypes you are interested in... these are just examples.
Drop these in your .bash_profile file:
# vim + grep = vig
# Open all files containing a particular string
# vim + grep = vig
# Open all files containing a particular string
# For example, to oen all files containing content "Foo", use
# vig Foo
function vig(){ vim `grep -Ril --exclude='*.class' "$1"`; }
# vim + find = vif
# Open all files where the name contains a string.
# vim + find = vif
# Open all files where the name contains a string.
# For example, to open all files named "Foo...", use
# vif Foo
function vif(){ vim `find -iname "$1*"`; }
# vim + java = vij
# Open all files matching a class name
# For example, find all classes named Foo.java, use
# For example, find all classes named Foo.java, use
# vij Foo
function vij(){ vim `find -name "$1.java"`; }
function vij(){ vim `find -name "$1.java"`; }
Sunday, December 21, 2014
Create Postage Stamp Window Border Theme in XFCE
I noticed that XFCE window themes allow transparent (color: None), so I thought it would be funny to create a postage stamp window border. This was tested on Xubuntu 14.04
# The theme is based on greybird. Copy the theme to a new one called 'bumpy'
cd /usr/share/themes/
sudo cp -r Greybird bumpy
cd bumpy/xfwm4/
# then update the border files
sudo vi left-active.xpm
sudo vi bottom-active.xpm
sudo vi right-active.xpm
sudo vi bottom-left-active.xpm
sudo vi bottom-right-active.xpm
# The theme is based on greybird. Copy the theme to a new one called 'bumpy'
cd /usr/share/themes/
sudo cp -r Greybird bumpy
cd bumpy/xfwm4/
# then update the border files
sudo vi left-active.xpm
/* XPM */
static char * left_active_xpm[] = {
"8 24 3 1",
" c None",
". c #cecece",
"x c #939393",
"x.......",
" x......",
" x.....",
" x....",
" x....",
" x.....",
" x......",
"x.......",
"x.......",
" x......",
" x.....",
" x....",
" x....",
" x.....",
" x......",
"x.......",
"x.......",
" x......",
" x.....",
" x....",
" x....",
" x.....",
" x......",
"x.......",
};
sudo vi bottom-active.xpm
/* XPM */
static char * left_active_xpm[] = {
"23 8 3 1",
" c None",
". c #cecece",
"x c #939393",
"........................",
"........................",
"........................",
"........................",
"...xx......xx......xx...",
"..x x....x x....x x..",
".x x..x x..x x.",
"x xx xx x",
};
sudo vi right-active.xpm
/* XPM */
static char * left_active_xpm[] = {
"8 24 3 1",
" c None",
". c #cecece",
"x c #939393",
".......x",
"......x ",
".....x ",
"....x ",
"....x ",
".....x ",
"......x ",
".......x",
".......x",
"......x ",
".....x ",
"....x ",
"....x ",
".....x ",
"......x ",
".......x",
".......x",
"......x ",
".....x ",
"....x ",
"....x ",
".....x ",
"......x ",
".......x",
};
sudo vi bottom-left-active.xpm
/* XPM */
static char * left_active_xpm[] = {
"16 16 3 1",
" c None",
". c #cecece",
"x c #939393",
"xxxxxxxx ",
"xxxxxxxx ",
"xxxxxxxx ",
"xxxxxxxx ",
"xxxxxxxx ",
"xxxxxxxx ",
"xxxxxxxx ",
"xxxxxxxx ",
"xxxxxxxxxxxxxxxx",
"xxxxxxxxxxxxxxxx",
"xxxxxxxxxxxxxxxx",
"xxxxxxxxxxxxxxxx",
"xxxxxxxxxxxxxxxx",
"xxxxxxxxxxxxxxxx",
"xxxxxxxxxxxxxxxx",
"xxxxxxxxxxxxxxxx",
};
sudo vi bottom-right-active.xpm
/* XPM */
static char * left_active_xpm[] = {
"16 16 3 1",
" c None",
". c #cecece",
"x c #939393",
" xxxxxxxx",
" xxxxxxxx",
" xxxxxxxx",
" xxxxxxxx",
" xxxxxxxx",
" xxxxxxxx",
" xxxxxxxx",
" xxxxxxxx",
"xxxxxxxxxxxxxxxx",
"xxxxxxxxxxxxxxxx",
"xxxxxxxxxxxxxxxx",
"xxxxxxxxxxxxxxxx",
"xxxxxxxxxxxxxxxx",
"xxxxxxxxxxxxxxxx",
"xxxxxxxxxxxxxxxx",
"xxxxxxxxxxxxxxxx",
};
Now, your windows have postage stamp borders:
Subscribe to:
Posts (Atom)





