对象文件映射(ODM (Object-Document Mapper))


除了可以
映射关系数据库的表
之外,Phalcon还可以使用NoSQL数据库如MongoDB等。Phalcon中的ODM具有可以非常容易的实现如下功能:CRUD,事件,验证等。

因为NoSQL数据库中无sql查询及计划等操作故可以提高数据操作的性能。再者,由于无SQL语句创建的操作故可以减少SQL注入的危险。

当前Phalcon中支持的NosSQL数据库如下:


名称


描述


MongoDB


MongoDB是一个稳定的高性能的开源的NoSQL数据

创建模型(Creating Models)?

NoSQL中的模型类扩展自
Phalcon\Mvc\Collection.模型必须要放入模型文件夹中而且每个模型文件必须只能有一个模型类;
模型类名应该为小驼峰法书写:

<?php

class Robots
extends \Phalcon\Mvc\Collection

{

}

如果PHP版本为5.4/5.5或更高版本,为了提高性能节省内存开销,最好在模型类文件中定义每个字段。

模型Robots默认和数据库中的robots表格映射。如果想使用别的名字映射数据库中的表格则只需要重写getSource()方法即可:

<?php

class Robots
extends \Phalcon\Mvc\Collection

{

public
function
getSource()

{

return
"the_robots";

}

}

理解文档对象(Understanding Documents To Objects)?

每个模型的实例和数据库表中的一个文档(记录)相对应。我们可以非常容易的通过读取对象属性来访问表格的数据。例如访问robots表格:

$ mongo test

MongoDB shell version: 1.8.2

connecting to: test

> db.robots.find()

{ "_id" : ObjectId("508735512d42b8c3d15ec4e1"),
"name" :
"Astro Boy",
"year" : 1952,

"type" :
"mechanical" }

{ "_id" : ObjectId("5087358f2d42b8c3d15ec4e2"),
"name" :
"Bender",
"year" : 1999,

"type" :
"mechanical" }

{ "_id" : ObjectId("508735d32d42b8c3d15ec4e3"),
"name" :
"Wall-E",
"year" : 2008 }

>

模型中使用命名空间(Models in Namespaces)?

我们在这里可以使用命名空间来避免类名冲突。这个例子中我们使用getSource方法来标明要使用的数据库表:

<?php

namespace Store\Toys;

class Robots
extends \Phalcon\Mvc\Collection

{

public
function
getSource()

{

return
"robots";

}

}

我们可以通过对象的ID查找到对象然后打印出其名字:

<?php

// Find record with _id = "5087358f2d42b8c3d15ec4e2"

$robot = Robots::findById("5087358f2d42b8c3d15ec4e2");

// Prints "Bender"

echo
$robot->name;

一旦记录被加载到内存中,我们就可以对这些数据进行修改了,修改之后还可以保存:

<?php

$robot = Robots::findFirst(array(

array(‘name‘
=> ‘Astroy Boy‘)

));

$robot->name =
"Voltron";

$robot->save();

设置连接(Setting a Connection)?

这里的MongoDB服务是从服务容器中取得的。默认,Phalcon会使mongo作服务名:

<?php

// Simple database connection to localhost

$di->set(‘mongo‘,
function() {

$mongo =
new Mongo();

return
$mongo->selectDb("store");

}, true);

// Connecting to a domain socket, falling back to localhost connection

$di->set(‘mongo‘,
function() {

$mongo =
new Mongo("mongodb:///tmp/mongodb-27017.sock,localhost:27017");

return
$mongo->selectDb("store");

}, true);

查找文档(Finding Documents)?

Phalcon\Mvc\Collection

<?php

// How many robots are there?

$robots = Robots::find();

echo
"There are ", count($robots),
"\n";

// How many mechanical robots are there?

$robots = Robots::find(array(

array("type"
=> "mechanical")

));

echo
"There are ", count($robots),
"\n";

// Get and print mechanical robots ordered by name upward

$robots = Robots::find(array(

array("type"
=> "mechanical"),

"sort" =>
array("name" =>
1)

));

foreach ($robots
as
$robot) {

echo
$robot->name,
"\n";

}

// Get first 100 mechanical robots ordered by name

$robots = Robots::find(array(

array("type"
=> "mechanical"),

"sort" =>
array("name" =>
1),

"limit" =>
100

));

foreach ($robots
as
$robot) {

echo
$robot->name,
"\n";

}

这里我们可以使用findFirst()来取得配置查询的第一条记录:

<?php

// What‘s the first robot in robots collection?

