Object-Oriented PHP for Beginners

Drupalers

James Candan /jɑnˈdən/

7 years PHP

5 years Drupal

 

Object-Oriented PHP for Beginners | Tuts+
DEC 23, 2011 / JASON LENGSTORF

http://code.tutsplus.com/tutorials/object-oriented-php-for-beginners--net-12762

 

Prerequisites

<?php

// Variables
$fruit = "apple";
  • Variables
  • Functions
  • Arrays/Loops
  • Logic
<?php

// Variables
$fruit = "apple";

// Logic operators
if ( $fruit == "apple" ) { 
    // can include html in string output
    echo "sweeeeeet!<br />"; 
}

// Arrays
$colors = array("blue", "purple", 'red');

// Loops
foreach ($colors as $color) {
    echo $color . "<br />";
}

<?php

// Variables
$fruit = "apple";

// Logic operators
if ( $fruit == "apple" ) { 
    // can include html in string output
    echo "sweeeeeet!<br />"; 
}

<?php

// Variables
$fruit = "apple";

// Logic operators
if ( $fruit == "apple" ) { 
    // can include html in string output
    echo "sweeeeeet!<br />"; 
}

// Arrays
$colors = array("blue", "purple", 'red');

// Loops
foreach ($colors as $color) {
    echo $color . "<br />";
}

// Functions
function color_exists($needle, $haystack) {
    return in_array($needle, $haystack);
}

// assign returned output to variable
$is_brown_good = color_exists("brown", $colors);

Basics

You might already...

Object properties

<?php

$node['type'];
$node['title'];

Not the same as an Array.

<?php

$node = node_load($nid);
echo $node->type;
echo $node->title;
class User {
  ...

  public function run($miles) {
    $this->miles += $miles;
  }
}

$user = new User();
$user->run($miles);

Consider this:

Objectives

  • High level overview
  • Define common terms
  • Review practical examples

Understanding OOP

Style

  • Group similar code into CLASSES
  • DRY - Don't Repeat Yourself
  • Simple, Straightforward Structure

"Object-oriented programming is a style of coding that allows developers to group similar tasks into classes."

Objects and Classes

Before you can get too deep into the finer points of OOP, a basic understanding of the differences between objects and classes is necessary.

Developers start talking about objects and classes, and they appear to be interchangeable terms.

 This is not the case.

Recognizing the Differences Between Objects and Classes

  • Classes are like blue prints
  • Objects are the actual Houses

Properties

Height

Methods

Come

Property values

Color: Gray

Eye Color: Brown

Height: 18"

Length: 36"

Weight: 30 lbs

Methods

Sit

Lay Down

Shake

Come

Create Instance

Object-Oriented Thinking
JULY 16, 2014 / RODRIGO ARAÚJO

http://www.universocomputacao.com/object-oriented-thinking/

Class

Object

Length

Weight

Eye Color

Color

Shake

Lay Down

Sit

Maximus

Structure

Structuring Classes

<?php

class Dog
{
    // class properties
    public $color;
    public $eye_color;
    public $height;
    public $length;
    public $weight;

    // class methods
    public function sit() {

    }
    public function lay_down() {

    }
    public function shake() {

    }
    public function come() {

    }
}
<?php

$maximus = new Dog();
$maximus->color     = "Gray";
$maximus->eye_color = "Brown";
$maximus->height    = 18;
$maximus->length    = 36;
$maximus->weight    = 30;

?>

Defining Class Properties

<?php
 
class Person
{
    // Let's write our first property
    public $name = "john";
}
<?php
 
class Person
{
    // Let's write our first property
    public $name = "john";
    public $test = "blue";
}

$my_person = new Person();
<?php
 
class Person
{

}
<?php
 
class Person
{
    // Let's write our first property
    public $name = "john";
    public $test = "blue";
}

$my_person = new Person();


var_dump($my_person);


echo $my_person->name;

Defining Class Methods

<?php
 
class Person
{
    public $name;
    public $weight = 0;
    public $miles = 0; 






}

$my_person = new Person();
$my_person->name = "john";
$my_person->weight = 190;

// notice: weight is 190
var_dump($my_person);
<?php
 
class Person
{
    public $name;
    public $weight = 0;
    public $miles = 0;   

    // Let's write our first method
    public function run($miles) {
        $this->miles += $miles;
        $this->weight -= $miles * .2;
    }
}

$my_person = new Person();
$my_person->name = "john";
$my_person->weight = 190;

// notice: weight is 190
var_dump($my_person);
<?php
 
