KEMBAR78
Intermediate PHP | KEY
Intermediate PHP
Bradley Holt & Matthew Weier O’Phinney
Arrays




Photo by AJ Cann
Associate values to keys

Keys can be integers (enumerative arrays) or
strings (associative arrays)

Values can be primitive types, objects, or
other arrays (multidimensional arrays)
<?php
$post = array(
   'id'           => 1234,
   'title'        => 'Intermediate PHP',
   'updated'      => new DateTime(
      '2010-12-16T18:00:00-05:00'
   ),
   'draft'        => false,
   'priority'     => 0.8,
   'categories' => array('PHP', 'BTV')
);
Reading, Writing, and
 Appending Arrays
<?php
$post = array(
   'id'         => 1234,
   'title'      => 'Intermediate PHP',
   // …
);
echo $post['title']; // Intermediate PHP
<?php
$post = array(
   'id'         => 1234,
   'title'      => 'Intermediate PHP',
   // …
);
$post['title'] = 'PHP 201';
<?php
$post = array(
   'id'           => 1234,
   'title'        => 'Intermediate PHP',
   'updated'      => new DateTime(
      '2010-12-16T18:00:00-05:00'
   ),
   'draft'        => false,
   'priority'     => 0.8,
   'categories' => array('PHP', 'BTV')
);
$post['summary'] = 'Arrays, functions, and
objects';
<?php
$post = array(
   // …
   'categories' => array('PHP', 'BTV')
);
$post['categories'][] = 'Programming';
print_r($post['categories']);
/*
Array
(
     [0] => PHP
     [1] => BTV
     [2] => Programming
)
  */
<?php
$post = array(
   // …
   'categories' => array('PHP', 'BTV')
);
$post['categories'][1] = 'Burlington';
print_r($post['categories']);
/*
Array
(
     [0] => PHP
     [1] => Burlington
)
  */
Iterating Over Arrays
<?php
$post = array(
   // …
   'categories' => array('PHP', 'BTV')
);
foreach ($post['categories'] as $v) {
   echo $v . PHP_EOL;
}
/*
PHP
BTV
  */
<?php
$post = array(
   // …
   'categories' => array('PHP', 'BTV')
);
foreach ($post['categories'] as $k => $v) {
   echo $k . ': ' . $v . PHP_EOL;
}
/*
0: PHP
1: BTV
  */
<?php
$post = array(
   'id'          => 1234,
   'title'       => 'Intermediate PHP',
   // …
);
foreach ($post as $k => $v) {
   echo $k . ': ' . $v . PHP_EOL;
}
/*
id: 1234
title: Intermediate PHP
…
  */
Implode and Explode
<?php
$post = array(
   // …
   'categories' => array('PHP', 'BTV')
);
echo implode(', ', $post['categories']);
// PHP, BTV
<?php
$post = array(
   // …
   'categories' =>
     explode(', ', 'PHP, BTV')
);
print_r($post['categories']);
/*
Array
(
     [0] => PHP
     [1] => BTV
)
  */
Array Key Exists,
In Array, and Array Keys
<?php
$post = array(
   'id'          => 1234,
   // …
   'categories' => array('PHP', 'BTV')
);
if (array_key_exists('categories', $post))
{
   echo implode(', ', $post['categories']);
} else {
   echo 'Uncategorized';
}
<?php
$post = array(
   // …
   'categories' => array('PHP', 'BTV')
);
if (in_array('PHP', $post['categories'])) {
     echo 'PHP: Hypertext Preprocessor';
}
<?php
$posts = array(
   1233 => array(/* … */),
   1234 => array(/* … */),
);
print_r(array_keys($posts));
/*
Array
(
     [0] => 1233
     [1] => 1234
)
  */
Sorting Arrays
<?php
$post = array(
   // …
   'categories' => array('PHP', 'BTV')
);
sort($post['categories']);
print_r($post['categories']);
/*
Array
(
     [0] => BTV
     [1] => PHP
)
  */
Sorting Function
          Attributes
Some sort by value, others by key

Some maintain key association, others do not

Some sort low to high, others high to low

Some are case sensitive, some are not

See:
http://www.php.net/manual/en/array.sorting.php
Sorting Functions
array_multisort()   rsort()

asort()             shuffle()

arsort()            sort()

krsort()            uasort()

ksort()             uksort()