$robot = Robots::findFirst();

echo
"The robot name is ",
$robot->name,
"\n";

// What‘s the first mechanical robot in robots collection?

$robot = Robots::findFirst(array(

array("type"
=> "mechanical")

));

echo
"The first mechanical robot name is ",
$robot->name,
"\n";

find()和findFirst方法都接收一个关联数据组为查询的条件:

<?php

// First robot where type = "mechanical" and year = "1999"

$robot = Robots::findFirst(array(

"conditions" =>
array(

"type" =>
"mechanical",

"year" =>
"1999"

)

));

// All virtual robots ordered by name downward

$robots = Robots::find(array(

"conditions" =>
array("type" =>
"virtual"),

"sort"       =>
array("name" => -1)

));

可用的查询选项:


参数


描述


例子


条件


搜索条件,用于取只满足要求的数,默认情况下Phalcon_model会假定关联数据的第一个参数为查询条


“conditions” => array(‘$gt’ => 1990)


字段


若指定则返回指定的字段而非全部字,当设置此字段时会返回非完全版本的对


“fields” => array(‘name’ => true)



这个选项用来对查询结果进行排序,使用一个为多个字段作为排序的标准,使用数组来表格,1代表升序,-1代表降


“order” => array(“name” => -1, “status” => 1)


限制


限制查询结果集到指定的范围


“limit” => 10


间隔


跳过指定的条目选取结果


“skip” => 50

如果你有使用sql(关系)数据库的经验,你也许想查看二者的映射表格
SQL to Mongo Mapping Chart .
聚合(Aggregations) ——————–
我们可以使用Mongo提供的方法使用Mongo模型返回聚合结果。聚合结果不是使用MapReduce来计算的。基于此,我们可以非常容易的取得聚合值,比如总计或平均值等:

<?php

$data = Article::aggregate(array(

array(

‘$project‘ =>
array(‘category‘ =>
1)

),

array(

‘$group‘ =>
array(

‘_id‘ =>
array(‘category‘ =>
‘$category‘),

‘id‘ =>
array(‘$max‘ =>
‘$_id‘)

)

)

));

创建和更新记录(Creating Updating/Records)?

Phalcon\Mvc\Collection::save()方法可以用来保存数据,Phalcon会根据当前数据库中的数据来对比以确定是新加一条数据还是更新数据。在Phalcon内部会直接使用
Phalcon\Mvc\Collection
的save或update方法来进行操作。
当然这个方法内部也会调用我们在模型中定义的验证方法或事件等:

<?php

$robot       =
new Robots();

$robot->type =
"mechanical";

$robot->name =
"Astro Boy";

$robot->year =
1952;

if ($robot->save()
== false) {

echo
"Umh, We can‘t store robots right now:
\n
";

foreach ($robot->getMessages()
as
$message) {

echo
$message,
"\n";

}

} else {

echo
"Great, a new robot was saved successfully!";

}

“_id”属性会被Mongo驱动自动的随MongId_而更新。

<?php

$robot->save();

echo
"The generated id is: ",
$robot->getId();

验证信息(Validation Messages)?

Phalcon\Mvc\Collection
提供了一个信息子系统,使用此系统开发者可以非常容易的实现在数据处理中的验证信息的显示及保存。
每条信息即是一个
Phalcon\Mvc\Model\Message
类的对象实例。我们使用getMessages来取得此信息。每条信息中包含了
如哪个字段产生的消息,或是消息类型等信息:

<?php

if ($robot->save()
== false) {

foreach ($robot->getMessages()
as
$message) {

echo
"Message: ",
$message->getMessage();

echo
"Field: ",
$message->getField();

echo
"Type: ",
$message->getType();

}

}

验证事件和事件管理(Validation Events and Events Manager)?

在模型类的数据操作过程中可以产生一些事件。我们可以在这些事件中定义一些业务规则。下面是
Phalcon\Mvc\Collection
所支持的事件及其执行顺序:


操作


名称


能否停止操作


解释


Inserting/Updating


beforeValidation


YES


在验证和最终插入/更新进行之执行


Inserting


beforeValidationOnCreate


YES


仅当创建新条目验证之前执行


Updating


beforeValidationOnUpdate


YES


仅在更新条目验证之前


Inserting/Updating


onValidationFails


YES (already stopped)


验证执行失败后执行


Inserting


afterValidationOnCreate


YES


新建条目验证之后执行


Updating


afterValidationOnUpdate


YES


更新条目后执行


Inserting/Updating


