我应该创建一个对象还是使用一个数组


Should I create an object or work with an array?

我对OOP PHP相当陌生,当我正在构建我的第一个项目时,我遇到了一些困难的困境。

我想建立一个论坛。是的,我知道有很多免费的,我只是想有一个,我可以根据自己的需要建立:)。另外,编写代码很有趣。

我已经建立了一个基本模型和控制器和模板,为论坛,线程和帖子。基本模型具有标准的数据库功能,如查找全部、按id查找等。单个模型扩展模型类,并且只对类具有特定的功能。我已经这样设置了:

class Post_Model extends Model {
    static protected $_table_name = 'post';
    static protected $_db_fields = array('id', 'thread_id', 'parent_id', 'username', 'user_id',
        'title', 'date_line', 'pagetext', 'show_signature', 'ip_address', 'icon_id', 'visible');
    /**
     * @var db fields
     */
    public $id;
    public $thread_id;
    public $parent_id;
    public $username;
    public $user_id;
    public $title;
    public $date_line;
    public $pagetext;
    public $show_signature;
    public $ip_address;
    public $icon_id;
    public $visible;
}
/*
 * joined fields with user object. needed to display posts in all details
 */
static public function get_posts($id, $limit, $offset){
    $result_set = static::find_by_sql("
        SELECT * 
        FROM post 
        LEFT JOIN user ON (post.user_id = user.id) where post.thread_id=".(int)$id." 
        ORDER BY date_line DESC 
        LIMIT {$offset} , {$limit}");
    return !empty($result_set) ? $result_set : false;  
}

除了那些艰难的决定,我已经不得不做出关于某些函数和变量是静态的还是非静态的决定。我现在进退两难:

基本CRUD从基本模型开始工作。这很好,我可以创建,更新,删除和读取我的数据库通过调用静态方法从(基)模型,它实例化这些论坛,线程和帖子模型的对象。到目前为止一切顺利。

部分Model Class:

    <?php
        /**
     * Find rows from database based on sql statement
     * @param string $sql
     * @retun array $result_set
     */
    static public function find_by_sql($sql = '') {
        $db = Database::getInstance();
        $mysqli = $db->getConnection();
        $result = $mysqli->query($sql);
        $object_array = array();
        while ($record = $result->fetch_array()) {
            $object_array[] = static::instantiate($record);
        }
        return $object_array;
    }
    private static function instantiate($record) {
        $object = new static;
        foreach ($record as $attribute => $value) {
            if ($object->has_attritube($attribute)) {
                $object->$attribute = $value;
            }
        }
        return $object;
    }
}
?>

我转移这些对象以便在我的模板中显示。当从一个表中读取数据时,它工作得很好。

    <?php
$postcount = $pagination->offset + 1;
if (!empty($posts)) {
    foreach ($posts as $post) {
        ?>
        <div class="post">
            <div class="posttime"><?php echo strftime("%A %e %B %G  %H:%M", $post->date_line); ?></div>
            <div class="postnumber">#<?php echo $postcount; ?></div>
            <div class="postuser">
                <div class="username"><?php echo $post->username; ?></div>
                <div class="avatar">avatar</div>
            </div>
            <div class="postcontents">
                <div class="posttext"><?php echo $post->pagetext; ?></div>  
            </div>
        </div>
        <?php
        $postcount++;
    }
    ?>    
<div class="pagination"><?php echo $page_split; ?></div> 

然而,对于线程中所有帖子的显示,我需要来自用户表的信息,例如,他们的帖子数量,排名,头像等。

好的,事情是这样的:

SELECT * FROM post
LEFT JOIN user ON (post.user_id = user.id)
where thread_id={$id}
ORDER BY date_line DESC
LIMIT {$offset} , {limit}

我现在有更多的字段然后变量,我已经设置在我的Post模型。因此,它们不会被转移显示。

我应该使用数组来显示这些额外的字段而不是对象吗?我宁愿仍然使用对象方法来显示,因为我现在已经设置好了。

或者我应该将这些用户字段作为变量添加到我的Post模型中吗?我认为这不是最整洁的方法,但它会工作。

或者我应该通过foreach循环来获得(尚未创建)用户类的单独实例吗?我认为它会消耗更多的内存,然后左连接,只是让我得到我需要的数据。

我想要一些关于如何解决这个问题的提示。

有一件事可能会打破这个困境;在PHP中,一个对象也可以作为一个数组(甚至一个函数!),但一个普通的普通数组不能有属性或任何其他OOP特性。

你将无法用你的模式解决这个问题,因为你在你的Post实体[即用户名]中混合了来自不同实体的属性。

这个想法是,你只需要让你的代码意识到实体之间的关系,像:
class Post extends Entity
{
  protected $id;
  protected $body;
  protected $date;
  // this will be an instance of a Thread entity, let's say
  protected $thread;
  // this will be an instance of the User entity
  protected $user;
  ...
}

这样你就可以:

$somePost -> getUser() -> getAvatar();

但是如何为每个帖子注入正确的用户和线程呢?这就是对象关系映射器的作用:在你的情况下,所有的SQL内容都将由ORM处理,你将只处理你的对象图,而不用担心自己构建查询;你只需要定义这样的关系。

一个流行的PHP ORM是Doctrine:下面是一个关于它如何处理关系声明的例子。

当然,这种方法有缺点,但这取决于您的调查和找出灵活性和依赖性之间的最佳权衡。