natcasesort()       usort()

natsort()
Stacks and Queues




Photo by Phil Cooper   Photo by Thomas W
Array Push and
Array Pop (stack)
<?php
$post = array(
   // …
   'categories' => array('PHP')
);
array_push($post['categories'], 'BTV');
echo array_pop($post['categories']);
// BTV
print_r($post['categories']);
/*
Array
(
     [0] => PHP
)
  */
Array Unshift and
Array Pop (queue)
<?php
$post = array(
   // …
   'categories' => array('BTV')
);
array_unshift($post['categories'], 'PHP');
print_r($post['categories']);
/*
Array
(
     [0] => PHP
     [1] => BTV
)
  */
echo array_pop($post['categories']);
// BTV
Functions
Internal Functions
<?php
print_r(get_defined_functions());
/*
Array
(
     [internal] => Array
         (
             [0] => zend_version
             [1] => func_num_args
             // …
         )
     [user] => Array
         (
         )
)
  */
<?php
$functions = get_defined_functions();
echo count($functions['internal']);
// 1857
<?php
$name = 'Marcus Börger';
if (function_exists('mb_strtolower')) {
  echo mb_strtolower($name, 'UTF-8');
  // marcus börger
} else {
  echo strtolower($name);
  // marcus b?rger
}
User-Defined Functions
Rules

Any valid PHP code is allowed inside
functions, including other functions and class
definitions

Function names are case-insensitive

Once defined, a function cannot be undefined
<?php
function nextId($posts)
{
   return max(array_keys($posts)) + 1;
}
$posts = array(
   1233 => array(/* … */),
   1234 => array(/* … */),
);
echo nextId($posts); // 1235
Type Hinting
<?php
function nextId(array $posts)
{
   return max(array_keys($posts)) + 1;
}
$posts = array(
   1233 => array(/* … */),
   1234 => array(/* … */),
);
echo nextId($posts); // 1235
echo nextId(1234);
// Argument 1 passed to nextId() must be an
array, integer given
Multiple Arguments
<?php
function isPublished(DateTime $published,
$draft)
{
  if ($draft) { return false; }
  $now = new DateTime();
  return $now >= $published;
}
$published = new
DateTime('2010-12-16T18:00:00-05:00');
$draft = false;
var_dump(isPublished($published, $draft));
// bool(true)
Default Arguments
<?php
function isPublished(DateTime $published,
$draft, $now = false)
{
  if ($draft) { return false; }
  $now = $now ? $now : new DateTime();
  return $now >= $published;
}
$published = new
DateTime('2010-12-16T18:00:00-05:00');
$draft = false;
$now = new
DateTime('2010-12-16T17:59:59-05:00');
var_dump(isPublished($published, $draft,
$now));
// bool(false)
Function Overloading
     (not really)
<?php
function nextId($arg1)
{
   switch (true) {
     case is_array($arg1):
       return max(array_keys($arg1)) + 1;
     case is_int($arg1):
       return $arg1 + 1;
   }
}
$posts = array(
   1233 => array(/* … */),
   1234 => array(/* … */),
);
echo nextId($posts); // 1235
echo nextId(1234); // 1235
Variable Number of
    Arguments
<?php
function mostRecent()
{
   $max = false;
   foreach (func_get_args() as $arg) {
     $max = $arg > $max ? $arg : $max;
   }
   return $max;
}
$mostRecent = mostRecent(
     new DateTime('2010-12-14T18:00:00'),
     new DateTime('2010-12-16T18:00:00'),
     new DateTime('2010-12-15T18:00:00')
);
// 2010-12-16T18:00:00
Objects
Basics


Encapsulate metadata and behavior

metadata => properties (variables, constants)

behavior => methods (functions)
Anonymous Objects
Cast an Associative
        Array to (object)
<?php
$a = array(
   'foo' => 'bar',
);
$o = (object) $a;
echo $o->foo; // 'bar'
stdClass


$o = new stdClass;
$o->foo = 'bar';
echo $o->foo; // 'bar'
Declaring a Class

<?php
class Foo
{
}
Declaring Properties

<?php
class Foo
{
  protected $bar = 'bar';
}
Extending Classes

<?php
class FooBar extends Foo
{
}
Visibility
public: accessible from instances or within
methods of any visibility, and within
extending classes

protected: accessible only within instance
methods of any visibility, and within
extending classes

private: accessible only within instance
methods from the declaring class
Modifiers


final: cannot be overridden in extending
classes

abstract: must be overridden in extending
classes
Abstract Classes
<?php
abstract class AbstractFoo
{
  abstract public function sayBar();
}

class Foo extends AbstractFoo
{
  public $bar;

    public function sayBar()
    {
      echo $this->bar;
    }
}
Interfaces
"Blueprints" for classes

Typically indicate behaviors found in
implementing classes

You can implement many interfaces, but only
extend once

  Allows you to compose multiple behaviors
  into a single class
<?php
interface Resource {
  public function getResource();
}
interface Dispatcher {
  public function dispatch();
}

abstract class DispatchableResource
implements Resource,Dispatcher
{
  // …
}
<?php
interface Resource { /* … */ }
interface Dispatcher { /* … */ }

abstract class DispatchableResource
implements Resource,Dispatcher
{
  protected $resource;
  public function getResource() {
    return $this->resource;
  }
  public function dispatch() {
    return 'Dispatched ' . $this-
>getResource();
  }
}
<?php
interface Resource { /* … */ }
interface Dispatcher { /* … */ }

abstract class DispatchableResource
implements Resource,Dispatcher { /* … */ }

class TrafficCop extends
DispatchableResource
{
  protected $resource = 'traffic cop';
}
$cop = new TrafficCop();
echo $cop->dispatch();
// 'Dispatched traffic cop'
Useful Tidbits
Type hinting: you can indicate an interface, abstract
   class, or class name "hint" with parameters:

 public function doSomething(Dispatcher
 $dispatcher) {/* … */}


                  Test for types:

 if ($object instanceof Dispatcher) { }


  Type hints look at the entire inheritance chain,
                including interfaces!
Statics
Static properties and methods may be
accessed without instantiation

Requires a different token to access:

  ClassName::$varName for variables

  Classname::methodName() for methods

  or use self or parent or static within
  a class, instead of the class name
Late Static Binding



static is used for "Late Static
Binding" (LSB)
<?php
class BasicPerson
{
  public static $sex = 'unisex';
  public static function getSex()
  {
    return static::$sex;
  }
}
class MalePerson extends BasicPerson
{
  public static $sex = 'male'; // LSB
}
echo BasicPerson::getSex(); // 'unisex'
BasicPerson::$sex = 'female';
echo BasicPerson::getSex(); // 'female'
echo MalePerson::getSex(); // 'male'
Magic Methods
Tie into different states of an object
Construct, Destruct, and
        Invoke
 __construct — Constructor (used when
 "new Class" is called)

 __destruct — Destructor (called when
 object is destroyed)

 __invoke — Call an object instance like a
 function (echo $object();)
Sleep and Wakeup


__sleep — Define what properties should be
serialized, and how

__wakeup — Determine how to initialize state
from serialized instance
Call and Call Static


Overload method access

__call

__callStatic
Get and Set


Overload property access

__get

__set
Cardinal Rule



Objects should model discrete concepts, and
not just be a container for functions.
Questions?
Thank You
Bradley Holt & Matthew Weier O’Phinney
License
Intermediate PHP is licensed under a Creative
Commons Attribution-NonCommercial-ShareAlike
3.0 Unported License.

Intermediate PHP

  • 1.
    Intermediate PHP Bradley Holt& Matthew Weier O’Phinney
  • 2.
  • 3.
    Associate values tokeys Keys can be integers (enumerative arrays) or strings (associative arrays) Values can be primitive types, objects, or other arrays (multidimensional arrays)
  • 4.
    <?php $post = array( 'id' => 1234, 'title' => 'Intermediate PHP', 'updated' => new DateTime( '2010-12-16T18:00:00-05:00' ), 'draft' => false, 'priority' => 0.8, 'categories' => array('PHP', 'BTV') );
  • 5.
    Reading, Writing, and Appending Arrays
  • 6.
    <?php $post = array( 'id' => 1234, 'title' => 'Intermediate PHP', // … ); echo $post['title']; // Intermediate PHP
  • 7.
    <?php $post = array( 'id' => 1234, 'title' => 'Intermediate PHP', // … ); $post['title'] = 'PHP 201';
  • 8.
    <?php $post = array( 'id' => 1234, 'title' => 'Intermediate PHP', 'updated' => new DateTime( '2010-12-16T18:00:00-05:00' ), 'draft' => false, 'priority' => 0.8, 'categories' => array('PHP', 'BTV') ); $post['summary'] = 'Arrays, functions, and objects';
  • 9.
    <?php $post = array( // … 'categories' => array('PHP', 'BTV') ); $post['categories'][] = 'Programming'; print_r($post['categories']); /* Array ( [0] => PHP [1] => BTV [2] => Programming ) */
  • 10.
    <?php $post = array( // … 'categories' => array('PHP', 'BTV') ); $post['categories'][1] = 'Burlington'; print_r($post['categories']); /* Array ( [0] => PHP [1] => Burlington ) */
  • 11.
  • 12.
    <?php $post = array( // … 'categories' => array('PHP', 'BTV') ); foreach ($post['categories'] as $v) { echo $v . PHP_EOL; } /* PHP BTV */
  • 13.
    <?php $post = array( // … 'categories' => array('PHP', 'BTV') ); foreach ($post['categories'] as $k => $v) { echo $k . ': ' . $v . PHP_EOL; } /* 0: PHP 1: BTV */
  • 14.
    <?php $post = array( 'id' => 1234, 'title' => 'Intermediate PHP', // … ); foreach ($post as $k => $v) { echo $k . ': ' . $v . PHP_EOL; } /* id: 1234 title: Intermediate PHP … */
  • 15.
  • 16.
    <?php $post = array( // … 'categories' => array('PHP', 'BTV') ); echo implode(', ', $post['categories']); // PHP, BTV
  • 17.
    <?php $post = array( // … 'categories' => explode(', ', 'PHP, BTV') ); print_r($post['categories']); /* Array ( [0] => PHP [1] => BTV ) */
  • 18.
    Array Key Exists, InArray, and Array Keys
  • 19.
    <?php $post = array( 'id' => 1234, // … 'categories' => array('PHP', 'BTV') ); if (array_key_exists('categories', $post)) { echo implode(', ', $post['categories']); } else { echo 'Uncategorized'; }
  • 20.
    <?php $post = array( // … 'categories' => array('PHP', 'BTV') ); if (in_array('PHP', $post['categories'])) { echo 'PHP: Hypertext Preprocessor'; }
  • 21.
    <?php $posts = array( 1233 => array(/* … */), 1234 => array(/* … */), ); print_r(array_keys($posts)); /* Array ( [0] => 1233 [1] => 1234 ) */
  • 22.
  • 23.
    <?php $post = array( // … 'categories' => array('PHP', 'BTV') ); sort($post['categories']); print_r($post['categories']); /* Array ( [0] => BTV [1] => PHP ) */
  • 24.
    Sorting Function Attributes Some sort by value, others by key Some maintain key association, others do not Some sort low to high, others high to low Some are case sensitive, some are not See: http://www.php.net/manual/en/array.sorting.php
  • 25.
    Sorting Functions array_multisort() rsort() asort() shuffle() arsort() sort() krsort() uasort() ksort() uksort() natcasesort() usort() natsort()
  • 26.
    Stacks and Queues Photoby Phil Cooper Photo by Thomas W
  • 27.
  • 28.
    <?php $post = array( // … 'categories' => array('PHP') ); array_push($post['categories'], 'BTV'); echo array_pop($post['categories']); // BTV print_r($post['categories']); /* Array ( [0] => PHP ) */
  • 29.
  • 30.
    <?php $post = array( // … 'categories' => array('BTV') ); array_unshift($post['categories'], 'PHP'); print_r($post['categories']); /* Array ( [0] => PHP [1] => BTV ) */ echo array_pop($post['categories']); // BTV
  • 31.
  • 32.
  • 33.
    <?php print_r(get_defined_functions()); /* Array ( [internal] => Array ( [0] => zend_version [1] => func_num_args // … ) [user] => Array ( ) ) */
  • 34.
    <?php $functions = get_defined_functions(); echocount($functions['internal']); // 1857
  • 35.
    <?php $name = 'MarcusBörger'; if (function_exists('mb_strtolower')) { echo mb_strtolower($name, 'UTF-8'); // marcus börger } else { echo strtolower($name); // marcus b?rger }
  • 36.
  • 37.
    Rules Any valid PHPcode is allowed inside functions, including other functions and class definitions Function names are case-insensitive Once defined, a function cannot be undefined
  • 38.
    <?php function nextId($posts) { return max(array_keys($posts)) + 1; } $posts = array( 1233 => array(/* … */), 1234 => array(/* … */), ); echo nextId($posts); // 1235
  • 39.
  • 40.
    <?php function nextId(array $posts) { return max(array_keys($posts)) + 1; } $posts = array( 1233 => array(/* … */), 1234 => array(/* … */), ); echo nextId($posts); // 1235 echo nextId(1234); // Argument 1 passed to nextId() must be an array, integer given
  • 41.
  • 42.
    <?php function isPublished(DateTime $published, $draft) { if ($draft) { return false; } $now = new DateTime(); return $now >= $published; } $published = new DateTime('2010-12-16T18:00:00-05:00'); $draft = false; var_dump(isPublished($published, $draft)); // bool(true)
  • 43.
  • 44.
    <?php function isPublished(DateTime $published, $draft,$now = false) { if ($draft) { return false; } $now = $now ? $now : new DateTime(); return $now >= $published; } $published = new DateTime('2010-12-16T18:00:00-05:00'); $draft = false; $now = new DateTime('2010-12-16T17:59:59-05:00'); var_dump(isPublished($published, $draft, $now)); // bool(false)
  • 45.
  • 46.
    <?php function nextId($arg1) { switch (true) { case is_array($arg1): return max(array_keys($arg1)) + 1; case is_int($arg1): return $arg1 + 1; } } $posts = array( 1233 => array(/* … */), 1234 => array(/* … */), ); echo nextId($posts); // 1235 echo nextId(1234); // 1235
  • 47.
  • 48.
    <?php function mostRecent() { $max = false; foreach (func_get_args() as $arg) { $max = $arg > $max ? $arg : $max; } return $max; } $mostRecent = mostRecent( new DateTime('2010-12-14T18:00:00'), new DateTime('2010-12-16T18:00:00'), new DateTime('2010-12-15T18:00:00') ); // 2010-12-16T18:00:00
  • 49.
  • 50.
    Basics Encapsulate metadata andbehavior metadata => properties (variables, constants) behavior => methods (functions)
  • 51.
  • 52.
    Cast an Associative Array to (object) <?php $a = array( 'foo' => 'bar', ); $o = (object) $a; echo $o->foo; // 'bar'
  • 53.
    stdClass $o = newstdClass; $o->foo = 'bar'; echo $o->foo; // 'bar'
  • 54.
  • 55.
    Declaring Properties <?php class Foo { protected $bar = 'bar'; }
  • 56.
  • 57.
    Visibility public: accessible frominstances or within methods of any visibility, and within extending classes protected: accessible only within instance methods of any visibility, and within extending classes private: accessible only within instance methods from the declaring class
  • 58.
    Modifiers final: cannot beoverridden in extending classes abstract: must be overridden in extending classes
  • 59.
  • 60.
    <?php abstract class AbstractFoo { abstract public function sayBar(); } class Foo extends AbstractFoo { public $bar; public function sayBar() { echo $this->bar; } }
  • 61.
    Interfaces "Blueprints" for classes Typicallyindicate behaviors found in implementing classes You can implement many interfaces, but only extend once Allows you to compose multiple behaviors into a single class
  • 62.
    <?php interface Resource { public function getResource(); } interface Dispatcher { public function dispatch(); } abstract class DispatchableResource implements Resource,Dispatcher { // … }
  • 63.
    <?php interface Resource {/* … */ } interface Dispatcher { /* … */ } abstract class DispatchableResource implements Resource,Dispatcher { protected $resource; public function getResource() { return $this->resource; } public function dispatch() { return 'Dispatched ' . $this- >getResource(); } }
  • 64.
    <?php interface Resource {/* … */ } interface Dispatcher { /* … */ } abstract class DispatchableResource implements Resource,Dispatcher { /* … */ } class TrafficCop extends DispatchableResource { protected $resource = 'traffic cop'; } $cop = new TrafficCop(); echo $cop->dispatch(); // 'Dispatched traffic cop'
  • 65.
  • 66.
    Type hinting: youcan indicate an interface, abstract class, or class name "hint" with parameters: public function doSomething(Dispatcher $dispatcher) {/* … */} Test for types: if ($object instanceof Dispatcher) { } Type hints look at the entire inheritance chain, including interfaces!
  • 67.
    Statics Static properties andmethods may be accessed without instantiation Requires a different token to access: ClassName::$varName for variables Classname::methodName() for methods or use self or parent or static within a class, instead of the class name
  • 68.
    Late Static Binding staticis used for "Late Static Binding" (LSB)
  • 69.
    <?php class BasicPerson { public static $sex = 'unisex'; public static function getSex() { return static::$sex; } } class MalePerson extends BasicPerson { public static $sex = 'male'; // LSB } echo BasicPerson::getSex(); // 'unisex' BasicPerson::$sex = 'female'; echo BasicPerson::getSex(); // 'female' echo MalePerson::getSex(); // 'male'
  • 70.
    Magic Methods Tie intodifferent states of an object
  • 71.
    Construct, Destruct, and Invoke __construct — Constructor (used when "new Class" is called) __destruct — Destructor (called when object is destroyed) __invoke — Call an object instance like a function (echo $object();)
  • 72.
    Sleep and Wakeup __sleep— Define what properties should be serialized, and how __wakeup — Determine how to initialize state from serialized instance
  • 73.
    Call and CallStatic Overload method access __call __callStatic
  • 74.
    Get and Set Overloadproperty access __get __set
  • 75.
    Cardinal Rule Objects shouldmodel discrete concepts, and not just be a container for functions.
  • 76.
  • 77.
    Thank You Bradley Holt& Matthew Weier O’Phinney
  • 78.
    License Intermediate PHP islicensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License.

Editor's Notes

  • #2 \n
  • #3 \n
  • #4 \n
  • #5 \n
  • #6 \n
  • #7 Reading from an associative array\n
  • #8 Writing to an associative array\n
  • #9 Appending to an associative array\n
  • #10 Appending to an enumerative array\n
  • #11 Writing to an enumerative array\n
  • #12 \n
  • #13 Iterating values in an enumerative array\n
  • #14 Iterating key value pairs in an enumerative array\n
  • #15 Iterating key value pairs in an associative array\n
  • #16 \n
  • #17 Implode returns a string, not an array.\n
  • #18 Explode returns an array.\n
  • #19 \n
  • #20 \n
  • #21 \n
  • #22 \n
  • #23 \n
  • #24 \n
  • #25 \n
  • #26 \n
  • #27 The SPL in PHP 5.3 has new data structures that can make stacks and queues more performant and memory efficient.\n
  • #28 \n
  • #29 Example of an array used as a stack (FILO)\n
  • #30 \n
  • #31 Example of an array used as a queue (FIFO)\n
  • #32 \n
  • #33 \n
  • #34 \n
  • #35 The number of internal functions will depend on which extensions you have installed.\n
  • #36 The multibyte string (mbstring) extension allows you to safely manipulate multibyte strings (e.g. UTF-8).\n
  • #37 \n
  • #38 \n
  • #39 This function finds the highest array key and adds one.\n
  • #40 \n
  • #41 You can type hint on array and class names, but not primitive data types like strings and integers.\n
  • #42 \n
  • #43 This function determines if a post is published based on its published date and whether or not it&amp;#x2019;s a draft.\n
  • #44 \n
  • #45 This is essentially the same as the previous function but allows you to specific when &amp;#x201C;now&amp;#x201D; is.\n
  • #46 \n
  • #47 throw new InvalidArgumentException();\n
  • #48 \n
  • #49 \n
  • #50 \n
  • #51 We already know about variables and functions now!\n
  • #52 &quot;Anonymous&quot; as they are not of any specific class; they&apos;re basically equivalent to &quot;bare objects&quot; or &quot;object literals&quot; in JavaScript.\n
  • #53 \n
  • #54 \n
  • #55 \n
  • #56 Definitions may not use computations or runtime values (other than constants); they must be concrete.\n
  • #57 \n
  • #58 \n
  • #59 \n
  • #60 \n
  • #61 \n
  • #62 Interfaces can extend other interfaces. Methods in interfaces must be public.\n
  • #63 \n
  • #64 \n
  • #65 \n
  • #66 \n
  • #67 \n
  • #68 \n
  • #69 \n
  • #70 \n
  • #71 \n
  • #72 \n
  • #73 \n
  • #74 \n
  • #75 \n
  • #76 If you want the latter, use namespaces!\n
  • #77 \n
  • #78 \n
  • #79 \n