如何从Codeigniter中的联接查询中获取多个自定义对象?

时间:2017-05-12 13:59:54

标签: php codeigniter join codeigniter-2

我最近了解到,在Codeigniter中,从查询中获取结果时,使用result()row()可以添加字符串参数以将结果转换为自定义对象。

所以,我有这两个表:

Books
id
title
author_id

Authors
id
name

这个查询:

$this->db->select('b.id, b.title, a.name AS author_name');
$this->db->from('books AS b');
$this->db->join('authors AS a', 'b.author_id = a.id');
$query = $this->db->get();
$books = $query->result('Book');

$books现在是一个Book对象数组(我加载了Book class),所以我可以这样做:

foreach($books as $book) {
    echo $book->title;
    echo $book->author_name;
}

当然,author_name$book的字段。对于这个非常简单的情况很好,但想象一个更复杂的情况,有更多的表,更多的类,涉及更多的字段,如果我可以直接在查询中创建一个$author对象,有一些东西会很好像这样:

foreach($books as $book) {
    echo $book->author->name;
}

我发现的一个解决方案是在Book类中有这样的东西:

class Book {

    public function author()
    {
        if (empty($this->author)) {
            $ci =& get_instance();
            $this->author = $ci->db->get_where('authors',
                ['id' => $this->author_id])->row(0, 'Author');
        }

        return $this->author;
    }
}

哪个有效,但这意味着在使用连接的原始查询之后,我将执行其他n个查询来获取作者。有更好的方法吗?

2 个答案:

答案 0 :(得分:0)

对于任何给定的书籍,您将始终必须执行多个请求以获取不同的对象。您可以通过单个查询获得基本的,必要的信息。

在一个更复杂的情况下,例如作者,你可以在你的书中有一个字段“authorId”和“authorName”,以及一个“getAuthor”方法。
然后,您的SQL查询可以使用单个查询填充书籍对象中的作者姓名和ID,如果需要,该书可以加载复杂的作者对象。

答案 1 :(得分:0)

您的解决方案是一种不好的做法,因为您在实体中混合了大量代码。另一方面,没有任何自动方法在另一个内创建对象。要“自动”执行此操作,您必须使用ORM这样的Doctrine。

另一方面,在您的示例中,您应该将逻辑代码从Book移到模型类(SRP)到separate the concerns

一个例子可能是:

public function getBook($id)
{
    $book = $this->db->get_where('books', ['id' => $id])->row(0, 'Book');
    $boo->author = $this->db->get_where('authors', ['id' => $book->author_id])->row(0, 'Author');
}

或者,您可以使用Closure封装所有内容并推迟实例化:

public function getBook($id)
{
    $book = $this->db->get_where('books', ['id' => $id])->row(0, 'Book');
    $book->authorClosure = $this->getAuthorClosure();
}

public function getAuthorClosure(Book $book)
{
    $db = $this->db;
    return function() use ($book , $db) {
        return $db->get_where('authors', ['id' => $book->author_id])->row(0, 'Author');
    };
}

public function getAuthor()
{
    if (!isset($this->author))
    {
        $closure = $this->authorClosure;
        $this->author = $closure();
    }

    return $this->author;
}

但是使用闭包,你应该有一个方法来返回作者而不是公共变量。