问题描述
对OOP PHP
来说我还很陌生,在构建第一个项目时,遇到了一些困难的困境.
I am fairly new to OOP PHP
and as I am building my first project, I am coming across some difficult dilemmas.
我正在尝试建立一个论坛.是的,我知道那里有很多免费的,我只想拥有一个可以根据自己的需求构建的:).另外,编码很有趣.
I'm trying to build a forum. Yes, I know there are many free ones out there, I just want to have one that I can build according to my own needs :). Plus, it's fun to code.
我已经为论坛,主题和帖子建立了基本模型,控制器和模板.基本模型具有标准的数据库功能,例如查找全部",按ID查找"等.各个模型扩展了模型类,并且对该类仅具有特定的功能.我已经这样设置了:
I have build a base model and controller and template, for the forum, thread and post.The base model has standard database functions, like find all, find by id etc. The individual models extend the model class and have only specific functions to the class.I have set it up like this:
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;
}
除了艰难的决定外,我还必须确定某些函数和变量是否为静态.我有这个难题:
And besides the decisions that were tough, that I already had to make about certain functions and variables being static or not. I have this dilemma:
基本CRUD从基本模型开始工作.很好,我可以通过从(基本)模型调用静态方法来创建,更新,删除和读取数据库,该方法为这些论坛,线程和帖子模型实例化对象.到目前为止一切顺利.
The basic CRUD works from the base model. That is fine, I can create, update, delete and read from my database through calling static methods from the (base) model, which instantiates objects for these forum, thread and post models. So far so good.
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;
}
}
?>
我转移了这些对象以在模板中显示.从一张桌子上读取时,效果很好.
I transfer these objects for displaying in my templates. When reading from one table, that works just fine.
<?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>
但是,为了显示线程中的所有帖子,我需要来自用户表的信息,例如他们的帖子数量,等级,头像等.
However, for the display of all posts in the threads, I need info from the user table, e.g. there number of their posts, rank, avatar etc.
好的,这就是事情了
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模型中设置的变量多.因此它们不会被转移显示.
I now have more fields then variables that I have setup in my Post model. So they are not transferred for displaying.
我应该使用数组来显示这些额外的字段而不是对象吗?我宁愿仍然使用对象方法进行显示,因为现在已经为此设置了.
Should I use an array for displaying these extra fields instead of object? I would rather still use the object approach for displaying, as I am now set up for that.
还是应该将这些用户字段作为变量添加到我的Post模型中?我认为这不是最整洁的方法,但是它可以工作.
Or should I maybe add these user fields as variables to my Post model? I am thinking that is not the most tidy way to do it, however it would work.
还是应该通过foreach
循环来获取(尚未创建)用户类的单独实例?我认为这将比左连接(仅向我获取所需数据)消耗更多的内存.
Or should I go through a foreach
loop to get a separate instance of a (yet to create) user class? I am thinking it would drain much more memory then the Left Join that simply gets me the data that I need.
我想要一些有关如何解决此问题的提示.
I would like some hints on how you would solve this.
推荐答案
您将无法使用自己的模式解决此问题,因为您正在混合来自Post
实体中不同实体的属性[即用户名].
You won't be able to solve this with your schema, because you are mixing properties from different entities in your Post
entity [i.e. username].
这个想法是,您只需要使代码知道实体之间的关系即可,例如:
The idea is that you just have to make your code aware of the relationship between entities, like:
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;
...
}
这样,您将可以执行以下操作:
This way you will be able to do:
$somePost -> getUser() -> getAvatar();
但是您如何为每个帖子注入正确的用户和主题?这就是 对象关系映射器 的作用:所有的SQL内容都将由ORM处理,您将只处理对象图,而不必担心自己构建查询.您只需要定义这种关系.
But how do you inject the correct user and thread to each post? That's what Object Relational Mappers are for: in you case, all the SQL stuff would be handled by the ORM, and you'll be just dealing with you object graph, with no worries about building queries on your own; you just have to define such relationships.
一个流行的PHP ORM是 Doctrine :此处是有关其如何处理关系声明的示例.
A popular PHP ORM is Doctrine: here is an example about how it handles relationships declarations.
这种方法当然有缺点,但是这取决于您调查并找出灵活性和依赖性之间的最佳权衡.
Of course this approach has downsides, but it's up to you investigating and finding out the best tradeoff between flexibility and dependencies.
这篇关于我应该创建对象还是使用数组?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!