简体   繁体   English

PHP通过引用设置类成员

[英]PHP set class member by reference

I'm trying to build a JSON server response in php. 我正在尝试在php中建立JSON服务器响应。 As the server run through the script I use an array in my output to keep track of errors and successes in the script. 当服务器运行脚本时,我在输出中使用一个数组来跟踪脚本中的错误和成功。 Like in the code below. 就像下面的代码一样。

<?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);

And the database class looks something like this... 数据库类看起来像这样...

<?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";

        ...
    }
}

And the when I run the script the output is always something like this... 当我运行脚本时,输出始终是这样的...

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

The problem seems to be when I try to pass $output by reference to the singleton instance of the database class or in the call to json_encode(). 问题似乎是当我尝试通过引用数据库类的单例实例或调用json_encode()传递$ output时。 I have looked all over and this is the only way to pass by reference, but the funny thing is if there is an error in the database JSON.parse() in the javascript throws the error, and the output isn't a php error log. 我到处都看过了,这是通过引用传递的唯一方法,但是有趣的是,如果javascript中的数据库JSON.parse()中有错误,则会引发错误,并且输出不是php错误登录。 Anyway, know a way around this by passing the reference of $output because there are gonna be times when I expect $output to get pretty big and I want to keep the copies of the array to a minimum and I really am no good with php array functions plus if I did something like this. 无论如何,通过传递$output的引用来了解一种解决方法,因为有时我会期望$ output变得很大,并且我想将数组的副本保持在最低限度,而我对php确实不好数组函数以及我是否做过这样的事情。 $output["error"][] = $db->login(); $ output [“错误”] [] = $ db-> login(); and changed login method to return the $output_log I would end up with this. 并更改了登录方法以返回$output_log我将以此结束。

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

EDIT: The changes I made base upon your answers in case anyone needs it. 编辑:如果有人需要,我会根据您的回答进行更改。 I went on to make a response namespace with two classes that are gonna my life sooo much easier. 我继续使用两个类来创建一个响应命名空间,这使我的生活变得更加轻松。

Response.php 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);
    }
}

and the new code from before would look like this 之前的新代码看起来像这样

valid.php -> starting point 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 -> database class 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");

        ...
    }
}

Thanks for the help Wizard and Chris. 感谢向导和克里斯的帮助。 =) =)

try to set it as: 尝试将其设置为:

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

but global variables are evil :) 但是全局变量是邪恶的:)

Avoid nasty global variables and do it OOP way. 避免使用讨厌的全局变量,并以OOP方式进行操作。 Use OutputLog class as a dependency of Database class. 使用OutputLog类作为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() ] ) );

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM