PHPオブジェクト指向

PHP

今回はPHPオブジェクト指向に関する内容を紹介します。

クラス

クラス定義

class クラス名 {
    //プロパティ,
    //メソッド,
    //定数
}

// サンプル
class Student {
}
$st1=new Student();
$st2=new Student;  // ()を省略できる。

オブジェクトの比較

$st1=new Student();
$st2=new Student;  // ()を省略できる。

var_dump($st1==$st2); // true   値が同じ
var_dump($st1===$st2); //false オブジェクトが同じ

プロパティ

// クラス定義
class Student {
    public $name;      // プロパティ
    public $age=29;
}
// インスタンス
$stu1 = new Student;

// プロパティに値を設定
$stu1->name=’test2′;
$stu1->age=30;

// プロパティの値を取得
echo $stu1->name;

// プロパティ追加
$stu1->address=’TOKYO’;

// プロパティ削除
unset($stu1->address);

メソッド

class Student {
    public $name;
    public $age;
    // メソッドの場合publicを省略できる。デフォルト値:public
    public function Test() {
        echo ‘test’;
    }
}

$stu1=new Student;
$stu1->Test();

アクセス権限

public 外部からアクセスできる
private 外部からアクセスできない
protected 継承の対象でアクセスできる

class Student {
    private $name;
    private $sex;

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

__construct&__destruct

class Student{
    private $name;
    private $age;
     public function __construct($name, $age) {
          $this->name=$name;
          $this->age=$age;
     }

     public function __destruct() {
          echo “{$this->name}終了”;
     }
}

new Student()のとき、__constructが実行される。function名はクラス名と同じの場合、constructとして使う。

継承

class サブクラス extends クラス {
}

子クラスから親クラスのメソッドを実行する(parent)

class Person {
    public function test() {
        echo “Person”;
    }

