草庐IT

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

coder 2023-10-24 原文

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

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() 方法中)城镇名称被用户名称覆盖时;所以我不能得到镇的名字。简单的解决方案是更改数据库和类上的属性名称;但我认为这将是一个糟糕的解决方案...... 请记住,数据库和类上的属性名称应该相同,因此查询中的 alias 是不可能的。

有什么方法可以通过 fetch_array 获取一个键为 [table.attribute] 而不是 [attribute] 的数组?
如果无法实现我想做的事情,我也想知道更好的方法。

最佳答案

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

关于php - 如何使用数组中的键 [table.attribute] mysqli_result::fetch_array?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38972482/

有关php - 如何使用数组中的键 [table.attribute] mysqli_result::fetch_array?的更多相关文章

  1. ruby - 如何使用 Nokogiri 的 xpath 和 at_xpath 方法 - 2

    我正在学习如何使用Nokogiri,根据这段代码我遇到了一些问题:require'rubygems'require'mechanize'post_agent=WWW::Mechanize.newpost_page=post_agent.get('http://www.vbulletin.org/forum/showthread.php?t=230708')puts"\nabsolutepathwithtbodygivesnil"putspost_page.parser.xpath('/html/body/div/div/div/div/div/table/tbody/tr/td/div

  2. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  3. ruby-on-rails - rails : keeping DRY with ActiveRecord models that share similar complex attributes - 2

    这似乎应该有一个直截了当的答案,但在Google上花了很多时间,所以我找不到它。这可能是缺少正确关键字的情况。在我的RoR应用程序中,我有几个模型共享一种特定类型的字符串属性,该属性具有特殊验证和其他功能。我能想到的最接近的类似示例是表示URL的字符串。这会导致模型中出现大量重复(甚至单元测试中会出现更多重复),但我不确定如何让它更DRY。我能想到几个可能的方向...按照“validates_url_format_of”插件,但这只会让验证干给这个特殊的字符串它自己的模型,但这看起来很像重溶液为这个特殊的字符串创建一个ruby​​类,但是我如何得到ActiveRecord关联这个类模型

  4. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  5. ruby-on-rails - 如何验证 update_all 是否实际在 Rails 中更新 - 2

    给定这段代码defcreate@upgrades=User.update_all(["role=?","upgraded"],:id=>params[:upgrade])redirect_toadmin_upgrades_path,:notice=>"Successfullyupgradeduser."end我如何在该操作中实际验证它们是否已保存或未重定向到适当的页面和消息? 最佳答案 在Rails3中,update_all不返回任何有意义的信息,除了已更新的记录数(这可能取决于您的DBMS是否返回该信息)。http://ar.ru

  6. ruby - 在 Ruby 中实现 `call_user_func_array` - 2

    我怎样才能完成http://php.net/manual/en/function.call-user-func-array.php在ruby中?所以我可以这样做:classAppdeffoo(a,b)putsa+benddefbarargs=[1,2]App.send(:foo,args)#doesn'tworkApp.send(:foo,args[0],args[1])#doeswork,butdoesnotscaleendend 最佳答案 尝试分解数组App.send(:foo,*args)

  7. ruby-on-rails - 'compass watch' 是如何工作的/它是如何与 rails 一起使用的 - 2

    我在我的项目目录中完成了compasscreate.和compassinitrails。几个问题:我已将我的.sass文件放在public/stylesheets中。这是放置它们的正确位置吗?当我运行compasswatch时,它不会自动编译这些.sass文件。我必须手动指定文件:compasswatchpublic/stylesheets/myfile.sass等。如何让它自动运行?文件ie.css、print.css和screen.css已放在stylesheets/compiled。如何在编译后不让它们重新出现的情况下删除它们?我自己编译的.sass文件编译成compiled/t

  8. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

    我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

  9. ruby - 如何指定 Rack 处理程序 - 2

    Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack

  10. ruby - 如何每月在 Heroku 运行一次 Scheduler 插件? - 2

    在选择我想要运行操作的频率时,唯一的选项是“每天”、“每小时”和“每10分钟”。谢谢!我想为我的Rails3.1应用程序运行调度程序。 最佳答案 这不是一个优雅的解决方案,但您可以安排它每天运行,并在实际开始工作之前检查日期是否为当月的第一天。 关于ruby-如何每月在Heroku运行一次Scheduler插件?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/8692687/

随机推荐