在这篇博客中,我们将学习magento的模型和数据库的基本操作。
模型在MVC模式中应用于逻辑+数据操作。在magento中,它们有相同的作用。在这片博客中,我们继续使用之前博客创建的文件系统,我们将会对布局文件做一些修改。在magento中,模型由两部分,第一个是模型文件,第二个是模型的资源文件,模型用来做逻辑操作,资源用来执行实际的数据库请求。
下面添加的是模块中用来加载Model的配置文件config.xml:
< global >
< models >
< test >
< class >Magease_Test< /class >< !--所有模型类文件的位置-- >
< resourceModel >test_mysql4< /resourceModel >< !--资源模型的位置-- >
< /test >
< test_mysql4 >
< class >Magease_Test_Model_Mysql4< /class >
< entities >
< test >
< table >test_tablename< /table >
< /test >
< /entities >
< /test_mysql4 >
< /models >
< resources >< !--这是对模块的访问和数据库的读写权限进行设置-- >
< test_setup >
< setup >
< module >Magease_Test< /module >
< /setup >
< connection >
< use >core_setup< /use >
< /connection >
< /test_setup >
< test_write >
< connection >
< use >core_write< /use >
< /connection >
< /test_write >
< test_read >
< connection >
< use >core_read< /use >
< /connection >
< /test_read >
< /resources >
< /global >
下面将对上面的一些重要信息解释一下。
< entities >
< test >
< table >test_tablename< /table >
< /test >
< /entities >
这里,我们添加一个模块中我们需要用到的所有数据表的列表。
例如:
< entities >
< test >
< table >test_tablename< /table >
< /test >
< test >
< table >test_tablename2< /table >
< /test >
< test >
< table >test_tablename3< /table >
< /test >
< /entities >
正如你看到的,在magento中,我们用不同的标识符引用数据库中的表名,并且在标签< entities >中,我们定义了magento数据表标识和实际表名的关系。
例如:"test/test"=>test_tablename
"test/test2"=>test_tablename2
"test/test3"=>test_tablename3
下面,我们将继续创建模型文件,在Model文件夹下创建Test.php文件,如下:
< ?php
class Magease_Test_Model_Test extends Mage_Core_Model_Abstract
{
public function _construct()
{
parent::_construct();
$this->_init('test/test');//这是资源文件的位置。
}
}
? >
有一个很重要的地方需要注意,函数$this->_init()中的'test/test'指向了资源文件的位置。
下一步,我们需要创建资源文件,在模型文件夹下创建Mysql4文件夹。在Mysql4文件夹下创建Test.php文件。
因此文件位置为\app\code\local\Excellence\Test\Model\Mysql4\Test.php。
< ?php
class Magease_Test_Model_Mysql4_Test extends Mage_Core_Model_Mysql4_Abstract
{
public function _construct()
{
$this->_init('test/test','tets_id'); //test_id是表test的主键。和配置文件config.xml中的一样,test/test是magento的表名
}
}
? >
在此强调一下,'test/test'是配置文件config.xml中我们创建的magento数据表标识。
现在,我们通过创建sql文件来创建数据表。在sql文件夹中,创建一个名为test_setup的子文件夹,新建一个mysql4-install-0.1.0.php[这里0.1.0是这个模块的版本号,和配置文件里的一样]。
< ?php
$installer=$this;//在Variable中获得installer类的对象
$installer->startSetup();
$installer->run("
DROP TABLE {$this->getTable()};
CREATE TABLE {$this->getTable()}(
'test_id' int(11) unsigned NOT NULL auto_increment,
'title' varchar(255) NOT NULL default,
'filename' varchar(255) NOT NULL default,
'content' text NOT NULL default '',
'status' smallint(6) NOT NULL default '0',
'create_time' datetime NULL,
'update_time' datetime NULL,
PRIMARY KEY ('test_id')
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
");
$installer->endSetup();
? >
在这里你能清楚的看到我们创建了SQL表。值得重视的是作用于表名的函数$this->getTable('test').在这里我们使用了getTable函数,所以表名自动加上magento的表前缀作为前缀(如果在安装过程中有添加)。所以,现在我们的模型、资源模型和sql表创建好了。
当任何magento页面在浏览器中被打开时,创建的sql文件被执行。它们工作的原理是:有一个名为"core_resource"的数据库表,这个文件保持每个加载进来的模块的模块版本和名字。例如:在我们的例子中模块版本将是test_setup,即sql文件和模块版本是0.1.0。magento的作用是检查数据库中模块的版本信息和config.xml中的版本信息,它执行相应的sql文件并在数据库中更新版本信息。
在例子中,我们已经加载了之前的模块(我们博客中的),不包含sql文件。所以,我们数据库表的版本是0.0.1,并且我们当前的模块版本也是0.0.1,。所以,我们的sql文件不会被加载。你可以通过打开PHPmyadmin来测试一下,当你打开magento时,你的新表不会被创建在数据库中。因此,想要执行我们的sql文件,我们只需要移除模块中"core_resource"里面的我们的模块的信息,然后在此打开magento。
另一种来加载sql文件的方式或者说是正确的方法是:我们增加模块的版本号为0.0.2,因此在config.xml文件中的标签< version >里,我们将使用的是0.0.2。同样,我们将创建一个名为mysql4-upgrate-0.0.1-0.0.2.php的新的sql文件。现在,当我们在此打开magento页面的时候,magento会检查表"core_resource",在哪个表中,版本号是0.0.1,。但是在config.xml中,我们已经更新版本号为0.0.2,所以,如果我们有任何sql更新文件,magento都会检查它并执行它,执行后,表"core_resource"中的版本信息也会更新到最新的版本。这也对magento更新的进程给了提示。
Save、Load和Delete函数
在其他许多重要的函数中,magento中所有继承自类Mage_Core_Model_Abstract的模块都有函数save()、delete()和load()。在进入这些函数前,还要学习另外一种重要的东西。在magento的每一个模型中,你可以调用任何getter和setter函数。
例如:$model->setAbc()会起作用,而$model->getAbc()会返回值。同样,$model->setManish(),$model->setCreateDate()可以做到。另一个需要记住的函数是$model->getDate()。这个函数返回模型中所有通过setter函数被设置的任何数组。
如果你想要知道setter和getter是如何实现的,它通过PHP魔术函数完成,而这些都将在类Varien_Object中实施。
Save函数应用于表中的INSERT操作。所以,保存一个模型前,你需要首先设置一下模型中所有的值。
$model=Mage::getModel('test/test');
$model->setTitle('test title');
$model->setFilename('filename');
$model->setContent('abc abc abc');
$model->setStatus(1);
$model->setCreatedTime(strtotime('now'));
$model->setUpdatedTime(strtotime('now'));
$model->save();
正如你注意到的,这些同我们数据库表的列一样。这些将插入所有的数据到表中相应的列,然后执行保存操作。你将会得到该表的主键(test_id).
你可以这样:
$id=$model->getId();
Or
$id=$model->getTestId();
Load函数就像它的名字一样,是用来读取表中的行,在模型中设置相应的值。对于加载函数工作,你需要有表的主键。
例如:
$test_id=3;
$model=Mage::getModel('test/test')->load($test_id);
echo $model->getTitle();
print_r($model->getData());
$model->setTitle('new title');
$model->save(); //这将通过加载的主键更新表中现有的行。不会插入一个新的列
Delete函数会根据主键删除表中的行。因此,如果你执行$model->delete(),它将根据模型中加载的主键删除行。
$test_id=3;
$model=Mage::getModel('test/test')->load($test_id);
$model->delete(); //删除主键为3的行
_before和_after函数
由于我们的模型继承Mage_Core_Model_Abstract,我们在自己的模型中可以访问很多有用的功能。我们已经讨论了save(),load()和delete()函数,其它哟御用的功能还有_beforeSave(), _afterSave(), _beforeLoad(), _afterLoad(), _beforeDelete(), _afterDelete()。顾名思义,这些函数都是在它们各自的操作之前或之后调用的。
_before():在保存模型之前调用。如果你想要在保存之前进行验证,你可以利用这个函数。例如:加入在用户保存之前,我们需要重复检查电子邮件地址。因此,该代码会是这样:
protect function _beforeSave()
{
parent::_beforeSave();
if($this->getResource()->checkDuplicate($this)){
throw new Exception('User Email Already Exists');
} // $this->getResource()返回资源模型的对象,在这里你可以操作sql数据
return $this;
}
同样,我们也可以使用其他的功能。