2017-11-17 9 views
6

を避けるために、SimpleXMLはを拡張または実装が..私はいくつかのXMLフレームを構築するために作成しました、以下のクラスを確認してくださいDRY

class CommandBuilder 
{ 
    public function __construct() 
    { 
     // 
    } 

    public function login($username, $password) 
    { 
     $frame = $this->frame(); 

     $command = $frame->addChild('command'); 
     $login = $command->addChild('login'); 
     $login->addChild('username', $username); 
     $login->addChild('password', $password); 
     $command->addChild('authKey', 'authkey'); 

     return $frame->asXML(); 
    } 

    public function info($id) 
    { 
     $frame = $this->frame(); 

     $command = $frame->addChild('command'); 
     $login = $command->addChild('product'); 
     $login->addChild('id', $id); 
     $command->addChild('authKey', 'authkey'); 

     return $frame->asXML(); 
    } 

    protected function frame() 
    { 
     return new SimpleXMLElement(
      '<app/>' 
     ); 
    } 
} 

要素の変更命令なし$frame->addChild('command')$command->addChild('authKey', 'authkey')の重複を回避する最善の方法は何ですか?

コードを改善するのに手伝ってください。ありがとう

答えて

0

あなたが持っているコードは単純化することができますが、合併症があります。私がそれをした方法は、フレームの建物をframeメソッドに移動します。他の各ルーチンは<command>ノードの基礎を構築し、これを渡すと、フレームメソッドはauthkeyビットを追加します。あなたの依存関係があまりにも混同されていないので、これはあなたがこれを移動させることができ、非常に簡単一例であるように

class CommandBuilder 
{ 
    public function __construct() 
    { 
     // 
    } 

    public function login($username, $password) 
    { 
     $command = new SimpleXMLElement('<command />'); 
     $login = $command->addChild('login'); 
     $login->addChild('username', $username); 
     $login->addChild('password', $password); 

     return $this->frame($command); 
    } 

    public function info($id) 
    { 
     $command = new SimpleXMLElement('<command />'); 
     $login = $command->addChild('product'); 
     $login->addChild('id', $id); 

     return $this->frame($command); 
    } 

    protected function frame($node) { 
     $node->addChild('authKey', 'authkey'); 
     $xml = new DOMDocument(); 
     $xml->loadXML('<app/>'); 
     // Convert SimpleXML to DOMDocument 
     $fromDom = dom_import_simplexml($node); 
     // Add in the $node passed in to the frame 
     $xml->documentElement->appendChild($xml->importNode($fromDom, true)); 

     return $xml->saveXML(); 
    } 
} 
0

に見えます...しかし、それはすべてのフレーム上で行わなければならない - このコードは、同じことをするだろう独自の方法に変換する。 PHPでは、オブジェクトは参照渡しされることに注意してください。つまり、オブジェクト変数は実際にオブジェクトへのメモリポインタであり、スカラー変数と配列変数がデフォルトで渡されるのとは対照的です(値によっては別名メモリポインタなし)。

テイクアウェイは、cloneがない限り、オブジェクトがどこで使用されていても常に同じであるということです。

<?php 
class CommandBuilder 
{ 
    public function preBuild(\SimpleXMLElement $node) 
    { 
     $command = $node->addChild('command'); 
     $command->addChild('authKey', 'authkey'); 
    } 
} 

さて、代わりにこれらの2つのメソッドを呼び出すので、あなたは単に$this->preBuild($frame)を呼び出すことができます。

2

どのように別のビルダークラス作成するには、このような何か、について:

class CommandBuilder 
{ 
    private $commandName; 

    private $params = []; 

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

    // convenience method, to allow for cleaner fluent interface usage 
    public static function create($commandName) { 
    return new self($commandName); 
    } 

    public function addParam($paramName, $paramValue) { 
    $this->params[] = [ 'name' => $paramName, 'value' => $paramValue ]; 

    return $this; 
    } 

    public function build() { 
    $app = new SimpleXMLElement('<app/>'); 
    $commandContainer = $app->addChild('command'); 
    $command = $commandContainer->addChild($this->commandName); 
    foreach($this->params as $param) { 
     $command->addChild($param[ 'name' ], $param[ 'value' ]); 
    } 
    $commandContainer->addChild('authKey', 'authKey'); 

    return $app->asXML(); 
    } 
} 

をして、特定のアプリケーションのコマンド構築する別のクラスがあります。

class AppCommands 
{ 
    public function login($username, $password) { 
    return CommandBuilder::create('login')->addParam('username', $username) 
              ->addParam('password', $password) 
              ->build(); 
    } 

    public function info($id) { 
    return CommandBuilder::create('product')->addParam('id', $id) 
               ->build(); 
    } 
} 

使い方は同じままに、あなたがCommandBuilderの代わりに、AppCommandsをインスタンス化除い:

$ac = new AppCommands; 

echo $ac->login('MyUsername', 'MyPassword'); 
echo PHP_EOL; 
echo $ac->info(5); 
あなたが望んでいた場合は

View this example on eval.in

、あなたはもちろん、動的CommandBuilderからauthKeyを渡す代わりに、可能性がハードコーディングするようなもので、内部にそれを:

class CommandBuilder 
{ 
    private $commandName; 

    private $authKey; 

    private $params = []; 

    public function __construct($commandName, $authKey) { 
    $this->commandName = $commandName; 
    $this->authKey = $authKey; 
    } 

    public static function create($commandName, $authKey) { 
    return new self($commandName, $authKey); 
    } 

    /* ... */ 

    public function build() { 

    /* ... */ 

    $commandContainer->addChild('authKey', $this->authKey); 

    return $app->asXML(); 
    } 
0

方法「スケルトンの作成について"メソッドは、呼び出し可能なパラメータとして受け取り、そのように途中で実行します。 (不都合な点は、$username$passwordのようなパラメータが繰り返されることです)。

class CommandBuilder 
{ 
    // ... 

    private function createCommand(callable $cmdEnricher) 
    { 
     $frame = $this->frame(); 

     $command = $frame->addChild('command'); 
     $cmdEnricher($command); 
     $command->addChild('authKey', 'authkey'); 

     return $frame->asXML(); 
    } 

    public function login($username, $password) 
    { 
     return $this->createCommand(function ($command) use ($username, $password) { 
      $login = $command->addChild('login'); 
      $login->addChild('username', $username); 
      $login->addChild('password', $password); 
     }); 
    } 

    public function info($id) 
    { 
     return $this->createCommand(function ($command) use ($id) { 
      $login = $command->addChild('product'); 
      $login->addChild('id', $id); 
     }); 
    } 

    // ... 
} 
関連する問題