Saturday, November 21, 2015

Quick Language Reference: Perl

for executable scripts

    path to perl, first line can have hashbang
    #!/usr/bin/perl

    for portability, first line can have hashbang
    #!/bin/env perl

    a space after ! is ok
    #! /usr/bin/perl


test for errors:

    cat filename | perl -cw

show all lib paths

    perl -e 'print join "\n", @INC;'

look for installed libs

    perl -e 'print join "\n", @INC;' | while read f; do find $f -follow; done \
      | grep XML | sort | uniq

look for which libs are used

    #(all the use statments)
    grep -R -e '^use' .  | sed -e 's/^[^:]*://' -e 's/\s*;.*$//' \
      | sort | uniq

    #(just the lib names)
    grep -R -e '^use' .  | sed -e 's/^[^:]*://' -e 's/\s*;.*$//' \
      |  awk '{print $2}' | sort | uniq

show installed/cpan versions

    #!/usr/bin/perl
    # pass perl module name/regex as arg
    # eg:
    #     DBI /DBD::/

    use CPAN;

    printf("%-20s %10s %10s\n", "Module", "Installed", "CPAN");

    foreach $a (@ARGV) {
      foreach $mod (CPAN::Shell->expand("Module", $a)){
        printf("%-20s %10s %10s %s\n",
          $mod->id,
          $mod->inst_version eq "undef" || !defined($mod->inst_version)
            ? "-" : $mod->inst_version,
          $mod->cpan_version eq "undef" || !defined($mod->cpan_version)
            ? "-" : $mod->cpan_version,
          $mod->uptodate ? "" : "*"
        );
      }
    }


print library paths

    perl -e 'printf "%d %s\n", ++$i, $_ for @INC'

    #1 /wcs/lib/perl5/5.6.1/i686-linux-perlio
    #2 /wcs/lib/perl5/5.6.1
    #3 /wcs/lib/perl5/wcs/5.6.1/i686-linux-perlio
    #4 /wcs/lib/perl5/wcs/5.6.1
    #5 /wcs/lib/perl5/wcs
    #6 .


installation preference:

    1. try yum, if that doesn't work
    2. install with CPAN.  if that doesn't work
    3. compile manually (avoid if possible)

install perl libs with yum

    yum install
    #for example:
    yum install perl-Apache*


install perl with cpan

    perl -MCPAN -e 'install CGI::Builder'


manual installation

    # general process to compile c programs
    ./configure
    make
    make test
    make install


command line args

    # first argument:
    $ARGV[0]

file perms

    must have execute perms on script files

hello world

    print "hello\n";

http header:

    print "content-type: text/html \n\n";    #HTTP HEADER


require strict variable defs

    #!/bin/perl
    use strict;


perl variable markers

    $ for strings, literals
    @ for arrays
    % for hash (associative array)


strings

    "interprets $var variables"
    'literal syntax no interpolation'

string concat

    .

string length

 
    length()

remove new line

    chomp()



# perl heredoc syntax
$heredoc = <
<END;
     Everything after the
     start of the
     here-doc is part of
     the string until we get
     to the
END

#  note end token can have NO leading whitespace
print $heredoc;

print line:

    print "line", "\n";

use data dumper for complex data, print to standard error log

    use Data::Dumper;
    print STDERR Data::Dumper::Dumper($node),"\n";

regex substitution

    # replace all words
    $sentence =~ s/london/London/g;

no match
 
    if ( $string !~ m/whatever/ ) {
        # it's not there
    }

regex match text, save to var

    # NOTE: $1 is a global var, may not be reset in a loop
    # () defines match

    # NOTE: =~ syntax seems backwards to me, but remember !~

    $string =~ m/whatever(sought_text)whatever2/;
    $soughtText = $1;


perl function, with variable

    # look ma, no args
    # everything is passed along the special @_ variable
    sub parse_layout {
      my $text = shift;

    }

    function rule of thumb:
        avoid long arg list.
        avoid referencing global data
        ideally, make all functions accept/return 1 hashref argument

if else

        if ( $line =~ /^#/ ) {
            # begins with comment;
        } elsif ( $line =~ /^\s*$/ ) {
            $endgroup = 1;
        } else {
            #data line;
        }

    comparison

        ==  != > < <= >=    for numbers only!
        eq, ne                for strings only!


    operators

        &&    and
        ||    or
        !    not

