简体   繁体   English

如何使用数据表和数据映射器? 他们有必要吗?

[英]How to use Data Tables and Data Mappers? Are they necessary?

I have had experience with frameworks before, but never really got into models much. 我之前曾经有过框架方面的经验,但是从没有真正进入模型。 I don't know if this is the case for all frameworks or just zend, but currently I am learning Zend Framework. 我不知道是所有框架还是zend都是这种情况,但是目前我正在学习Zend框架。

I have been crawling through sample applications and trying to read huge articles, but I couldn't find a short and clear answer to what confuses me. 我一直在浏览示例应用程序并尝试阅读大量文章,但是我找不到使我感到困惑的简短明了的答案。

What is the relationship between the 3 classes? 这三个类别之间有什么关系? (model, modelmapper, datatable) (模型,模型映射器,数据表)

Let's say I have a database table called users and it has 3 fields userID, userName, userPassword What would be an example code? 假设我有一个名为users的数据库表,它具有3个字段userID, userName, userPassword 。示例代码是什么?

and is it necessary to build the model part of my application in this way? 是否有必要以这种方式构建应用程序的模型部分? Would it be a bad practice if I just had functions to retrieve data from the database and return results as arrays? 如果我仅具有从数据库检索数据并以数组形式返回结果的功能,那将是不好的做法吗?

Please consider that this is a very simple application that has users,their image galleries, and messaging functionality. 请考虑这是一个非常简单的应用程序,具有用户,其图像库和消息传递功能。

Thanks in advance. 提前致谢。

For simple application and to get your feet wet in ZF start out by just using the DbTable models that tie your database table to the database adapter. 对于简单的应用程序和使您陷入ZF的困境,只需使用将数据库表绑定到数据库适配器的DbTable模型即可。 This is not best practice, buit is easy and will get you started. 这不是最佳实践,buit很简单,可以帮助您入门。

using the Zend_Tool cli the command will have this format 使用Zend_Tool cli命令将具有这种格式
zf create db-table name actual-table-name module force-overwrite , zf create db-table name actual-table-name module force-overwrite
which will translate to: 它将转换为:

zf create db-table Users users

db this will create a file named Users.php at /application/models/DbTable/ and it will look like: db这将在/application/models/DbTable/创建一个名为Users.php的文件,如下所示:

<?php

class Application_Model_DbTable_Users extends Zend_Db_Table_Abstract
{
    protected $_name = 'users'; //name of table, does not have to match name of class
}

now to use this in a controller to fetchAll is as simple as: 现在在控制器中使用它来fetchAll很简单:

<?php

class IndexController extends Zend_Controller_Action {

   public function indexAction(){
       $db = new Application_Model_DbTable_Users();//instantiate model
       $result = $db->fetchAll();//perform query, see Zend_Db_Table_Abstract for API
       $this->view->users = $result;//send to view
    } 
} 

just by making this one little class you will have access to the functionality of your chosen database adapter. 只需完成这一小类,您就可以访问所选数据库适配器的功能。 You can also build methods in the DbTable model to customize your access needs. 您还可以在DbTable模型中构建方法来自定义访问需求。

<?php

class Application_Model_DbTable_Users extends Zend_Db_Table_Abstract
{
    protected $_name = 'users'; //name of table, does not have to match name of class

    public function getUser($id) {
       $select = $this->select();//see Zend_Db_Select for info, provides more secure interface for building queries.
       $select->where('id = ?', $id);//can be chained

       $result = $this->fetchRow($select);//returns a row object, if array is needed use ->toArray()
       return $result;
    }
} 

This method would be used in a similar manner to the fetchAll() method: 该方法的使用方式与fetchAll()方法类似:

<?php

class IndexController extends Zend_Controller_Action {

   public function indexAction(){
       $id = $this->getRequest()->getParam('id');//assumes the id is set somehow and posted
       $db = new Application_Model_DbTable_Users();//instantiate model
       $result = $db->getUser($id);//perform query, see Zend_Db_Table_Abstract for API
       //$this->view->user = $result;//send to view as object
       $this->view->user = $result->toArray();//send to view as an array
    } 
} 

Hope this get you started, don't forget to read the manual 希望这可以帮助您入门,不要忘记阅读手册