afterValidation


YES


在验证进行之前执


Inserting/Updating


beforeSave


YES


在请示的操作(保存)运行之前


Updating


beforeUpdate


YES


更新操作执行之前运行


Inserting


beforeCreate


YES


创建操作执行之前运行


Updating


afterUpdate


NO


更新执行之后执行


Inserting


afterCreate


NO


创建执行之后


Inserting/Updating


afterSave


NO


保存执行之后

为了响应一个事件,我们需在模型中实现同名方法:

<?php

class Robots
extends \Phalcon\Mvc\Collection

{

public
function
beforeValidationOnCreate()

{

echo
"This is executed before creating a Robot!";

}

}

在执行操作之前先在指定的事件中设置值有时是非常有用的:

<?php

class Products
extends \Phalcon\Mvc\Collection

{

public
function
beforeCreate()

{

// Set the creation date

$this->created_at
= date(‘Y-m-d H:i:s‘);

}

public
function
beforeUpdate()

{

// Set the modification date

$this->modified_in
= date(‘Y-m-d H:i:s‘);

}

}

另外,这个组件也可以和
Phalcon\Events\Manager
进行集成,这就意味着我们在事件触发创建监听器。

<?php

$eventsManager = new Phalcon\Events\Manager();

//Attach an anonymous function as a listener for "model" events

$eventsManager->attach(‘collection‘, function($event, $robot) {

if ($event->getType() == ‘beforeSave‘) {

if ($robot->name == ‘Scooby Doo‘) {

echo "Scooby Doo isn‘t a robot!";

return false;

}

}

return true;

});

$robot = new Robots();

$robot->setEventsManager($eventsManager);

$robot->name = ‘Scooby Doo‘;

$robot->year = 1969;

$robot->save();

上面的例子中EventsManager仅在对象和监听器(匿名函数)之间扮演了一个桥接器的角色。如果我们想在创建应用时使用同一个EventsManager,我们需要把这个EventsManager对象设置到

collectionManager服务中:

<?php

//Registering the collectionManager service

$di->set(‘collectionManager‘,
function() {

$eventsManager =
new Phalcon\Events\Manager();

// Attach an anonymous function as a listener for "model" events

$eventsManager->attach(‘collection‘,
function($event,
$model) {

if (get_class($model)
== ‘Robots‘) {

if ($event->getType()
== ‘beforeSave‘) {

if ($model->name
== ‘Scooby Doo‘) {

echo
"Scooby Doo isn‘t a robot!";

return
false;

}

}

}

return
true;

});

// Setting a default EventsManager

$modelsManager =
new Phalcon\Mvc\Collection\Manager();

$modelsManager->setEventsManager($eventsManager);

return
$modelsManager;

}, true);

实现业务规则(Implementing a Business Rule)?

当插入或更新删除等执行时,模型会检查上面表格中列出的方法是否存在。我们建议定义模型里的验证方法以避免业务逻辑暴露出来。下面的例子中实现了在保存或更新时对年份的验证,年份不能小于0年:

<?php

class Robots
extends \Phalcon\Mvc\Collection

{

public
function
beforeSave()

{

if ($this->year
< 0) {

echo
"Year cannot be smaller than zero!";

return
false;

}

}

}

在响应某些事件时返回了false则会停止当前的操作。
如果事实响应未返回任何值,
Phalcon\Mvc\Collection
会假定返回了true值。

验证数据完整性(Validating Data Integrity)?

Phalcon\Mvc\Collection
提供了若干个事件用于验证数据和实现业务逻辑。特定的事件中我们可以调用内建的验证器 Phalcon提供了一些验证器可以用在此阶段的验证上。

下面的例子中展示了如何使用:

<?php

use Phalcon\Mvc\Model\Validator\InclusionIn,

Phalcon\Mvc\Model\Validator\Numericality;

class Robots
extends \Phalcon\Mvc\Collection

{

public
function
validation()

{

$this->validate(new
InclusionIn(

array(

"field"  =>
"type",

"message" =>
"Type must be: mechanical or virtual",

"domain" =>
array("Mechanical",
"Virtual")

)

));

$this->validate(new
Numericality(

array(

"field"  =>
"price",

"message" =>
"Price must be numeric"

)

));

return
$this->validationHasFailed() !=
true;

}

}

上面的例子使用了内建的”InclusionIn”验证器。这个验证器检查了字段的类型是否在指定的范围内。如果值不在范围内即验证失败会返回false.
下面支持的内验证器:

除了内建的验证器外,我们还可以创建自己的验证器:

<?php

class UrlValidator
extends \Phalcon\Mvc\Collection\Validator

{

public
function
validate($model)

{

$field =
$this->getOption(‘field‘);

$value    =
$model->$field;

$filtered = filter_var($value,
FILTER_VALIDATE_URL);

if (!$filtered)
{

$this->appendMessage("The
URL is invalid",
$field,
"UrlValidator");

return
false;

}

return
true;

}

}

添加验证器到模型:

<?php

class Customers
extends \Phalcon\Mvc\Collection

{

public
function
validation()

{

$this->validate(new
UrlValidator(array(

"field"  =>
"url",

)));

if ($this->validationHasFailed()
== true) {

return
false;

}

}

}

创建验证器的目的即是使之在多个模型间重复利用以实现代码重用。验证器可简单如下:

<?php

class Robots
extends \Phalcon\Mvc\Collection

{

public
function
validation()

{

if ($this->type
== "Old") {

$message =
new Phalcon\Mvc\Model\Message(

"Sorry, old robots are not allowed anymore",

"type",

"MyType"

);

$this->appendMessage($message);

return
false;

}

return
true;

}

}

删除记录(Deleting Records)?

Phalcon\Mvc\Collection::delete()方法用来删除记录条目。我们可以如下使用:

<?php

$robot = Robots::findFirst();

if ($robot !=
false) {

if ($robot->delete()
== false) {

echo
"Sorry, we can‘t delete the robot right now:
\n";

foreach ($robot->getMessages()
as
$message) {

echo
$message,
"\n";

}

} else {

echo
"The robot was deleted successfully!";

}

}

也可以使用遍历的方式删除多个条目的数据:

<?php

$robots = Robots::find(array(

array("type"
=> "mechanical")

));

foreach ($robots
as
$robot) {

if ($robot->delete()
== false) {

echo
"Sorry, we can‘t delete the robot right now:
\n";

foreach ($robot->getMessages()
as
$message) {

echo
$message,
"\n";

}

} else {

echo
"The robot was deleted successfully!";

}

}

当删除操作执行时我们可以执行如下事件,以实现定制业务逻辑的目的:


操作


名称


是否可停止


解释


删除


beforeDelete



删除之前执行


删除


afterDelete



删除之后执行

验证失败事件(Validation Failed Events)?

验证失败时依据不同的情形下列事件会触发:


操作


名称


解释


插入和或更新


notSave


当插入/更新操作失败时触


插入删除或更新


onValidationFails


当数据操作失败时触发

固有 Id

用户主键(Implicit Ids vs. User Primary Keys)?

默认Phalcon\Mvc\Collection会使用MongoIds_来产生_id.如果用户想自定义主键也可以只需:

<?php

class Robots
extends Phalcon\Mvc\Collection

{

public
function
initialize()

{

$this->useImplicitObjectIds(false);

}

}

设置多个数据库(Setting multiple databases)?

Phalcon中,所有的模可以只属于一个数据库或是每个模型有一个数据。事实上当
Phalcon\Mvc\Collection
试图连接数据库时 Phalcon会从DI中取名为mongo的服务。当然我们可在模型的initialize方法中进行连接设置:

<?php

// This service returns a mongo database at 192.168.1.100

$di->set(‘mongo1‘,
function() {

$mongo =
new Mongo("mongodb://scott:[email protected]");

return
$mongo->selectDb("management");

}, true);

// This service returns a mongo database at localhost

$di->set(‘mongo2‘,
function() {

$mongo =
new Mongo("mongodb://localhost");

return
$mongo->selectDb("invoicing");

}, true);

然后在初始化方法,我们定义了模型的连接:

<?php

class Robots
extends \Phalcon\Mvc\Collection

{

public
function
initialize()

{

$this->setConnectionService(‘mongo1‘);

}

}

注入服务到模型(Injecting services into Models)?

我们可能需要在模型内使用应用的服务,下面的例子中展示了如何去做:

<?php

class Robots
extends \Phalcon\Mvc\Collection

{

public
function
notSave()

{

// Obtain the flash service from the DI container

$flash =
$this->getDI()->getShared(‘flash‘);

// Show validation messages

foreach ($this->getMessages()
as
$message){

$flash->error((string)
$message);

}

}

}

notSave事件在创建和更新失败时触发。我们使用flash服务来处理验证信息。如此做我们无需在每次保存后打印消息出来。

时间: 2024-10-12 23:01:37