perl split string

    my $info = "part:part:part:part";
    my @parts = split(/:/, $info);

remove trailing newline, if it's there

    chomp();

trim

    sub trim {
        my $s = shift;
        $s =~ s/^\s+//;
        $s =~ s/\s+$//;
        return $s;
    }


define array/hash

    # actual named variables
    my @coins = ("Quarter","Dime","Nickel");
    my %account = ('username' => 'jimmyboy', 'password' => 's3cret!');


    # !!!! WARNING !!!!

    # perl doesn't really have a low-level concept of array like you might expect
    # for any complex array manipulation, use array/hash *pointers* instead (below)
    # unlike arrays, these can be assigned to another variable
    # or redefined in a loop
    # the pointers will work more like the array/hash in other languages

    NOTE: perl array "weirdness" as compared to php
    http://www.webreference.com/programming/perl/nested/index.html
    http://docstore.mik.ua/orelly/perl4/prog/ch09_01.htm


define array/hash pointers (what you should use)

    arrays are handled a bit differently than in php
    arrays loop by ref by default


    array reference

        my $array = [];

    hash reference

        my $hash = {};



    create from existing array/hash


        $aref = \@array;         # $aref now holds a reference to @array
        $href = \%hash;          # $href now holds a reference to %hash
        $sref = \$scalar;        # $sref now holds a reference to $scalar




define nested or complex data structure:
    grok:
        somewhat like javascript/python with {} []
        like php with =>

        my $VAR1 = {
                  'alpha' => [
                               123,
                               456
                             ],
                  'beta' => 'x'
                };


access array/hash pointer

    use $href-> to dereference


    # like c, can dereference pointer properties with ->


        $hashref->{key}
        $hashref->{'key'}   #quotes on keys optional
        $arrayref->[0]

    # alt syntax: use double $$ ... uglier

         $$hashref{'asdf'}
         $$arrayref[0]

dereference array ref to array

     @$ret

dereference array ref to hash
     %$ret

dereference field of a class:

    @{$user->{'Accounts'}}
    %{$user->{'Accounts'}}


loop over array

    foreach my $part ( @parts ) {
        print $part;
    }

loop over keys

    foreach my $key (  keys %hash ) {
        print $key;
    }


    NOTE: build a list of items, then perform operation on the list


passing refernce

    my %some_hash = ();
    return \%some_hash
 
    my %some_array ...
    return \@some_hash


sorting

    http://raleigh.pm.org/sorting.html

    case insensitive

        @s = sort {lc $a cmp lc $b} @a;

    element length

        @s = sort {lenth $a <=> length $b} @a;

    sub routine

        @s = sort mycriteria @a;
           sub mycriteria {
             my($aa) = $a =~ /(\d+)/;
             my($bb) = $b =~ /(\d+)/;

             sin($aa) <=> sin($bb) ||
             $aa*$aa <=> $bb*$bb;
           }


# two levels of sorting
# $a and $b are predefined

    sub inorder {
      $ACCT_SORTORDER{$user->{$a}{'TypeID'}} <=> $ACCT_SORTORDER{$user->{$b}{'TypeID'}}
        or
      $user->{$a}{'Nickname'} cmp $user->{$b}{'Nickname'};
    }

    my(@accounts) = sort inorder @{$user->{'Accounts'}};


try/catch exception

    here's the version of perl's try/catch

      eval {
        $response_doc = $parser->parse_string( $xml_str );
      };
      # catch parse exception            
      if($@) {
        # error
      }

      # reset $@ if calling again, this is global var
   

system call
    system "curl --basic --user $username:$password --data-ascii status='$message' http://twitter.com/statuses/update.json";
 
    # with backticks
    my $ret =
    `curl --basic --user $username:$password --data-ascii status='$message' http://twitter.com/statuses/update.json`;




