我对OOP PHP
相当新,当我正在构建我的第一个项目时,我遇到了一些困难的困境。
我正在努力建立一个论坛。是的,我知道有很多免费的,我只想拥有一个我可以根据自己的需要建立的:)。此外,编码很有趣。
我为论坛,帖子和帖子构建了一个基本模型和控制器和模板。 基本模型具有标准的数据库函数,如find all,find by 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
循环来获取(尚未创建)用户类的单独实例?我认为它会耗尽更多的内存,然后是Left Join,它只是让我得到了我需要的数据。
我想知道如何解决这个问题。
答案 0 :(得分:2)
有一件事可能会打破困境;在PHP中,对象也可以act as an array(或even a function!)但普通的普通数组不能具有属性或任何其他OOP功能。
答案 1 :(得分:1)
您将无法使用您的架构解决此问题,因为您正在混合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();
但是如何为每个帖子注入正确的用户和线程?这就是Object Relational Mappers的用途:在你的情况下,所有的SQL东西都将由ORM处理,你只需处理你的对象图,而不用担心自己构建查询;你只需要定义这种关系。
流行的PHP ORM是Doctrine:here is an example about how it handles relationships declarations。
当然这种方法有缺点,但是由你来调查并找出灵活性和依赖性之间的最佳权衡。