class Person
{
    public $name;
    public $weight = 0;
    public $miles = 0;  

    // Let's write our first method
    public function run($miles) {
        $this->miles += $miles;
        $this->weight -= $miles * .2;
    }
}

$my_person = new Person();
$my_person->name = "john";
$my_person->weight = 190;

// notice: weight is 190
var_dump($my_person);

// notice: we've lost weight from running
$my_person->run(10);
var_dump($my_person);

PHP vs Javascript

<?php
 
class Person
{
    public $name;
    public $weight = 0;
    public $miles = 0;  

    // Let's write our first method
    public function run($miles) {
        $this->miles += $miles;
        $this->weight -= $miles;
    }
}

$my_person = new Person();
$my_person->name = "john";
$my_person->weight = 170;

// notice: weight is 170
var_dump($my_person);

// notice: we've lost weight from running
$my_person->run(5);
var_dump($my_person);

<script type="text/javascript">

var Person = function () {
    this.name = '';
    this.weight = 0;
    this.miles = 0;
};

Person.prototype.run = function (miles) {
    this.miles += miles;
    this.weight -= miles;
};

var my_person = new Person();
my_person.name = "john";
my_person.weight = 170;

console.log(my_person.name); // john
console.log(my_person.weight); // 170
console.log(my_person.miles); // 0

my_person.run(5);
console.log(my_person.name); // john
console.log(my_person.weight); // 165
console.log(my_person.miles); // 5

</script>

Magic Methods

<?php

class Dog {
        
  public $legs;
  public $color;
  public $eye_color;
    
  public function __construct($color, $eye_color) {
    $this->legs = 4;
    $this->color = $color;
    $this->eye_color = $eye_color;
  }   
}

$rover = new Dog("black/white", "light blue");
var_dump($rover);

Constructor

<?php

class Dog {

  public $legs = 4;

}

$rover = new Dog();
echo $rover;

// returns a Fatal error.
<?php

class Dog {

  public $legs = 4;

  public function __toString() {
    return "Dogs have $this->legs legs.";
  }

}

$rover = new Dog();
echo $rover;

// outputs "Dogs have 4 legs."

__toString

Inheritance

class Shape 
{
    public $sides;
    public $fill_color;

    public function __construct($sides) {
        $this->sides = $sides;
    }

    public function get_angle() {
        return 360 / $this->sides;
    }
}

$hexagon = new Shape(6);

echo $hexagon->get_angle(); // --> 60
class Rectangle extends Shape
{
    public $sides = 4;
    public $length;
    public $width;

    public function __construct($width, $length){
        $this->length = length;
        $this->width = width;
    }
}
class Square extends Rectangle
{
    public function __construct($width) {
        $this->length = width;
        $this->width = width;
    }
}
$my_square = new Square();
echo $my_square->get_angle(); // --> 90

$my_hexagon = new Shape(6);
echo $my_square->get_angle(); // --> 120

Extends

class Rectangle extends Shape
{
    public $sides = 4;
    public $length;
    public $width;

    public function __construct($width, $length){
        $this->length = length;
        $this->width = width;
    }
}
class Shape 
{
    public $sides;
    public $fill_color;

    public function __construct($sides) {
        $this->sides = $sides;
    }

    public function get_angle() {
        return 360 / $this->sides;
    }
}

$hexagon = new Shape(6);

echo $hexagon->get_angle(); // --> 60

Override

class Rectangle extends Shape
{
    public $length;
    public $width;

    public function __construct($width, $length){
        parent::__construct(4);
        $this->length = length;
        $this->width = width;
    }
}
class Shape 
{
    public $sides;
    public $fill_color;

    public function __construct($sides) {
        $this->sides = $sides;
    }

    public function get_angle() {
        return 360 / $this->sides;
    }
}

$hexagon = new Shape(6);

echo $hexagon->get_angle(); // --> 60

Parent

Visibility

<?php
 
class Person
{
    public name;
    public weight = 0;    

    public function run($miles) {
        $this->weight -= $miles;
    }
}

Can be accessed anywhere, both within the class and externally.

<?php

$my_person = new Person();

// public property and method I can access
$my_person->weight = 100;
$my_person->run(5);

?>

Public

Can only be accessed within the class itself or in descendant classes (classes that extend the class containing the protected method).

Protected

<?php

class Shape 
{
    protected $sides;
    protected $fill_color;

    public function __construct($sides) {
        $this->sides = $sides;
    }