对象文件映射(ODM (Object-Document Mapper))的相关文章

44 MySQL &amp; orm对象关系映射

orm 模型 对象关系映射: Object Relational Mapping 是一种程序技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换 ORM模型的简单性简化了数据库查询过程 三个核心原则: 简单性:以最基本的形式建模数据:简化了数据库查询过程 传达性:数据库结构被任何人都能理解的语言文档化: 精确性:基于数据模型创建正确标准化的结构. 1)singleton 实现orm mysql_singleton.py import pymysql class Mysql(object)

对象关系映射(ORM)

对象-关系映射(Object Relational Mapping,简称ORM,对象关系映射)是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术. 简单的说,ORM是通过使用描述对象和数据库之间映射的元数据,将java程序中的对象自动持久化到关系数据库中.本质上就是将数据从一种形式转换到另外一种形式. 对象-关系映射(Object/Relation Mapping,简称ORM),是随着面向对象的软件开发方法发展而产生的.面向对象的开发方法是当今企业级应用开发环境中的主流开发方法,关系数

面试题思考:什么是 对象/关系 映射集成模块

所谓对象关系映射(Object Relational Mapping,简称ORM)是通过使用描述对象和数据库之间映射的元数据,将面向对象语言程序中的对象自动持久化到关系数据库中.本质上就是将数据从一种形式转换到另外一种形式. 详细一点,是 面向对象编程中的 对象(Object) 和关系数据库的 关系(Relation) 的一个映射(Mapping). 产生的原因是因为软件开发已经是面向对象的了. 所有的值,操作都是基于对象的概念. 而数据库还是关系数据库.记录的存储还是一条一条的. 为了在逻辑上

Hibernate之配置文件以及对象关系映射文件了解

声明:CSDN不知道怎么了,有时候就是发表不了博文.本来就是一天一篇博文,最近搞的我很郁闷.有时候一天,有时候两三天都不能发.这就属于不可抗力.没办法的,啥时能发,我就发了. 一.学习案例:关于hibernate的配置文件以及对象关系映射文件的了解. 二.案例分析: a)hibernate配置文件(hibernate.cfg.xml) 1.hibernate.dialect:数据库使用的SQL方言 2.hiebrnate.connection.driver_class:数据库的驱动程序 3.hi

一:ORM关系对象映射(Object Relational Mapping,简称ORM)

狼来的日子里! 奋发博取 10)django-ORM(创建,字段类型,字段参数) 一:ORM关系对象映射(Object Relational Mapping,简称ORM) ORM分两种: DB first 先在数据库中创建数据库表等 Code first 先创建类,然后根据类创建数据表等.django中遵循 Code Frist 的原则,即:根据代码中定义的类来自动生成数据库表. 二:Django ORM创建 1)创建类 创建的类必须继承models.Model,在数据库中自动创建表名为:app

Hibernate -- xxx.hbm.xml ORM元数据 表对象关系映射文件

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> <!-- ORM元数据 表对象关系映射文件 p

hibernate(四)__由表逆向创建Domain对象和对象关系映射文件

之前我们是手写Domain对象和对象关系映射文件->然后生成数据库中的Table. 现在我们反过来先在数据库中建好Table->然后用工具生成Domain对象和对象关系映射文件. 步骤: 1.创建一个web工程项目 2.通过myeclipse 提供的数据库浏览器连接到我们的数据库. ①新建一个数据库连接: ②配置数据库连接(这里借用以oracle一张图,后面都是在sql server的数据库下的配置,可以忽视不影响): ③成功之后输入登录密码进入数据库: 右键表可直接修改删除表,当然这也是相当

[原创]java WEB学习笔记81:Hibernate学习之路--- 对象关系映射文件(.hbm.xml):hibernate-mapping 节点,class节点,id节点(主键生成策略),property节点

本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱好者,互联网技术发烧友 微博:伊直都在0221 QQ:951226918 -----------------------------------------------------------------------------------------------------------------

hibernate 对象关系映射文件详解

POJO 类和数据库的映射文件*.hbm.xml POJO类和关系数据库之间的映射可以用一个XML文档来定义. 映射文件的扩展名为.hbm.xml 在运行时Hibernate将根据这个映射文件来生成各种SQL语句 通过POJO类的数据库映射文件,Hibernate可以理解持久化类和数据表之间的对应关系,也可以理解持久化类属性与数据库表列之间的对应关系 映射文件说明 hibernate-mapping 类层次:class 主键:id 基本类型:property 实体引用类: many-to-one