    public function show() {
        echo “Person”;
    }
}

class Student extends Persion {
    public function show() {
        $this->test();
        parent::show();
    }
}

オーバーライドとオーバーロード

オーバーライド

class Person {
    public function test() {
        echo “Person”;
    }
}
class Student extends Persion {
    public function test() {
      echo “Student”;
    }
}

オーバーロード(使えない)

PHPではオーバーロードが使えない。

class Person {
    public function test() {
        echo “Person”;
    }
    public function test($arg) {   //エラー
        echo “Person”;
    }
}

マジックメソッドでオーバーロード

class Student{
    public function __call($fn_name, $fn_args){
      switch (count($fn_args)){
        case 1:
          echo “{$fn_name} para1”;
          break;
        case 2:
          echo “{$fn_name} para2”;
          break;
        default:
          echo “error”;
      }
    }
}
$stu=new Student;
$stu->show(1);
$stu->shwo(1,2);

static

class Person {
    public static $age=30;
    public static function test() {
        echo “Person”;
    }
}

Person::$age
Person::show();

self

class Person {
    public static $num=30;
    public function add($num) {
        self::$num +=$num;  // self ==Personクラス
    }
}

static

class Person {
    public static $num=30;
    public function add($num) {
        echo static::$num;         // staticはオブジェクト.子インスタンスになるかも
    }
}

final

final 定義したクラスを継承できない。
final定義したメソッドをオーバーライドできない。

class Person {
    public final function test() {
        echo “Person”;
    }
}
class Student extends Persion {
    public function test() {            // オーバーライドできない
      echo “Student”;
    }
}

abstract

①メソッドを定義し、実行内容を定義しない。
②クラスをインスタンスできない。

abstract class Person {
    public abstract function test() {}
}
class Student extends Persion {
    public function test() {        // 親クラスのabstractを定義しないとエラー
      echo “Student”;
    }
}

クラス定数(const)

class Person {
    //public const AGE=0; //7.1以降
    const AGE=0;  //7.1以前
}

echo Person::AGE;

interface

interface IPerson {
    function test1() {}; //デフォルト値public
    function test1() {}; //デフォルト値public

}

class Student implements IPerson {
    public function test1() {
    }
    public function test2() {
    }
}
// 複数
interface Inter1{
    function func1();
}

interface Inter2{
    function func1();
}

class Student implements Inter1,Inter2 {
    public function func1() {
    }
}

無名クラス(7.0以降)

$stu= new class {
    private $name;
    private $age;
     public function __construct($name, $age) {
          $this->name=$name;
          $this->age=$age;
     }

無名関数(7.0以降)

無名関数->call(オブジェクト);
$fun=function(){
    echo “func”;
}
class Student{
}

$stu=new Student();
$fun->call($stu);

異常処理

try {
  //処理内容
  // 異常
  throw new Exception(‘msg’,’code’);
} catch(Exception $ex) {
      // エラーのとき、実行する
} finally {
     // 最後に実行する
}
# カスタマイズ異常
class AException extends Exception{
}

クラスのオートローディング

手動で

ファイル: Good.class.php

<?
class Good{
}

ファイル:Book.class.php

<?
class Book extends Good {
}

ファイル:demo.php
<?
require “./Good.class.php”;
requre “./Book.class.php”;

$book=new Book();

(__autoload)_PHP7.2以前

ファイル:demo.php
<?
function __autoload($class){
    require “./{$class}.class.php”;
}

$book=new Book();

spl_autoload_register()PHP5.1以降

方法1

ファイル:demo.php
<?
function loadClass($class){
    require “./{$class}.class.php”;
}
spl_autoload_register(‘loadClass’);

$book=new Book();

方法2

ファイル:demo.php
<?
spl_autoload_register(function($class_name){
    require “./{$class_name}.class.php”;
});

$book=new Book();

方法3

ファイル:demo.php
<?
function loadClass($class){
    $arr=array(
         ‘Good’ => ‘./good/Good.class.php’,
         ‘Book’ => ‘./book/Book.class.php’,
    );
    if (isset($arr[$class]))
        require $arr[$class];
    else

        require “./{$class}.class.php”;
}
spl_autoload_register(‘loadClass’);

$book=new Book();

clone

class Person {
    public final function test() {
        echo “Person”;
    }
    // closeを実行するとき、__clone()を実行される
    public function __clone() {
        echo ‘__clone()’;
    }
}

$stu=new Person();
$stu2=clone $stu;

デザインパターン

Singleton

class DB {
    private $instance;
    private function __construct() {}
    private function __clone() {}

    public static function getInstance() {
        if (!self::$instance instanceof self)
            self::$instance=new self();
        return self::$instance;
    }
}

Factory

class A{}
class B{}

class ProductsFactory {
   public function createProduct($num) {
       switch($num) {
           case 1:
                 return new A();
           case 2:
                 return new B();
           default:
                 return null;
       }
   }
}

$factory=new ProductsFactory();
$obj1=factory.createProduct(1);
$obj2=factory.createProduct(2);

Strategy

class A {
    public function getData() {
        echo ‘A getData’;
    }
}

class B {
    public function getData() {
        echo ‘B getData’;
    }
}

class SampleStrategy {
    public function getData($obj) {
        $obj->getData();
    }
}

$sap=new SampleStrategy();
$sap->getData(new B());

シリアライズとデシリアライズ

シリアライズ

$arr=[‘test1′,’test2′,’test3’];
$str=serialize($arr);
file_put_contents(‘./arr.txt’,$str);

デシリアライズ

$str=file_get_contents(‘./arr.txt’);
$arr=unserialize($str);
print_r($arr)

マジックメソッド

__tostring()と__invoke()

class Student{
     public function __tostring(){
          return ‘__tostring()’;
     }
     public function __invoke(){
           return ‘__invoke()’;
    }
}

$stu=new Student();
echo $stu;   // __tostring()出力
$stu();         // __invoke()出力

__set($k,$v)と__get($k)、__isset($k)と__unset($k)

class Student {
     private $name;
     private $age;
     public function __set($k, $v){
          $this->$k=$v;
     }
     public function __get($k){
           return $this-$k;
    }
     public function __isset($k){
           return isset($this->$k;
    }
     public function __unset($k){
           return unset($this->$k;
    }
}

$stu=new Student();
$stu->name=’test’;       // __set($k,$v)を実行される
echo $stu->name;        // __get($k)を実行される
echo isset($stu->age);   // __isset($k)を実行される
unset($stu->age);         // __unset($k)を実行される

__call()、__callstatic

class Student {
     public function __call($name, $args){
           echo ‘存在しないメソッド’.$name;
    }
    public function __callstatic($name, $args){
           echo ‘存在しないstaticメソッド’.$name;
    }
}
$stu=new Student();
$stu->play();   // __call()が実行される
Student::play(); //__callstaticが実行される

__sleep()、__wakeup()

class Student {
     private $name;
     private $age;

     // シリアライズのとき、実行される
     public function __sleep(){
           return array(‘name’,’age’);
    }
     // デシリアライズのとき、実行される
     public function __wakeup(){
          $this->address=’test’;
    }
}

オブジェクトループ

class Student{
    public $name=’test1′;
    protected $age=29;
    private $address=’TOKYO’;
    public function show(){
      foreach($this as $k=>$v) {
        echo $k.”-“.$v;
      }
    }
}
$stu=new Student;
foreach($stu as $k=>$v) {       //name-test1
    echo $k.”-“.$v;
}
$stu->show();  //name-test1age-29address-TOKYO

名前空間

名前空間を定義するには、namespaceキーワードの後に任意の空間名を記述します。
\ で区切ってサブ名前空間を記述できます。

名前空間の記述

namespace app\content;
function play() {
    echo ‘A play’.”\n”;
}
namespace app;
function play() {
    echo ‘B play’.”\n”;
}
// 非修飾形式
play(); // B play
// 修飾形式
content\play(); //A play
// 完全修飾形式
\app\content\play(); //A play

useキーワード

use 名前空間の全てまたは一部 as 別名;

namespace app\content;
function play() {
    echo ‘A play’.”\n”;
}
namespace demo;
function play() {
    echo ‘B play’.”\n”;
}

use app\content;
play(); // B play
content\paly(); //A play   「use app\content;」がない場合、エラー

クラスをインポート

use 完全修飾形式のクラス名;

関数をインポート

use function 完全修飾形式の関数名;

定数をインポート

use const 完全修飾形式の定数名;

トレイト(trait)

trait使用

trait A {
    public function play() {
         echo ‘A play’;
    }
}

class Emp {
    use A;
}

$emp=new Emp;
$emp->play();  // A play

重複宣言による衝突

trait A {
    public function play() {
         echo ‘A play’;
    }
}
trait B {
    public function play() {
        echo ‘B play’;
    }
}
class Emp {
    use A,B {
        //方法1(Bの代わりにAを使う)
        A::play insteadof B;
       // Bのメソッドを利用したい場合
       B::play as playB;
    }
}

$emp=new Emp;
$emp->play();  // A play
$emp->playB();  // B play

アクセス権限変更

trait A {
    private function play() {
         echo ‘A play’;
    }
}

class Emp {
    use A {
        play as public playNew;  // メッソドのアクセス権限とメソッド名を変更する        
    }
}

$emp=new Emp;
$emp->playNew();  // A play

foreach可能なオブジェクトを作る

Iterator

Iteratorを利用するとき、以下の五つメソッドを実装しなければならない。

interface Iterator extends Traversable {
    function current();
    function key();
    function next();
    function rewind();
    function valid();
}
 
class Student implements Iterator {
    private $score_list=array();
    
    public function addScore($score) {
        $this->score_list[]=$score;
    }
    public function rewind() {
        reset($this->score_list);
    }
    public function valid(){
        return key($this->score_list) !==null;
    }
    public function current() {
        return current($this->score_list);
    }
    public function key() {
        return key($this->score_list);
    }
    public function next() {
        return next($this->score_list);
    }
}
 
$stu=new Student;
$stu->addScore(29);
$stu->addScore(10);
$stu->addScore(23);
$stu->addScore(33);

foreach($stu as $k=>$v) {
    echo “{$k}-{$v}”;

IteratorAggregate

interface IteratorAggregate extends Traversable {
    function getIterator();
}
class Student implements IteratorAggregate {
    private $score_list=array();
    
    public function addScore($score) {
        $this->score_list[]=$score;
    }
    // 方法1
public function getIterator() {
        return new ArrayIterator($this->score_list);

    }
    // 方法2
    public function getIterator() {
         foreach ($this->score_list as $key => $val) {
            yield $key => $val;
        }

    } 
}
 
$stu=new Student;
$stu->addScore(29);
$stu->addScore(10);
$stu->addScore(23);
$stu->addScore(33);

foreach($stu as $k=>$v) {
    echo “{$k}-{$v}”;
タイトルとURLをコピーしました