You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
Brennen Bearnes 14082e4737 capsule history 3 years ago
..
Makefile php: add a little renderer that runs php examples 3 years ago
README.md capsule history 3 years ago
render.pl php: add a little renderer that runs php examples 3 years ago

README.md

% PHP for the Reluctant % Brennen Bearnes % 2020-08-28

So you have to review some PHP

I know...

::: incremental

  • ...it's gross. And what if someone notices? They might expect you to write the stuff.
  • You're probably never going to like PHP, but if you're anything like me you can learn to live with it. It's just a programming language, after all.
  • They're all bad.
  • Yes, even the ones you like.
  • With that in mind, this presentation aims to convey some important considerations and gotchas when presented with PHP code.

:::

Basics

::: incremental

  • High-level, dynamically typed, general-purpose language...
  • ...with pecularities due to its origins as a web templating tool
  • Procedural, with increasingly feature-rich OOP bolted on top
  • C-like syntax with elements lifted from Perl
  • Curly braces for blocks, semicolons for line endings
  • Stateless, shared-nothing, web-request-per-invocation model
  • Lots of builtin functions
  • Important behavior depends on configuration in ways that can be painful
  • Good docs, but take user comments with a grain of salt

:::

The capsule history

::: incremental

  • 1994-2003:
    • Origins and eventual wide availability on cheap shared hosting
    • Widely deployed in e-commerce and forum contexts
  • 2004: PHP 5.0: Recognizable form of the modern language with OOP
  • 2009: PHP 5.3: Matures substantially with namespaces, etc.
  • phpBB, osCommerce, MediaWiki, WordPress, Facebook, Drupal, Slack
    • A real mixed bag, if we're honest

:::

By 2020: Modern features, often implemented a little weird

  • Namespaces
  • Traits
  • A profiler and debugger (xdebug)
  • Anonymous functions and closures, generators, a smattering of functional idioms
  • Fairly standard autoloading of classes/modules
  • A package manager and repository, piles of 3rd-party libraries
  • Architecture astronauts aplenty

Hello world

The simplest example in PHP is just a file containing a string literal:

Hello world.
  • Until it sees a <?php tag, the interpreter will just print everything it encounters.
  • This is a legacy of PHP's origins as a templating language.
  • Modern code often hides this, but it's always lurking in the background.

Hello world, take 2

For a more traditional hello world, you'd write:

<?php
print "Hello world.\n";

Hello world, take 3

Or maybe:

<?php
  $name = 'world';
?>
Hello, <?= $name ?>.

Variables

  • Prefixed with $: $foo, $bar, $baz
  • The sigil is always $, and conveys no type information (unlike Perl, etc.)
  • Must begin with a letter, and can contain [A-Za-z0-9_]
  • Names are case-sensitive
  • Mutable, can contain a value of any type

Variable scope

These are your options:

<?php
// Global scope:
$foo = 1;

function bar () {
  // Local to function or method:
  $foo = 2;
  return $foo;
}

function baz () {
  // Access the $foo in global scope:
  global $foo;
  $foo = 3;
}

print "$foo\n";
print bar() . "\n";
baz();
print "$foo\n";

Constants

<?php
// Define a constant - all-caps by convention:
define('NAME', 'VALUE');

print NAME;

// Barewords can be risky since they're treated as string literals
// for undefined constants.  You can use constant() instead:
print constant('NAME');

Types

Booleans

<?php
// Literals, case-insensitive:
$are_cats_mammals = true;
$are_elephants_reptiles = false;

Numbers

<?php
// Floating point:
$foo = 1.234;

// Integer:
$foo = 1;

Numbers, fancy stuff

You'll rarely encounter any but the first syntax for these, but they do work:

<?php
// Floating point:
$foo = 1.234;
$foo = 1.2e3;
$foo = 7E-10;

# $foo = 1_234.567;

// Integer:
$foo = 1;
$foo = 0123;       // octal number (equivalent to 83 decimal)
$foo = 0x1A;       // hexadecimal number (equivalent to 26 decimal)
$foo = 0b11111111; // binary number (equivalent to 255 decimal)

# $foo = 1_234_567;  // decimal number (as of PHP 7.4.0)

Strings

<?php
$var = 'variable';

$double = "double-quoted with $var interpolation and escapes.\n";
$single = 'single-quoted';

// String concatenation:
print $double . "\n" . $single;

Heredocs & Nowdocs

An alternative string quoting mechanism, a la shell or Perl:

<?php
$foo = <<<EOT
bar
EOT;

To avoid variable interpolation and escapes, enclose the end marker in single quotes:

<?php
echo <<<'EOD'
Example of string spanning multiple lines
using nowdoc syntax. Backslashes are always treated literally,
e.g. \\ and \'.
EOD;

Arrays

<?php
// Old syntax:
$arr = array(1, 2, 3);

// Short syntax:
$arr = [1, 2, 3];

print_r($arr);

Arrays: The Swiss Army Knife of PHP data structures

  • Really "ordered maps"
  • Keys can be integers or strings, implicitly integers if not specified
  • Muddle a range of concepts that are distinct in other languages:
    • List / hash / dictionary / tree
  • Nestable
  • Can contain any data type
  • 0-indexed

Arrays: An ordered list

<?php
$foo = ['one', 'two', 'three'];
print_r($foo);

// Also perfectly legal - mixing types:
$foo = ['one', 2, 3.0];
print_r($foo);

Arrays: Key / value

<?php
$relenger_nicks = [
  'dancy'   => 'Ahmon Dancy',
  'brennen' => 'Brennen Bearnes',
  'liw'     => 'Lars Wirzenius',
  'longma'  => 'Jeena Huneidi',
];

Arrays: Nested data structures

<?php
$relengers = [
  [
    'nick'    => 'dancy',
    'name'    => 'Ahmon Dancy',
    'editors' => ['emacs', 'vim']
  ],
  [
    'nick'    => 'brennen',
    'name'    => 'Brennen Bearnes',
    'editors' => ['vim', 'nano', 'edit.com']
  ],
];

print $relengers[1]['name'] . ' uses ' . $relengers[1]['editors'][0];

Typecasting

Type coercion is common, and (unsurprisingly) a frequent cause of unexpected behavior. (More about that in a minute.)

Types can be explicitly cast like so:

<?php
$foo = true;

$foo_float = (float)$foo;
$foo_int   = (int)$foo;
$foo_str   = (string)$foo;
$foo_bool  = (bool)$foo;

Truth values

<?php
// Things that evaluate to false:
false, 0, -0, 0.0, -0.0, '0', '', null, []
// ...plus undefined variables.

Functions

Classes and objects

<?php

abstract class Encabulator {

  abstract public function reticulate ();

}

class TurboEncabulator extends Encabulator {

  protected $_splinesReticulated = false;

  public function reticulate () {
    $this->_splinesReticulated = true;
  }

}

$te = new TurboEncabulator();
$te->reticulate();

Traps for the unwary

With a basic overview of the language out of the way, let's go over some common pitfalls and sources of recurring bugs.

Undefined array elements

<?php
$arr = [
  'foo' => 'bar',
];

$baz = $arr['fo'];

Null objects

<?php
$foo->method();