バージョン選択

フォーラム

メニュー

オンライン状況

53 人のユーザが現在オンラインです。 (40 人のユーザが フォーラム を参照しています。)
登録ユーザ: 0
ゲスト: 53
もっと...

サイト内検索

質問 > その他 > 共通クラス内で「フロント機能」 or 「管理機能」の判定

その他

新規スレッドを追加する

スレッド表示 | 新しいものから 前のトピック | 次のトピック | 下へ
投稿者 スレッド
seasoft
投稿日時: 2009/5/2 11:08
対応状況: −−−
登録日: 2008/6/4
居住地:
投稿: 7367
Re: 共通クラス内で「フロント機能」 or 「管理機能」の判定
nanasess 様

> Helper の中身は, できるだけシンプルにし, エラー制御を分岐したい場合はエラー処理用のコールバック関数(or クラス)を用意して, Page クラス側で処理した方が良いです.

なるほど。
既存のソース中で「エラー処理用のコールバック関数(or クラス)」に関して参考になりそうな箇所はありますか? ありましたら、教えてください。
勉強してみようと思います。


> あと, 全くオフトピですが, GW 後半に, やっと EC-CUBE と戯れる時間がとれそうなので, 2.x を作った時から永らく考え中だった, 新しいプラグインの仕組みを作ろうと思っています.
>
> アクセス解析用タグの埋め込みとか, 自作のブロックなどが EC-CUBE 本体が依存することなく作れるようになるはず...

カナリ期待です。


----------------
Seasoft
こちらでの投稿は、アイディア程度に留めさせていただいております。
個別案件の作業は有償で承っております。お気軽にご相談ください。

nanasess
投稿日時: 2009/5/2 12:51
対応状況: −−−
登録日: 2006/9/9
居住地:
投稿: 2313
Re: 共通クラス内で「フロント機能」 or 「管理機能」の判定
引用:

seasoftさんは書きました:
nanasess 様

> Helper の中身は, できるだけシンプルにし, エラー制御を分岐したい場合はエラー処理用のコールバック関数(or クラス)を用意して, Page クラス側で処理した方が良いです.

なるほど。
既存のソース中で「エラー処理用のコールバック関数(or クラス)」に関して参考になりそうな箇所はありますか? ありましたら、教えてください。
勉強してみようと思います。


残念ながら, EC-CUBE はエラーハンドリングが貧弱なので, そういった処理をしている箇所は無さそうです...

1. Pear::Error のような, エラー処理用のクラスを用意
2. Helper クラスのメンバーにするか, Helper の関数に参照渡しする
3. エラーが発生した場合の処理は, Error クラスに記述

と, しておいて, 各 Page クラスで固有のエラー処理をしたければ, Error クラスの関数をオーバーライドしてやれば良いと思います.

Helper のエラー処理を Error クラスに移譲し, Page クラス側でオーバーライドして実装するイメージ(Proxy パターン)です.

説明がわかりにくくてスミマセン.
時間ができたら, どこかで作ってみようと思います.
seasoft
投稿日時: 2009/5/2 15:47
対応状況: −−−
登録日: 2008/6/4
居住地:
投稿: 7367
Re: 共通クラス内で「フロント機能」 or 「管理機能」の判定
詳細な説明ありがとうございます。

なかなか、規模が大きな話になってしまうのですね。しかし、現状の EC-CUBE でエラー処理が不十分というのは常々感じますので、解決していきたい課題ですね。


----------------
Seasoft
こちらでの投稿は、アイディア程度に留めさせていただいております。
個別案件の作業は有償で承っております。お気軽にご相談ください。

ramrun
投稿日時: 2009/5/4 1:09
対応状況: −−−
仙人
登録日: 2006/11/3
居住地:
投稿: 789
Re: 共通クラス内で「フロント機能」 or 「管理機能」の判定
ヌシが釣れてましたw

私は大したことできませんがそれなりに古株?なので、「かくあるべき」みたいな形があるのは理解しているつもりなんですが...
具体的にどうこういえ...ないんですよね(汗)。
考えた人に出てきてもらえて、ほっとしているところですw