In general and in contrast to many other frameworks, Zend Framework does not force you to use a specific model architecture. 通常,与许多其他框架相比,Zend Framework不会强迫您使用特定的模型架构。 So you are free to use whatever architecture suits best for your application. 因此,您可以自由使用最适合您的应用程序的体系结构。 So the usage of an object-relational mapper is only one possible approach out of many. 因此,使用对象关系映射器只是众多方法中的一种。

But to answer your specific question: The reason why a mapper is used is simply because the information stored in a relational database cannot be translated 1:1 into an object model. 但是要回答您的特定问题:使用映射器的原因仅仅是因为无法将关系数据库中存储的信息1:1转换为对象模型。 This is called the Object-relational impedance mismatch and is described in all detail on the corresponding Wikipedia article. 这称为对象关系阻抗不匹配,并在相应的Wikipedia文章中进行了详细描述。

For your example application let's consider the relation between messages and users . 对于您的示例应用程序,让我们考虑messagesusers之间的关系。 Let's assume you have two tables with the columns given in parentheses: 假设您有两个带有括号中的列的表:

users (id, username, email, password)
messages (recipient: users.id, sender: users.id, message)

Which would correspond to the "dumb" objects User and Message . 对应于“哑”对象UserMessage Now you want to load a specific message. 现在您要加载特定的消息。 The Object Message provides the methods getRecipient() and getSender() which both should return an instance of User . 对象Message提供方法getRecipient()getSender() ,它们都应返回User的实例。 But if you read a specific row in the database, it will return an array and not the object with all the references to the other objects you need. 但是,如果您读取数据库中的特定行,它将返回一个数组,而不是包含所有需要的其他对象的引用的对象。 This is exactly where the mapper comes in: It takes care that the "flat" result from the database is converted into an object and that all necessary references to other objects are made available. 这正是映射器的用武之地: 注意将数据库的“平面”结果转换为对象,并确保对其他对象的所有必要引用都可用。

Finally, another important function is to separate the persistence from the plain model. 最后,另一个重要功能是将持久性与普通模型分开。 Let's assume that one day you want to switch from a classical relational database engine to a XML storage. 假设有一天您想从经典的关系数据库引擎切换到XML存储。 You don't have to touch the business logic at all as long if your new persistence layer can provide the necessary objects. 只要新的持久层可以提供必要的对象,您就不必完全接触业务逻辑。

I'd like to confirm what I understood. 我想确认一下我的理解。

Application_Model_User and Application_Model_Message have only variables and their setter and getter methods. Application_Model_UserApplication_Model_Message仅具有变量及其setter和getter方法。 Basically they are storage models. 基本上,它们是存储模型。

Application_Model_MessageMapper has functions like getSender that may return an instance of Application_Model_User Also Mappers use db-table classes to retrieve data. Application_Model_MessageMapper具有类似于getSender函数,这些函数可能返回Application_Model_User的实例。而且,映射器使用db-table类来检索数据。

Now I can do something like this in my controller; 现在,我可以在控制器中执行类似的操作;

$id = $this->getRequest()->getParam('id'); // I received the message ID
$messageMapper = new Application_Model_MessageMapper(); 
$message = $messageMapper->getMessageByID($id); // this method uses Application_Model_DbTable_Message to fetch data, 
// then creates an object type of Application_Model_Message to set its fields and return.

$sender = $messageMapper->getSender($message);  // returns an instance of Application_Model_User after doing the necessary processes.

So Mappers talk to db-table classes, fetch data from them, and set that data into a model object to return. 因此,Mapper与db-table类进行对话,从它们中获取数据,并将该数据设置为模型对象以返回。

Have I understood this correctly so far? 到目前为止,我是否正确理解了这一点? If so, I will just start working on the project, and learn more as I go. 如果是这样,我将开始从事该项目,并从中学到更多。

I still don't know how to use these db-table classes with linking tables which are needed for many to many relationships, but I think I'll figure it out eventually if I got the base. 我仍然不知道如何将这些db-table类与链接表使用,这对于多对多关系而言是必需的,但是我想如果有基础,最终我会弄清楚的。

Please indicate anything I misunderstood. 请指出我误解的任何内容。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM