2017-02-15 3 views
0

私はPHPでJSONサーバーレスポンスを作成しようとしています。サーバーはスクリプトを実行しているので、スクリプトのエラーと成功を追跡するために、出力に配列を使用します。以下のコードのように。PHPは参照によってクラスメンバーを設定しました

<?php 
$output = array(); 
$output["success"] = array(); 
$output["error"] = array(); 

public function foo(){ 
    global $output; 
    $db = database::getInstance(); //initialize singleton instance 
    $db->setOutput($output);  //set Output log 
    $db->login();     //log user in 

    $output["success"][] = "method end"; //debug breakpoint 
} 

echo json_encode($output, JSON_HEX_QUOT | JSON_HEX_TAG); 

とデータベースのクラス次のようになります...

<?php 
namespace db; 
class database{ 
    private var $output_log; 

    public function setOutputLog(&$output){ 
     $this->output_log = $output; 
    } 

    public function login(){ 
     ... 

     $this->output_log["error"][] = "login error"; 

     ... 
    } 
} 

そして、私は、出力は常にこのようなものであるスクリプトを実行する...

{ 
    "success" : ["method end"], 
    "error" : [] 
} 

問題は、データベースクラスのシングルトンインスタンスまたはjson_encode()の呼び出しで$出力を参照渡ししようとしたときのようです。私は全面的に見ているが、これは参照渡しの唯一の方法ですが、面白いのはデータベースにエラーがある場合ですJSON.parse()javascriptでエラーをスローし、出力はPHPエラーではありませんログ。とにかく、$outputの参照を渡すことでこれを回避する方法を知っています。なぜなら、$出力がかなり大きくなると予想される時があり、私は配列のコピーを最小限に保ちたいと思うので、PHP配列私はこのようなことをした場合、機能します。 $ output ["error"] [] = $ db-> login(); と$output_logを返すようにログイン方法を変更しました。

{ 
    "success" : ["method end"], 
    "error" : ["error":["login error"]] 
} 

編集:私は誰もがそれを必要とする場合にはあなたの答えに応じ基盤を作っ 変更。私は、私の人生がもっと楽になる2つのクラスでレスポンス名前空間を作りました。

Response.php

namespace response; 
class json_builder 
{ 
    private static $instance; 
    private $output; 

    private function __construct(){ 
     $this->output = array(); 
    } 

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

    public function addLine($tag, $msg){ 
     $this->output[$tag] = $msg; 
    } 

    public function remove($tag){ 
     unset($this->output[$tag]); 
    } 

    public function addArray($tag){ 
     $this->output[$tag] = array(); 
    } 

    public function addArrayLine($tag, $msg){ 
     array_push($this->output[$tag], $msg); 
    } 

    public function export($filter){ 
     echo json_encode($this->output, $filter); 
     unset($this->output); 
    } 
} 

class xml_builder 
{ 
    private static $instance; 
    private $output; 

    private function __construct(){ 
     $this->output = "<?xml version=\"1.0\"?>"; 
    } 

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

    public function addNode($tag, $msg, $attributes){ 
     $this->output += ($attributes) ? "<"+$tag+" "+$attributes+">" : "<"+$tag+">"; 
     $this->output += $msg + "</"+$tag+">"; 
    } 

    public function startNode($tag, $msg, $attributes){ 
     $this->output += ($attributes) ? "<"+$tag+" "+$attributes+">" : "<"+$tag+">"; 
    } 

    public function endNode($tag){ 
     $this->output += "</"+$tag+">"; 
    } 

    public function addInput($msg){ 
     $this->output += $msg; 
    } 

    public function export(){ 
     echo $this->output; 
     unset($this->output); 
    } 
} 

と前から新しいコードはこの

valid.phpのようになります。 - >開始点

<?php 
require_once "response.php"; 
require_once "db.php"; 

$output = /response/json_builder::getInstance(); 
$output->addArray("success"); 
$output->addArray"error"); 

public function foo(){ 
    $output = /response/json_builder::getInstance(); 
    $db = database::getInstance(); //initialize singleton instance 
    $db->login();     //log user in 

    $output->addArrayLine("success", "method end"); //debug breakpoint 
} 

$output->export(JSON_HEX_QUOT | JSON_HEX_TAG); 

をdb.php - >データベースクラス

<?php 
namespace db; 
class database{ 
    private $xml_output; 
    private $json_output; 

    private function __construct() 
    { 
     $this->json_output = \response\json_builder::getInstance(); 
     $this->xml_output = \response\xml_builder::getInstance(); 
    } 

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

    public function login(){ 
     ... 

     $this->output->addArrayLine("error", "login error"); 

     ... 
    } 
} 

ヘルプウィザードとクリスに感謝します。 =)

答えて

0

としてそれを設定しよう:

public function setOutputLog(&$output){ 
    $this->output_log = &$output; 
} 

が、グローバル変数は:)

+0

私はちょうどそれを理解し、それは笑いましたが、私は今、私の配列の中で私の配列の値を適切にする方法を見つけることができる新しい問題があります。 '$ array [" name "] [] =" text "'は配列の最初のエントリを上書きしているようで、 'array_push($ array [" name "]、" text ")'でも同じことが起こります。だから私は 'JSON.parse()'や 'json_encode()'が原因だと思っています。 –

+0

それを解決しました。私はxmlHttpRequestで変数を間違って渡していました。 –

0

厄介なグローバル変数を避け、それをOOPの方法を行う悪です。 クラスをDatabaseクラスの依存関係として使用してください。

class OutputLog 
{ 
    protected $log = []; 

    public add($line) { 
     $this->log[] = $line; 
    } 

    public all() { 
     return $this->log; 
    } 
} 

class Database 
{ 
    protected $success; 
    protected $error; 

    public function __construct(OutputLog $success, OutputLog $error) 
    { 
     $this->success = $success; 
     $this->error = $error; 
    } 

    public function login() 
    { 
     // Code 
     $this->error->add('Login Error'); 
     $this->success->add('Login Successful'); 
    } 
} 

$error = new OutputLog(); 
$success = new OutputLog(); 

$db = new Database($success, $error); 
$db->login(); 

$success->add('Main End'); 

echo(json_encode([ $success->all(), $error->all() ])); 
+0

なぜグローバルが悪いのですか? '$ output'はユーザー入力を受け付けていないので、jsonをエンコードした後に' unset($ output) 'を使用します。私は皆が彼らを避けなければならないと言っているので、本当に興味があります。だからグローバルの適切な使用は何ですか?また、あなたが提案した方法は、私が避けようとしているものです。私は変数の参照を渡していたので、実際にはグローバルではないので、メモリに '$ output'のコピーをたくさん作成したくありません。私は例でそのコマンドを使用しました。 –

+0

オブジェクトはデフォルトで参照渡しされますが、柔軟性があります。あなたが望むなら、 'OutputLog'に' - > addSuccess() 'と' - > addError() 'メソッドを持たせることができます。そんなにクリーンなのです。 –

関連する問題