で、なにも考えないのもアレなので、set_error_handlerを使って考えてみました。
SingletonのErrorHandlerにエラーを放り込んでおいて、LC_Pageで表示する... みたいなサンプル?のつもりです(汗)。

<?php
class ErrorHandler {
  var $list = array();
  
  function &getInstance() {
    static $eh;
    if($eh == null) {
      $eh = new ErrorHandler();
    }
    return $eh;
  }
  
  function set($errno, $errstr, $errfile, $errline)
  {
    switch($errno) {
    case E_USER_ERROR :
      $this->list[] = "User error: [$errno] $errstr in $errfile on line $errline";
      break;
    default :
      echo "Other error: [$errno] $errstr in $errfile on line $errline <br />\n";
    }
  }
  
  function get() {
    return array_pop($this->list);
  }
  
  function isError() {
    return !empty($this->list);
  }
}

/* ================================================= */

class Helper_Mail {
  function sendOrder() {
    $obj = new Send_Mail_Ex;
    $obj->sendMail();
    $var = $var; // error line 39
  }
}

class Send_Mail_Ex extends Send_Mail{
  function Send_Mail_Ex() {
    parent::Send_Mail();
  }
}

class Send_Mail {
  function Send_Mail() {}
  function sendMail() {
    $err = true;
    if($err) trigger_error('class Send_Mail の method sendMail() で error', E_USER_ERROR); // error line 53
  }
}

/* ================================================= */

$objErr1 =& ErrorHandler::getInstance();
if(version_compare(phpversion(), '5.0.0', '>=')) {
  set_error_handler(array($objErr1, 'set'), E_ALL);
} else {
  set_error_handler(array($objErr1, 'set'));
}

trigger_error("とりあえずエラー", E_USER_ERROR); // error line 66

$c = new Helper_Mail;
$c->sendOrder();

$buf = 1 / 0; // error line 71

$objErr2 =& ErrorHandler::getInstance();
print "<pre>";
print_r($objErr2->list);
print "</pre>\n";

$objErr3 =& ErrorHandler::getInstance();
while(1) {
  if(!$objErr3->isError()) {
    echo 'エラーリストは空です';
    break;
  }
  echo $objErr3->get() . "<br />\n";
}

?>
seasoft
投稿日時: 2009/5/6 12:09
対応状況: −−−
登録日: 2008/6/4
居住地:
投稿: 7367
Re: 共通クラス内で「フロント機能」 or 「管理機能」の判定
ramrun 様

非常に有用なサンプルをありがとうございます。とても良い感じです。

これでしたら、共通クラス内でのエラーを、フロント機能・管理機能のテンプレートを生かしたエラー表示ができそうです。

try/catch と異なり、特定のエラーが特定の Page クラスで発生した場合に、固有の処理を行いたいといったケースが少々難しそうですね。

以前にリターンコードで実装した SC_Helper_Mail#sfSendOrderMail を trigger_error/set_error_handler で実装するとどうなるかといった辺りを試してみようかと思います。


----------------
Seasoft
こちらでの投稿は、アイディア程度に留めさせていただいております。
個別案件の作業は有償で承っております。お気軽にご相談ください。

ramrun
投稿日時: 2009/5/7 0:54
対応状況: −−−
仙人
登録日: 2006/11/3
居住地:
投稿: 789
Re: 共通クラス内で「フロント機能」 or 「管理機能」の判定
引用:
try/catch と異なり、特定のエラーが特定の Page クラスで発生した場合に、固有の処理を行いたいといったケースが少々難しそうですね。

require_base.phpあたりでset_error_handlerして、LC_Pageでそれまでに捕まえたエラーをウンヌンするという考えでした。

単にエラーになりそうな箇所をset_error_handlerとrestre_error_handlerでサンドイッチして、その間のエラーだけ収集したほうがいいかな。

<?php
/* ▼▼  ErrorHandler  ▼▼ */
class ErrorHandler {
  var $list = array();
  
  function ErrorHandler($name = '') {
    static $err_stock = array();
    
    $this->name = $name;
    $this->list =& $err_stock;
    $this->pos = count($this->list);
    
    if(version_compare(phpversion(), '5.0.0', '>=')) {
      set_error_handler(array(&$this, 'set'), E_ALL);
    } else {
      set_error_handler(array(&$this, 'set'));
    }
    echo "▼ $this->name エラーハンドラをセットしました\n";
    register_shutdown_function(array(&$this, 'destroy'));
  }
  
  function set($errno, $errstr, $errfile, $errline) {
    for($i = 0; $i < ($this->pos + 1); $i++) {
      $this->list[$i][] = "[$errno] $errstr $errfile $errline";
    }
  }
  
  function get() {
    $message = '';
    while(count($this->list[$this->pos])) {
      $message .= $this->name . array_pop($this->list[$this->pos]) . "\n";
    }
    return $message;
  }
  
  function isError() {
    return !empty($this->list[$this->pos]);
  }
  
  function reset() {
    restore_error_handler();
    unset($this->list[$this->pos]);
    echo "▲ $this->name エラーハンドラを破棄しました\n";
  }
  
  function destroy() {
    unset($this->list);
    restore_error_handler();
  }
}

/* ▼▼  Mail  ▼▼ */

class Helper_Mail {
  function sendOrder() {
    $objMail = new Send_Mail_Ex;
    
    $objErr = new ErrorHandler('['.get_class($this).']');  // ▼▼ set_error_handler    ▼▼
      $objMail->sendMail();
    if($objErr->isError()) {
      echo "エラー処理\n";
    }
    $objErr->reset();                                      // ▲▲ restre_error_handler ▲▲
  }
}

class Send_Mail_Ex extends Send_Mail{
  function Send_Mail_Ex() {
    parent::Send_Mail();
  }
}

class Send_Mail {
  function Send_Mail() {
    $buf = 1 / 0; // error
  }
  
  function sendMail() {
    trigger_error('Send_Mail の sendMail() でエラー'); // error
  }
}

/* ▼▼  LC_Page_hoge  ▼▼ */

trigger_error('set_error_handlerする前にtrigger_error');

echo "<pre>";

$obj = new ErrorHandler('[LC_Page_hoge1]');  // ▼▼ set_error_handler    ▼▼
  trigger_error('LC_Page_hoge の process() でエラー'); // error
  $c = new Helper_Mail;
  $c->sendOrder();
echo $obj->get();
$obj->reset();                               // ▲▲ restre_error_handler ▲▲

$obj = new ErrorHandler('[LC_Page_hoge2]');  // ▼▼ set_error_handler    ▼▼
  $objMail = new Send_Mail_Ex(); // error
echo $obj->get();
$obj->reset();                               // ▲▲ restre_error_handler ▲▲

echo "</pre>";

?>
追記:入れ子にしたときに使えなさそな動きをしていたので修正(汗)
seasoft
投稿日時: 2009/5/7 20:08
対応状況: −−−
登録日: 2008/6/4
居住地:
投稿: 7367
Re: 共通クラス内での「フロント機能」 or 「管理機能」判定
> require_base.phpあたりでset_error_handlerして、LC_Pageでそれまでに捕まえたエラーをウンヌンするという考えでした。

その範囲に留めるのが良いような感じもしますね。それだけでも、ある程度のエラー(例外系)には対応できそうです。

現状ではテンプレートで JavaScript で Alert している、正常系(完了など)のメッセージあたりも統合できたら良いですね。


> 単にエラーになりそうな箇所をset_error_handlerとrestre_error_handlerでサンドイッチして、その間のエラーだけ収集したほうがいいかな。

私のスキルではこの辺りまで、自前のエラー制御でカバーするのは難しそうです。特にデバッグを困難にしてしまいそうで・・・

EC-CUBE が PHP 4 サポートを放棄して、try/catch を使える日を待とうかと思います。


----------------
Seasoft
こちらでの投稿は、アイディア程度に留めさせていただいております。
個別案件の作業は有償で承っております。お気軽にご相談ください。

