如何使用数组中的键[table.attribute] mysqli_result :: fetch_array?

时间:2016-08-16 10:27:27

标签: php mysql mysqli fetch

我正在尝试创建一个通用方法来自动从查询中实例化对象:

SELECT town.*, content.*, user.*
FROM townhub.content
LEFT JOIN town ON content.townReceiver = town.id_town
LEFT JOIN user ON content.author = user.id_user

我想要构建的方法应该将3种类型的对象:TownUserContent返回到数组中。我想过这样的事情:

protected function build_objects($result, Array $classes) {
    $data = array();
    $i = 0;
    while ($row = $result->fetch_array(MYSQLI_ASSOC)) {

        foreach ($classes as $class) {
            $$class = new $class;
            $$class = $$class->fill_object($$class, $row);
            $data[$i][$class] = $$class;


        }
        $i++;
    }
    return $data;
}

然后,在每个班级,这样的方法:

public function fill_object($object, Array $row) {
    $attributes = get_object_vars($object);
    foreach ($row as $attribute => $value) {
        foreach ($attributes as $objAtt => $emptyValue) {
            if ($attribute == $objAtt) {
                $object->$attribute = $value;
            }
        }
    }
    return $object;
}

实际上,这就是我想要的,下面的数组(使用build_objects()中的var_dump($ data)打印):

array (size=4)
  0 => 
    array (size=3)
      'Content' => 
        object(Content)[4]
          protected 'id_content' => string '1' (length=1)
          public 'title' => string 'Hello World!' (length=10)
          public 'description' => string 'Hello world description' (length=43)
          public 'category' => string '1' (length=1)
          public 'date' => string '2015-01-01' (length=10)
          public 'townReceiver' => string '1' (length=1)
          public 'author' => string '1' (length=1)
          private 'dbHost' (Model) => string 'localhost' (length=9)
          private 'dbUser' (Model) => string 'root' (length=4)
          private 'dbPass' (Model) => string 'root' (length=4)
          private 'dbName' (Model) => string 'townhub' (length=7)
          private 'conn' (Model) => null
      'Town' => 
        object(Town)[5]
          protected 'id_town' => string '1' (length=1)
          public 'name' => string 'Isaac' (length=5)
          public 'population' => string '750' (length=3)
          private 'dbHost' (Model) => string 'localhost' (length=9)
          private 'dbUser' (Model) => string 'root' (length=4)
          private 'dbPass' (Model) => string 'root' (length=4)
          private 'dbName' (Model) => string 'townhub' (length=7)
          private 'conn' (Model) => null
      'User' => 
        object(User)[6]
          protected 'id_user' => string '1' (length=1)
          protected 'dni' => string '20011225' (length=9)
          private 'password' => string '1234' (length=4)
          public 'name' => string 'Isaac' (length=5)
          public 'firstSurname' => string 'Surname1' (length=5)
          public 'secondSurname' => string 'Surname2' (length=5)
          public 'birthdate' => string '0000-00-00' (length=10)
          public 'gender' => string 'H' (length=1)
          public 'email' => string 'isaac@mail.com' (length=19)
          public 'isAdmin' => string '1' (length=1)
          public 'id_town' => string '1' (length=1)
          private 'dbHost' (Model) => string 'localhost' (length=9)
          private 'dbUser' (Model) => string 'root' (length=4)
          private 'dbPass' (Model) => string 'root' (length=4)
          private 'dbName' (Model) => string 'townhub' (length=7)
          private 'conn' (Model) => null

问题在于,当我用fech_array(在fill_object()方法中)时,城镇的名字会被用户的名字覆盖;所以我无法得到这个城镇的名字。简单的解决方案是在db和classes上更改属性的名称;但我认为这将是一个糟糕的解决方案...... 请记住,属性的名称应该在db和classes上等于,因此查询中的alias是不可能的。

有任何方法可以使用[{1}}数组使用键[table.attribute]代替[属性]吗?
如果不想做我想做的事情,我也想知道更好的方法。

1 个答案:

答案 0 :(得分:1)

 <?php

class DataCollectionHelper
{
    /**
     * $result var is the result of:
     * "SELECT *
     * FROM townhub.content".
     * 
     * As you left join your tables, it may appear that you haven't any towns and users
     * for particular content.
     *
     * @param $result
     * 
     * @return array
     */
    protected function build_objects($result)
    {
        $data = array();
        $i = 0;
        while ($row = $result->fetch_array(MYSQLI_ASSOC)) {
            $contentObject = new Content();
            $contentObject->fill_object($row);
            $data[$i]['Content'] = $contentObject;
            $data[$i]['User'] = $this->getUserByContentAuthor($contentObject->getAuthor());
            $data[$i]['Town'] = $this->getTownByContentByTownReceiver($contentObject->getTownReceiver());
            $i++;
        }

        return $data;
    }

    /**
     * @param integer $townReceiver
     *
     * @return Town
     */
    private function getTownByContentByTownReceiver($townReceiver)
    {
        /**
         * Here you have to get town data by your $townReceiver - property
         *  and return the object of Town
         */
    }

    /**
     * @param integer $author
     *
     * @return User
     */
    private function getUserByContentAuthor($author)
    {
        /**
         * The same here for users
         */
    }
}

class Content
{
    /**
     * @var integer
     */
    protected $content_id;
    /**
     * @var string
     */
    public $title;

    /**
     * @var integer
     */
    public $townReceiver;

    /**
     * @var string
     */
    public $description;

    /**
     * @var integer
     */
    public $author;
    /* other vars */

    /**
     * @param array $row
     *
     * @return $this
     */
    public function fill_object(array $row)
    {
        /*
         * It's not the best approach, to do like that.
         * It's better to use setters or just set your properties
         * $this->title = $row['title']; etc
         *
         * Still you could use $this instead of your $object variable
         */
        $attributes = get_object_vars($this);
        foreach ($row as $attribute => $value) {

            foreach ($attributes as $objAtt => $emptyValue) {
                if ($attribute == $objAtt) {
                    $this->$attribute = $value;
                }
            }
        }

        return $this;
    }

    /**
     * @return int
     */
    public function getTownReceiver()
    {
        return $this->townReceiver;
    }

    /**
     * @return int
     */
    public function getAuthor()
    {
        return $this->author;
    }
}