如何更有效地创建对象数组?

时间:2011-02-03 16:37:27

标签: php sql oop class

我正在尝试从我的页面生成时间(最多0.9秒!)中减少十分之一秒的宝贵时间!我想知道是否有更有效的方法来加载以下(示例)数据。

想象一下,你有一个描述用户的类,以及一个描述用户写的帖子的类。

要列出特定用户撰写的每篇帖子的各种属性,您可以使用以下代码:

$user = new User( $user_id );
$post_array = $user->get_posts();

User类内部将是以下代码:

function get_posts()
{
    $posts_array = array();
    $result = mysql_query( "SELECT id FROM posts WHERE author = '" . $this->id . "'" );
    while ( $row = mysql_fetch_array( $result ) )
    {
        $posts_array[] = new Post( $row['id'] );
    }
}

我不喜欢这样一个事实:我必须两次点击数据库,一次获取帖子ID,每次我实例化Post类时都会这样。我是否已将自己编入角落?有没有更有效的方法呢?

使用SELECT * FROM posts...将所有帖子的数据传递给实例化的Post对象然后使用$posts_array[] = new Post( $row );会不会是不好的做法?

4 个答案:

答案 0 :(得分:1)

我没有看到一次执行大查询(即SELECT *)然后将其传递给post对象,可能是通过特殊方法或静态构造函数(例如Post::createPostFromData())。事实上,我认为这被称为Dependency Injection,强烈建议使用它,因为设计模式会发生。

编辑:在Re - DRY

除非我完全弄错,DRY原则专门指代代码,即没有几段代码执行相同的操作,或者字面上是相同的代码行,其中0或更小变化,如果你这样做,将它们分解为函数/方法/你有什么。原因很多,但主要集中在维护和调试上 - 如果有任何需要改变,那么使用DRY只需更改一次。

在这种情况下,没有理由重复代码甚至查询,因为您只是使用预先构建的数据填充对象。但是,如果您想添加允许您按ID获取帖子然后填充对象的代码,那么通过编写代码来填充对象两次就可以完全违反DRY,即使数据来自多个来源也是如此

在这种情况下,我会主张使用纯静态构造函数,以便您可以完全控制实例化的条件,例如:

class Post {
    // object properties
    protected $post_id;
    public $post_name;
    // ...

    protected function __construct($post_id, $post_data = null) {
        if (is_null($post_data)) {
            // create $post_data object by fetching $post_id
        }
        // code to populate the object
    }

    public static function fromData($data) {
        if (!is_array($data)) {
            return false;
        }
        return new self(null, $data);
    }

    public static function fromId($post_id) {
        if (!ctype_digit((string)$post_id)) {
            return false;
        }
        return new self($post_id);
    }
}

答案 1 :(得分:1)

欢迎来到不太精彩的对象关系映射世界!

就“OO设计纯度”而言,您现在的工作方式具有直接实施的优势,并可根据需要按需加载来自数据库的相关数据块。 MySQL查询需要时间,但通过网络传输大型结果集也是如此。注意过早优化并了解可以实施的其他策略,以减少可能更有效且更容易实现的页面加载时间。您确定应用程序的这一方面对加载时间有重大影响吗?即使它是,你有没有看过PHP字节码缓存或MySQL查询缓存?

答案 2 :(得分:0)

每次要获取Post时,为什么不使用PostSet使用单个查询返回Posts,而不是运行查询?你可以使它变得懒惰,以便它只在你开始从它获取帖子时运行查询。为方便起见,请查看Zend Framework,特别是Zend_Db和Zend_Db_Table。您不必使用整个框架 - 只需要您需要的类。

http://framework.zend.com/manual/en/zend.db.table.html

答案 3 :(得分:0)

使用INNER JOIN查询怎么样?

$result = mysql_query("SELECT user_table.id, post_table.id, post_table.user_id FROM user_table INNER JOIN post_table ON post_table.user_id = user_table.id WHERE user_table.name = '".$user_name);

**注意:我没有测试过它的“WHERE”部分,但我之前使用过JOIN。这更像是一种理论,而不是一种答案。

用户选择可以建立在您希望的任何列上。

INNER JOIN示例: - http://www.w3schools.com/sql/sql_join_inner.asp