nanasess
投稿日時: 2009/5/8 22:47
対応状況: −−−
登録日: 2006/9/9
居住地:
投稿: 2313
Re: 共通クラス内での「フロント機能」 or 「管理機能」判定
レス遅くなりまして, 大変申し訳ないです.

コンパイル待ち状態だったので, ざくっと書いてみました.
大変申し訳ございませんが, 現在動作させる環境が無いので, このままでは動かないかもしれません...
後日ちゃんとテストしますので, イメージだけでもお伝えできたらと思います.

僕的には, PHP の error_handler も try/catch も使いにくくて嫌いなので, 結果セットや, エラーの内容を保持するクラスを作ってみました.

できるだけ, 既存の処理に影響無く, 必要な関数のみに処理を加えることができるはず...


<?php

/**
 * 結果を返すための共通クラス.
 */
class LC_Results {

      /** エラーが存在するかどうか */
      var $has_error = false;

      var $errors = array();
      var $results = array();
   
      /**
       * エラーを追加する.
       *
       * エラーを追加した際, $this->has_error は true に設定され,
       * errorListener() 関数でエラーが処理された後, $this->errors
       * に格納される.
       *
       * @param mixed $error エラーの内容
       * @return void
       */
      function addError($error) {
          $this->has_error = true;
          $this->errorListener($error);
	  $this->errors[] = $error;
      }

      /**
       * 正常結果を追加する.
       *
       * @param mixed $result 正常に処理された場合の結果
       * @return void
       */
      function addResult($result) {
          $this->results[] = $result;
      }

      /**
       * 固有のエラー処理をするためのリスナー.
       *
       * @param mixed $error エラーの内容
       * @return void
       */
      function errorListener(&$error) {
      }
}

class Helper_Mail {

  /**
   * @param LC_Results $result 結果クラス
   */
  function sendOrder(&$result = "") {
    $objMail = new Send_Mail_Ex;
    
    $objMail->sendMail($result);
  }
}

class Send_Mail {
  
    function sendMail(&$result) {
        // some logic...
        if ($logic_is_error) {
            $result->addError($error);
        } else {
            $result->addResult($result);
        }
    }
}

class Send_Mail_Result extends LC_Results {

    function errorListener(&$error) {
         $error = "is sendMail Error!";
    }
}

class LC_Page_Hoge extends LC_Page {

    function process() {
        $c = new Helper_Mail;
        $result = new Send_Mail_Result_Hoge();
        $c->sendOrder($result);
        if ($result->has_error) {
            foreach($result->errors as $error) {
                echo $error;
            }
        } else {
           foreach($result->results as $result) {
               echo $result;
           }
        }
    }
}

/**
 * Page クラス固有のエラー処理
 */
class Send_Mail_Result_Hoge extends Send_Mail_Result {

    function errorListener(&$error) {
         $error = "is sendMail Hoge Error!";
    }
}
?>


まず, 結果を保持するための基底クラスである LC_Results クラスを用意し, その中で正常な結果やエラー結果を保持するようにします.
また, エラーの内容をカスタマイズするための Listener 関数を用意しておきます.

各 Helper クラスや, 各 Page クラスで固有のエラー処理をしたい場合は, LC_Results を継承したインナークラスを作って, errorListener() 関数をオーバーライドさせてやれば OK です.

はずしていたりして, 使えなかったらゴメンナサイ...
ramrun
投稿日時: 2009/5/9 9:35
対応状況: −−−
仙人
登録日: 2006/11/3
居住地:
投稿: 789
Re: 共通クラス内での「フロント機能」 or 「管理機能」判定
動作確認しました。
Helper_Mailがnot foundになるから「なんだよコノヤロー」とか思いましたが、その上のリスナーに対するコメント行が閉じてなかったのが原因でしたw

こういうデザインパターン?の類は知らない(自分のレベル的に)ので非常に参考になります。
errorListenerがオーバーライドされていくのはカッコイイですね。

引用:
はずしていたりして, 使えなかったらゴメンナサイ...
多分はずしていないと思います。