file handling:


    mode    operand    create    truncate
    read    <      
    write    >        Y    Y
    append    >>        Y  
    Each of the above modes can also be prefixed with the + character to allow for simultaneous reading and writing.

    mode    operand    create    truncate
    read/write    +<      
    read/write    +>    Y    Y
    read/append    +>>    Y  


    # open file  for read
    open FILE, "
    As you might have guessed already if you just want read access you can skip the mode just as we did in the very first example above.

    Reading files

    If you want to read a text file line-by-line then you can do it as such:

    my @lines =
    The
    while (      print $_;
    }

    The $_ variable is automatically set for you to the contents of the current line. If you wish you may name your line variable instead:

    while (my $line =

    # release handle
    close FILE;


    # write to file
    open FILE, ">file.txt" or die $!;
    print FILE $str;
    close FILE;


perl oop

OOP perl is a little like Python

for more info:

    http://www.tutorialspoint.com/perl/perl_oo_perl.htm


    #!/usr/bin/perl

    package Person;

    sub new
    {
        my $class = shift;
        my $self = {
            _firstName => shift,
            _lastName  => shift,
            _ssn       => shift,
        };
        # Print all the values just for clarification.
        print "First Name is $self->{_firstName}\n";
        print "Last Name is $self->{_lastName}\n";
        print "SSN is $self->{_ssn}\n";
        bless $self, $class;
        return $self;
    }
    sub setFirstName {
        my ( $self, $firstName ) = @_;
        $self->{_firstName} = $firstName if defined($firstName);
        return $self->{_firstName};
    }

    sub getFirstName {
        my( $self ) = @_;
        return $self->{_firstName};
    }
    1;



# using
# use the source file, and call

    use Person;

    $object = new Person( "Mohammad", "Saleem", 23234345);
    # Get first name which is set using constructor.
    $firstName = $object->getFirstName();


# inherit

    our @ISA = qw(Person);    # inherits from Person



# CGI
#query parameters
# get/post parameters

    http://perldoc.perl.org/CGI.html


    use CGI;
    my $q = CGI->new;

        # Process an HTTP request
     @values  = $q->param('form_field');
     $fh      = $q->upload('file_field');
     $riddle  = $query->cookie('riddle_name');
     %answers = $query->cookie('answers');
    # Prepare various HTTP responses

    print $q->header();
    print $q->header('application/json');

    $cookie1 = $q->cookie(-name=>'riddle_name', -value=>"The Sphynx's Question");
    $cookie2 = $q->cookie(-name=>'answers', -value=>\%answers);
    print $q->header(
        -type    => 'image/gif',
        -expires => '+3d',
        -cookie  => [$cookie1,$cookie2]
        );
   print  $q->redirect('http://yoursite.com/your/page');

Quick Language Reference: Ruby

# interactive ruby shell:

    # install on linux
    yum -y install ruby ruby-irb

    # install on windows
    use cygwin, install all ruby packages.  includes gem and irb

    # To quit IRB, type quit, exit or just hit Control-D.

    # load file
    # or put ruby code in  ~/.irbrc
    irb -r 'file'

    # dynamically load file
    irb
    require 'file'


# equiv of print_r, var_dump (think "pretty print")

    pp object

# hash tag

    #!/usr/bin/env ruby

# comments

    #

# define/set variable

    a = 1
    b = "some string"

    c = nil

#print

    puts "hi"

# read line

    line = gets


# define method/function

    def hi(name)
        puts "hi #{name}!"
    end


# call function
    hi
    hi("name")

# introspection: print all methods of object

    require 'pp'
    pp 5.methods



# default values, functions in string

    def hi(name = "World")
        puts "Hello #{name.capitalize}!"
    end


# simple class

    class Greeter

      # constructor
      def initialize(name = "World")
        # use meta char @ to access class properties
        @name = name
      end

      def say_hi
        puts "Hi #{@name}!"
      end

      def say_bye
        puts "Bye #{@name}, come back soon."
      end

    end


# instantiate class with .new

    g = Greeter.new("John Smith")
    g.say_hi
    g.say_bye


# list public methods for object:

    # include all ancestors
    Greeter.instance_methods

    # only in immediate class
    Greeter.instance_methods(false)


# test if a method is defined for the object

    # is name defined on the object?
    g.respond_to?("name")


# alter existing class

    #NOTE: The changes will be present in any new objects you create and even available in existing objects of that class.

    class Greeter

        # public getter and setter  
       attr_accessor :name

        # only getter
       attr_reader :thing

    end


# array

    names = ["Albert", "Brenda", "Charles", "Dave", "Englebert"]

     
    # size:
    names.size  
 

# loop over array

    # pipes into bound variable 'name'
     names.each do |name|
 
    puts "Hello #{name}!"
     end

# join

    names.join(", ")


# hash

    H = Hash["a" => 100, "b" => 200]

    puts "#{H['a']}"
    puts "#{H['b']}"

    #This will produce following result:

    #100
    #200


# get hash keys as array

    keys = H.keys
    puts "#{keys}"

# loop over hash

    hash.each do |key, array|
      puts "#{key}-----"
      puts array
    end

    hash.keys.sort.each do |key|
      puts "#{key}-----"
      hash[key].each { |val| puts val }
    end


    puts h.sort.map {|k,v| ["#{k}----"] + v}


# hash methods:

        http://www.tutorialspoint.com/ruby/ruby_hashes.htm


# duck typing.  you can probe capabilities of object

    class Greeter2
        def say_bye
          if @names.nil?
            puts "..."
          elsif @names.respond_to?("join")
            # Join the list elements with commas
            puts "Goodbye #{@names.join(", ")}. "
          else
            puts "Goodbye #{@names}. "
          end
        end
    end


# test if class file is called directly

    if __FILE__ == $0
        # I am filename  

    end


# parse standard input stdin

    #!/usr/bin/env ruby

    chars = 0
    words = 0
    lines = 0

    # Count the stuff

    while line = gets
      chars += line.size
      words += line.split.size
      lines += 1
    end

    # Display the results

    puts "Chars=%s, Words=%s, Lines=%s" % [
      chars, words, lines
    ]


# read all lines

    lines = readlines
    puts "Chars=%d, Words=%d, Lines=%d" % [lines.join.size, lines.join.split.size, lines.size]


# code blocks

    Procs are objects that can be called.
    Sending the call method to the proc object executes the code block.
    The [] operator is a synonym for call.


    {
        |boundvariable|
    }


    do |var|

    end


    block = proc { |x| puts "Called with #{x}" }

    # calling
    block.call(1)
    block.call(2)

    block[222]


# using blocks (notes from Matz and the interwebs)

    Matz: Blocks are basically nameless functions. You may be familiar with the lambda from other languages like Lisp or Python. Basically, you can pass a nameless function to another function, and then that function can invoke the passed-in nameless function. For example, a function could perform iteration by passing one item at a time to the nameless function. This is a common style, called higher order function style, among languages that can handle functions as first class objects. Lisp does it. Python does it.  Even C does it with function pointers. Many other languages do this style of programming. In Ruby, the difference is mainly a different kind of syntax for higher order functions. In other languages, you have to specify explicitly that a function can accept another function as an argument. But in Ruby, any method can be called with a block as an implicit argument. Inside the method, you can call the block using the yield keyword with a value.

    SO: Blocks are not objects, they are syntactic structures; this is why they cannot be assigned to a variable. This is a privilege reserved for objects.
    Blocks are closures -- they're functions that close over the enclosing scope. They don't conceptually "belong to" a given object.

    Blocks that directly follow a method call are implicitly passed to the method.
    The method may call the proc by invoking yield and passing any arguments.
    You can test for the presence of a block using block_given?.
    yield(arg) if block_given?


    def three_times(arg)
      yield(arg)
      yield(arg)
      yield(arg)
    end

    three_times("x") { |val| puts val }
    three_times(22) do |thing|
      puts "Got #{thing}"
    end

    # output

    x
    x
    x
    Got 22
    Got 22
    Got 22


    The block may be explicitly passed using the & operator.
    def three_times(arg, &block)
      block.call(arg)
      block.call(arg)
      block.call(arg)
    end


# lambda vs procs

    There are two slight differences between lambda and Proc.new.

    First, argument checking. The Ruby documentation for lambda states: Equivalent to Proc.new, except the resulting Proc objects check the number of parameters passed when called.. Here is an example to demonstrate this:

    Second, there is a difference in the way returns are handled from the Proc. A return from Proc.new returns from the enclosing method (acting just like a return from a block.


    def try_ret_procnew
        ret = Proc.new { return "Baaam" }
        ret.call
        "This is not reached"
    end

    # prints "Baaam"
    puts try_ret_procnew


    While return from lambda acts more conventionally, returning to its caller:

    def try_ret_lambda
        ret = lambda { return "Baaam" }
        ret.call
        "This is printed"
    end

    # prints "This is printed"
    puts try_ret_lambda


    I would probably recommend using lambda instead of Proc.new when possible.


#  unit testing

    require 'test/unit'
    require 'trio'

    class TestTrio < Test::Unit::TestCase
      def setup
        @trio = Trio.new(1,2,3)
      end

      def test_trio
        assert_equal [1,2,3], @trio.to_a
      end
    end


# database io

    require 'dbi'

    db = DBI.connect("DBI:Pg:poc", 'jim', nil)
    sql = %{
      SELECT name, id
      FROM users
      WHERE id < 4
    }
    db.select_all(sql) do |row|
      puts "User #{row['name']}, id #{row['id']}"
    end
    db.disconnect


# composite pattern, loops

    << is the polymorphic append operator.
    { ... } is a code block. It is automatically passed to the each function.
    |installer| is an argument to the code block.
    list.each { |item| code } is equivalent to the for loop
    do ... end is also code block.


    class MasterInstaller
      def initialize
        @installers = []
      end

      def register(installer)
        @installers << installer
      end

      def install
        for installer in @installers
          installer.install
        end
      end

      def uninstall
        @installers.each { |installer|
          installer.uninstall
        }
      end

      def backup
        @installers.each do |installer|
          installer.backup
        end
      end
    end


# what's the ?

    ? as a method name suffix (e.g. include?) indicates that the method returns a true/false value.

# includes  (load module)

    require: finds the file and loads it (once)
 
    new: sent to a Class object will cause a new instance to be created. Parameters passed to new will automatically be passed to initialize.
 
    Parenthesis are optional if the result is not ambiguous.
 
    ARGV is a list of command line arguments
 
    No interface declaration is needed for installers. As long as they implement the needed methods, the master installer can use them.
 

    # find file, load
    require 'masterinstaller'
    require 'fileinstaller'
    require 'sqlinstaller'

    m = MasterInstaller.new

    m.register(FileInstaller.new("xyz.rb", "bin"))
    m.register SqlInstaller.new(
      "INSERT INTO a_table VALUES(1,2,3);" )

    commands = ['install', 'uninstall', 'backup']
    ARGV.each do |command|
      puts "Command is #{command}"
      m.send(command) if commands.include? command
      puts
    end


# reserved words

 
    BEGIN        do        next    then
    END            else    nill    true
    alias        elsif    not        undef
    and            end        or        unless
    begin        ensure    redo    until
    break        false    rescue    when
    case        for        retry    while
    class        if        return    while
    def            in        self    __FILE__
    defined?    module    super    __LINE__


# gotchas:

 
    No Primitives. Integers and floats are objects
    -1.abs => 1

    No Semi-colons
    nil, not null

    nil is an object
    nil.nil? => true

    nil and false are false
    everything else, including 0, is true

    Picky about spaces
    f (arg) gives warning.
    f(arg) is ok.


    Different type model
    Duck Typing!
    No interfaces needed.

    Expression oriented syntax.
    Almost everything returns a value
    x = if a==0 then 5 else 1 end
    Methods automatically return their last expression.

    Single Inheritance
    But mixins are available

    Per-object methods are allowed (singleton methods)
    Classes are always open (even built in classes)


# messages

    OO in Java is defined in terms of calling functions
    Member functions, static functions, etc.
    OO in Ruby is defined in terms of sending messages
    Sending messages, obj.send(:method_name)

    class Proxy
      def initialize(target)
        @target = target
      end
      def method_missing(sym, *args, &block)
        @target.send(sym, *args, &block)
      end
    end

    class Dog
      def talk; puts "WOOF"; end
    end

    d = Dog.new
    p = Proxy.new(d)

    p.talk

# file

Here, the File.open method takes a block. It then opens a new file (in "append" mode), and yields the open file into the block. When the block completes, Ruby closes the file. Except that Ruby doesn't just close the file when the block completes; it guarantees that the File will be closed, even if executing the block results in a raise. Let's take a look at the implementation of File in Rubinius:

    def append(location, data)
      path = Pathname.new(location)
      raise "Location does not exist" unless path.exist?
   
      File.open(path, "a") do |file|
        file.puts YAML.dump(data)
      end
   
      return data
    end

# modules are called "gems" or "ruby-gems"

    # install with yum
    yum install rubygem-json


# introspection

    Depending on what information you're looking for, try:

    obj.methods
    and if you want just the methods defined for obj (as opposed to getting methods on Object as well)

    obj.methods - Object.methods
    Also interesting is doing stuff like:

    obj.methods.grep /to_/
    To get instance variables, do this:

    obj.instance_variables
    and for class variables:

    obj.class_variables


# list all installed gems

    gem list

# list all remote gems

    gem list rhc --remote --all

Quick Langauge Reference: Python

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

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 &amp, &copy &pound &curren 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.