    public function get_angle() {
        return 360 / $this->sides;
    }

    public function get_sides() {
        return $this->sides;
    }
}
<?php

class Rectangle extends Shape{
    protected $length;
    protected $width;

    public function __construct($width, $length){
        $this->sides = 4; // <-- this is ok.
        $this->length = length;
        $this->width = width;
    }
}

// Accessing protected properties would be fatal
$rect = new Rectangle(3, 5);
echo $rect->sides; // --> fatal error
echo $rect->get_sides(); // --> this is ok.
?>

Accessible only from within the class that defines it. This means that even if a new class extends the class that defines a private property, that property or method will not be available at all within the child class.

Private

<?php
 
class Person
{
    protected $name;
    private $walks; // boolean  

    public function get_name() {
        return $this->name;
    }

    public function set_name($name) {
        $this->name = $name;
    }  

    public function get_walks() {
        return $this->walks;
    }

    public function set_walks($walks) {
        $this->walks = $walks;
    }
}
<?php

class Infant extends Person{

    public function __construct($name){
        $this->name = $name; // <-- Successfully sets the name to protected
        $this->walks = FALSE; // <-- NOT OK.
        $this->set_walks(FALSE); // <-- OK.
    }
}

$my_person = new Infant("Charlie");

// cannot access protected from outside the class
echo $my_person->name; // --> fatal error

// can run public methods outside the class
echo $my_person->get_walks(); // correctly outputs false

// but accessing private elements would be fatal
echo $my_person->walks; // --> fatal error

?>
<?php

class MyClass 
{
  public static function plusOne() {
      return "The count is " . ++self::$count . ".<br />";
  }
}

can be accessed without first instantiating the class

Note:

When accessing static properties, the dollar sign
($) comes after the scope resolution operator (::).

Static

<?php

do
{
  // Call plusOne without instantiating MyClass
  echo MyClass::plusOne();
} while ( MyClass::$count < 10 );

"In languages like c# and java, statics are a part of the language. You can do things like... Console.WriteLine() or int.TryParse(), String.Join() etc... these are all utilities"

Console.WriteLine();
int.TryParse();
String.Join();

 

Comments |When to Use Static Methods
FEB 20, 2015 / jrenton

http://verraes.net/2014/06/when-to-use-static-methods-in-php/#comment-1865595749

 

<?php
$time = Time::from("11:45");
<?php
$sum = Calculator::sum(1, 2);

 

When to Use Static Methods
JUN 14, 2014 / MATHIAS VERRAES

http://verraes.net/2014/06/when-to-use-static-methods-in-php/

 

Example use cases:

Static Examples

Comments

<?php

/**
 * Dear maintainer:
 * 
 * Once you are done trying to 'optimize' this routine,
 * and have realized what a terrible mistake that was,
 * please increment the following counter as a warning
 * to the next guy:
 * 
 * total_hours_wasted_here = 42
 */
<?php

// When I wrote this, only God and I understood what I was doing
// Now, God only knows
// drunk, fix later
long john; // silver
# TODO: Figure out what i'm doing here and comment accordingly
// Magic. Do not touch.
// John! If you’ll svn remove this once more,
// I’ll shut you, for God’s sake!
// That piece of code is not “something strange”!
// That is THE AUTH VALIDATION.

What are some of the funniest comments in source code? | Quora

Last asked: 22 Dec, 2013

