0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

PHPでObserverパターンで実装してみた

Posted at

はじめに

Rx****をやってみたくなり、基本となる(?)ObserverパターンをPHPにて実装して見た。
前提条件として、

  • PHP5.xでも動く
  • ある程度実用的

とします。

Observerパターンとは

あちこちのページで書かれているので細かくは省略します。
状態変化に応じた処理を記述するときに有効らしいです。

今回のサンプル

タイトルと内容を入力とするフォームからPOSTされた時に、

  • メール送信
  • ログ出力

を行う処理を記述するのにObserverパターンで記述してみます。
(この程度でObserverパターンを使うのもって話はあるが。。。(汗)
クラス図はこんな感じ
class.png

ソース構成はこんな感じ
┣━ classes
┃  ┣━ ifSubject.php
┃  ┣━ clsFormdat.php
┃  ┣━ ifObserver.php
┃  ┣━ clsLogObserver.php
┃  ┣━ clsSndMailObserver.php
┗━ smp1.php

実装

インターフェイス

まずSubjectのインターフェイスは

ifSubject.php
<?php
/**
 * Subjectインターフェイス
 */
interface ifSubject {
  public function addObserver($obj);      // Observerインスタンス追加
  public function removeObserver($obj);   // Observerインスタンス削除
  public function notify();               // Observerへの通知
}

次にObserverインターフェイスは

ifObserver.php
<?php
/**
 * Observerインターフェイス
 */
interface ifObserver {
  public function execute($obj);   // Subjectからの通知受信
}

Subjectクラス

clsFormdat.php
<?php
require_once(dirname(__FILE__)."/ifSubject.php");

/**
 * フォームデータクラス
 */
class clsFormdat implements ifSubject {
  private $title = ""; /// タイトル
  private $memo = "";  /// 内容

  private $arrObservers = NULL;  /// Observerインスタンス配列

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

  /**
   * タイトルと内容のセッター
   */
  public function __set($itm,$val) {
    if ( $itm == "title" ) $this->title = $val;
    if ( $itm == "memo" ) $this->memo = $val;
  }

  /**
   * タイトルと内容のゲッター
   */
  public function __get($itm) {
    if ( $itm == "title" ) return $this->title;
    if ( $itm == "memo" ) return $this->memo;
  }

  /**
   * Observerインスタンス追加
   * @param $obj Observerインスタンス
   */
  public function addObserver($obj) {
    $this->arrObservers[get_class($obj)] = $obj;
  }

  /**
   * Observerインスタンス削除
   * @param $obj Observerインスタンス
   */
  public function removeObserver($obj) {
    unset($this->arrObservers[get_class($obj)]);
  }

  /**
   * Observerへの通知
   */
  public function notify() {
    foreach($this->arrObservers as $obj) {
      $obj->execute($this);
    }
  }
}

Observerクラス

まず、ログ出力クラスは

clsLogObserver.php
<?php
require_once(dirname(__FILE__)."/ifObserver.php");

/**
 * ログ出力クラス
 */
class clsLogObserver implements ifObserver {
  public function __construct() {

  }

  /**
   * 通知受信
   * @param $obj clsFormdatのインスタンス
   */
  public function execute($obj) {
    $buf  = "title:".$obj->title;
    $buf .= "\n".$obj->memo;
    $fp = fopen("/var/www/Log/app.log","a");
    fwrite($fp,$buf);
    fclose($fp);
  }
}

次にメール送信クラス

clsSndMailObserver.php
<?php
require_once(dirname(__FILE__)."/ifObserver.php");

/**
 * メール送信クラス
 */
class clsSndMailObserver implements ifObserver {
  public function __construct() {

  }

  /**
   * 通知受信
   * @param $obj clsFormdatのインスタンス
   */
  public function execute($obj) {
    mail("tst@cde.jp",$obj->title,$obj->memo,"From: adm@cde.jp");
  }
}

動かしてみる

次のコードで実際に動かしてみる。

smp1.php
<?php
require_once(dirname(__FILE__)."/classes/clsLogObserver.php");
require_once(dirname(__FILE__)."/classes/clsSndMailObserver.php");
require_once(dirname(__FILE__)."/classes/clsFormdat.php");

$obj = new clsFormdat();

$objLog = new clsLogObserver();
$obj->addObserver($objLog);

$objMail = new clsSndMailObserver();
$obj->addObserver($objMail);

$obj->title = "サンプルタイトル";
$obj->memo  = "サンプルサンプル\nサンプル";
$obj->notify();

確かに実装はシンプルになったようだ。

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?