ところでひとつ気になったんですが、
$result = new Send_Mail_Result_Hoge();

の$resultが参照で渡されていきますが、たとえば
class Helper_Mail {

  /**
   * @param LC_Results $result 結果クラス
   */
  function sendOrder(&$result = "") {
    $objMail = new Send_Mail;
    
    $objMail->sendMail($result);
    if ($result->has_error) {
      // some logic...
    }
  }
}

はいいとして、
class Helper_Mail {

  /**
   * @param LC_Results $result 結果クラス
   */
  function sendOrder(&$result = "") {
    $objMail = new Send_Mail;
    
    $result = new Send_Mail_Result;
    $objMail->sendMail($result);
    if ($result->has_error) {
      // some logic...
    }
  }
}

みたいなのはおかしいですよね?
変なことを聞いてるようでしたらごめんなさい(汗)。
nanasess
投稿日時: 2009/5/9 10:02
対応状況: −−−
登録日: 2006/9/9
居住地:
投稿: 2313
Re: 共通クラス内での「フロント機能」 or 「管理機能」判定
ramrun さん,

引用:

ramrunさんは書きました:
動作確認しました。
Helper_Mailがnot foundになるから「なんだよコノヤロー」とか思いましたが、その上のリスナーに対するコメント行が閉じてなかったのが原因でしたw


ありがとうございます.
全く動かしてなかったのがバレバレですね(汗)
修正しておきました.

引用:

こういうデザインパターン?の類は知らない(自分のレベル的に)ので非常に参考になります。
errorListenerがオーバーライドされていくのはカッコイイですね。

引用:
はずしていたりして, 使えなかったらゴメンナサイ...
多分はずしていないと思います。


良かったです!

引用:

ところでひとつ気になったんですが、
$result = new Send_Mail_Result_Hoge();

の$resultが参照で渡されていきますが、たとえば
class Helper_Mail {

  /**
   * @param LC_Results $result 結果クラス
   */
  function sendOrder(&$result = "") {
    $objMail = new Send_Mail;
    
    $objMail->sendMail($result);
    if ($result->has_error) {
      // some logic...
    }
  }
}

はいいとして、
class Helper_Mail {

  /**
   * @param LC_Results $result 結果クラス
   */
  function sendOrder(&$result = "") {
    $objMail = new Send_Mail;
    
    $result = new Send_Mail_Result;
    $objMail->sendMail($result);
    if ($result->has_error) {
      // some logic...
    }
  }
}

みたいなのはおかしいですよね?
変なことを聞いてるようでしたらごめんなさい(汗)。



後者の例だと, sendOrder() 関数を使おうとしている人が $result を渡しても, 内部で上書きされてしまい, 想定通りの挙動にならないと思います.

今回は, できるだけ既存の関数の挙動を変えないことを念頭にしたので引数の参照渡しにしていますが, 本来なら「結果」を返すためのクラスなので関数の返り値にしてしまった方がわかりやすそうです.

phpDoc コメントも


@return LC_Results ○○処理の結果.


と書けてコードの見通しも良くなりそうです.

とり急ぎですが動作確認のお礼まで.
ありがとうございました!
« 1 2 (3) 4 »
スレッド表示 | 新しいものから 前のトピック | 次のトピック | トップ


 



ログイン


EC-CUBE公式 Amazon Payプラグイン

統計情報

総メンバー数は88,707名です
総投稿数は109,948件です

投稿数ランキング

1
seasoft
7367
2
468
3217
3
AMUAMU
2712
4
nanasess
2313
5
umebius
2085
6
yuh
1819
7
h_tanaka
1638
8
red
1570
9
mcontact
1285
10
tsuji
958
11
fukap
907
12
shutta
835
13
tao_s
799
14 ramrun 789
15 karin 689
16 sumida 641
17
homan
633
18 DELIGHT 572
19
patapata
502
20
flealog
485


ネットショップの壺

EC-CUBEインテグレートパートナー

Copyright© EC-CUBE CO.,LTD. All Rights Reserved.