http://www.quora.com/What-are-some-of-the-funniest-comments-in-source-code

 

  • Starts with a forward slash and two asterisks (/**)
  • Always associated with just one structural element in PHP
    • a file, class, interface, trait, function, constant, method, property or variable.
/**
  * Returns the name of this object.
  *
  * @return string
  */

Example

DocBlocks

Tags

  • Tags are a type of specialized information (meta-data)
  • Begins on a new line with an @ symbol
  • Arguments that provide additional context
<?php
 
/**
 * @author James Candan <james@codejourneymen.com>
 * @copyright 2015 Acme
 * @license http://www.php.net/license/3_01.txt PHP License 3.01

. . .

 * @param string $val a value required for the class
 * @return void
 */

Example

Example

<?php
 
/**
 * A simple class
 *
 * This is the long description for this class,
 * which can span as many lines as needed. It is
 * not required, whereas the short description is
 * necessary.
 *
 * It can also span multiple paragraphs if the
 * description merits that much verbiage.
 *
 * @author Jason Lengstorf <jason.lengstorf@ennuidesign.com>
 * @copyright 2010 Ennui Design
 * @license http://www.php.net/license/3_01.txt PHP License 3.01
 */
class SimpleClass
{
  /**
   * A public variable
   *
   * @var string stores data for the class
   */
  public $foo;
 
  /**
   * Sets $foo to a new value upon class instantiation
   *
   * @param string $val a value required for the class
   * @return void
   */
  public function __construct($val)
  {
      $this->foo = $val;
  }
 
  /**
   * Multiplies two integers
   *
   * Accepts a pair of integers and returns the
   * product of the two.
   *
   * @param int $bat a number to be multiplied
   * @param int $baz a number to be multiplied
   * @return int the product of the two parameters
   */
  public function bar($bat, $baz)
  {
      return $bat * $baz;
  }
}
 
?>

Auto-documentation

Tools such as phpDocumentor can be used to generate professional documentation directly from the source code of your PHP project. 

 

Namespacing in PHP | Tuts+
OCT 1, 2012 / 
ELIAS ZERROUQ

http://code.tutsplus.com/tutorials/namespacing-in-php--net-27203

 

Namespacing

What's a Namespace?

Namespacing is used to avoid conflicting definitions and introduce more flexibility and organization in your code base.

Defining a Namespace

A namespace definition

  • Must be first statement in a PHP file
  • Uses the "namespace" keyword
  • Must start with a letter or underscore, followed by any number of letters, numbers, or underscores
<?php 

/**
 * @file my_project.php
 */

namespace MyProject {
    // Regular PHP code goes here, anything goes!
    function run() 
    {
        echo 'Running from a namespace!';
    }
}
<?php

require 'my_project.php';

run();  // --> Fatal error: 
        // Call to undefined function run()


\MyProject\run(); // --> success!

Sub-namespaces

  • Follow a certain hierarchy, much like directories
  • You should store sub-namespaces in sub-directories
  • PHP uses the backslash as its namespace separator
  • You can have as many sub-namespaces as you want.
<?php 
/**
 * @file myproject/database/connection.php
 */

namespace MyProject\Database
 
class Connection {
    // Handling database connections
}
<?php 

/**
 * @file myproject/blog/auth/handler/social/twitter.php
 */

namespace MyProject\Blog\Auth\Handler\Social;
 
class Twitter {
    // Handles Twitter authentication
}

Comparison

<?php

/**
 * Let's create two person arrays, each 
 * containing a bit of info about the person.
 */

$person1 = array(
  'name' => 'Tom',
  'job' => 'Button-Pusher',
  'age' => 34
);
 
$person2 = array(
  'name' => 'John',
  'job' => 'Lever-Puller',
  'age' => 41
);

function changeJob($person, $new_job) {
  $person['job'] = $new_job; // Change job
  return $person;
}

function happyBirthday($person) {
  ++$person['age']; // Add 1 to age
  return $person;
}

// Tom got a promotion and had a birthday
$person1 = changeJob($person1, 'Box-Mover');
$person1 = happyBirthday($person1);
 
// John just had a birthday
$person2 = happyBirthday($person2);

<?php

/**
 * @file
 * Given two Linkedin contacts, we want to 
 * update their job title and age.
 */

class Person
{
  private $_name;
  private $_job;
  private $_age;

  public function __construct($name, $job, $age) {
    $this->_name = $name;
    $this->_job = $job;
    $this->_age = $age;
  }

  /**
   * Set person's job title.
   *
   * @param $newjob
   */
  public function changeJob($new_job) {
    $this->_job = $new_job;
  }

  /**
   * Increment person's age.
   */
  public function happyBirthday() {
    ++$this->_age;
  }

  // ...
  // getters and setters
}

 
/**
 * Let's create two person objects, each 
 * containing a bit of info about the person.
 */

$person1 = new Person("Tom", "Button-Pusher", 34);
$person2 = new Person("John", "Lever Puller", 41);


// Tom got a promotion and had a birthday
$person1->changeJob("Box-Mover");
$person1->happyBirthday();

// John just had a birthday
$person2->happyBirthday();

Procedural

OOP

Summary

  • Classes are blueprints
  • Objects are actual houses
  • Classes can have Parent - Child Inheritance via "extends"
  • Visibility
    • Public - can be seen from anywhere
    • Protected - can be seen from Class & Subclass
    • Private - can ONLY be seen from within Class
    • Static - Doesn't require instantiating (Utilities)
  • Namespaces - like directories

Questions?

OOP PHP for Drupalers

By James Candan

OOP PHP for Drupalers

  • 1,617