2011-12-10 11 views
2

私はPHPの状況に慣れてきました。そこで、クラスが何であるか知らずにクラスのコンストラクタにアクセスする必要があります。私は間違ったデザインの観点からこれに近づいているかもしれないので、ここに状況があります。私はDrupalで作業しています。Drupal以外のデベロッパーがプロジェクトに参加することを許可するために、クラスレスデータ処理の周りにわずかなOO層を記述しています。PHPでは、クラスのコンストラクタ関数を返すことは可能ですか?

Drupalでは、すべてのコンテンツがノードとみなされます。そこで抽象クラスNodeを作った。どのコンテンツにも特定のコンテンツタイプが必要です。オブジェクト指向ではこれは簡単です - 私はNodeを拡張するPersonクラス、Nodeを拡張するEventクラスなどを作っています。今では難しい部分があります。私のプロジェクトではこれらのノードを他のノードに "include"することができます。すなわち、ノードAがノードBを含む場合、Aが表示されると、Bからのデータが表示される。つまり、ノードAがインスタンス化されるたびにノードBもインスタンス化する必要があります。しかし... Nodeは抽象クラスです。したがって、私は生のNodeをインスタンス化できません。実装クラスのインスタンスを生成する必要があります。だから、私が知る限り、すべての拡張クラスがコンストラクタを返す実装しなければならない抽象的な静的関数を書く必要があります...または、型を決定するために何らかの方法でリフレクションを使用する必要があります。適切なクラスのコンストラクタ?

Drupalに関係なく、この問題をPHP/OOプログラミングの観点から処理する最も適切な方法は何ですか?ここで

は私のコードです:

<?php 

abstract class Node { 

    public $title, $short_summary, $full_summary, $body, $uri, $machine_type_name, $included_content; 

    public function __construct($node) { 

     ## 
     ## Set simple values 
     $this->title = $node->title; 
     $this->body = $node->body['und'][0]['safe_value']; 

     ## 
     ## Set clean uri if aliased 
     if (drupal_lookup_path('alias', 'node/'.$node->nid)) { 
      $this->uri = '/'.drupal_lookup_path('alias', 'node/'.$node->nid); 
     } else { 
      $this->uri = '/node/'.$node->nid; 
     } 

     ## 
     ## Set short summary if exists, else short form of body text 
     if(strlen($node->body['und'][0]['safe_summary'])) { 
      $this->short_summary = $node->body['und'][0]['safe_summary']; 
     } else { 
      $this->short_summary = text_summary($node->body['und'][0]['safe_value'], NULL, 100); 
     } 

     ## 
     ## Set full summary to concatenation of body 
     $this->full_summary = text_summary($node->body['und'][0]['safe_value'], NULL, 600); 

     ## 
     ## Add included content if module is enabled 
     if (module_exists('content_inclusion')) { 
      // is this possible? Is there a better design pattern available? 
      $this->included_content = Node::get_constructor(node_load($node->content_inclusion['und'][0]['value'])); 
     } 

    } 

    public static abstract function get_all_published(); 
    public static abstract function get_by_nid($nid); 
    public static abstract function get_constructor(); 
} 

?> 
+0

ライアン、[ 'static'](http://php.net/lsb)を満たします。私はあなたが良い友達になると確信しています。 – salathe

+0

私はあなたの助けに感謝しますが、私は明らかに私の上記のコードから静的キーワードのいくつかの理解を持っています。私が何かが欠落していない限り、私はこの問題がどういうふうに問題に対処しているのか分かりません。 – rybosome

+1

しかし、後半の静的バインディング*のために使用されている、同じ双子 'static'を満たしていますか? ([docs](http://php.net/lsb)) – salathe

答えて

2

あなたはこのことを意味しますか:?

class MySubClass extends Node 
{ 
    public static function get_constructor() 
    { 
     return new self(); 
    } 
} 

// ... 

$object = MySubClass::get_constructor(); 

それとも、PHP 5.3を持っている場合、あなたがreturn new static();$class = get_called_class(); return new $class();を使用する可能性があるとlate static bindingを使用することができます。など

全例:

abstract class Node 
{ 
    public $test; 

    public function __construct() 
    { 
     $this->test = 'Node'; 
    } 

    public static function get_constructor() 
    { 
     return new static(); 
    } 
} 

class MySubClass extends Node 
{ 
    public function __construct() 
    { 
     $this->test = __CLASS__ . PHP_EOL; 
    } 
} 

// ... 

$object = MySubClass::get_constructor(); 
echo $object->test; // echoes "MySubClass" 
+0

ノードは抽象クラスなので、インスタンス化することはできません。インスタンス化されるNodeを実装する未知のクラスが必要です。 – rybosome

+0

それでも動作するはずです。あなたのサブクラス名で呼び出す限り。 (例えば、 'MySubClass :: get_constructor();') –

+0

http://codepad.org/cNyMNob4 –

関連する問題