# Model Events
## 事件与事件管理器(Events and Events Manager)
Models allow you to implement events that will be thrown when performing an insert/update/delete. They help define business rules for a certain model. The following are the events supported by[Phalcon\\Mvc\\Model](http://docs.iphalcon.cn/api/Phalcon_Mvc_Model.html)and their order of execution:
| Operation | Name | Can stop operation? | Explanation |
| --- | --- | --- | --- |
| Inserting/Updating | beforeValidation | YES | Is executed before the fields are validated for not nulls/empty strings or foreign keys |
| Inserting | beforeValidationOnCreate | YES | Is executed before the fields are validated for not nulls/empty strings or foreign keys when an insertion operation is being made |
| Updating | beforeValidationOnUpdate | YES | Is executed before the fields are validated for not nulls/empty strings or foreign keys when an updating operation is being made |
| Inserting/Updating | onValidationFails | YES (already stopped) | Is executed after an integrity validator fails |
| Inserting | afterValidationOnCreate | YES | Is executed after the fields are validated for not nulls/empty strings or foreign keys when an insertion operation is being made |
| Updating | afterValidationOnUpdate | YES | Is executed after the fields are validated for not nulls/empty strings or foreign keys when an updating operation is being made |
| Inserting/Updating | afterValidation | YES | Is executed after the fields are validated for not nulls/empty strings or foreign keys |
| Inserting/Updating | beforeSave | YES | Runs before the required operation over the database system |
| Updating | beforeUpdate | YES | Runs before the required operation over the database system only when an updating operation is being made |
| Inserting | beforeCreate | YES | Runs before the required operation over the database system only when an inserting operation is being made |
| Updating | afterUpdate | NO | Runs after the required operation over the database system only when an updating operation is being made |
| Inserting | afterCreate | NO | Runs after the required operation over the database system only when an inserting operation is being made |
| Inserting/Updating | afterSave | NO | Runs after the required operation over the database system |
### 模型中自定义事件(Implementing Events in the Model’s class)
The easier way to make a model react to events is implement a method with the same name of the event in the model’s class:
~~~
<?php
namespace Store\Toys;
use Phalcon\Mvc\Model;
class Robots extends Model
{
public function beforeValidationOnCreate()
{
echo "This is executed before creating a Robot!";
}
}
~~~
Events can be useful to assign values before performing an operation, for example:
~~~
<?php
use Phalcon\Mvc\Model;
class Products extends Model
{
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");
}
}
~~~
### 使用自定义事件管理器(Using a custom Events Manager)
Additionally, this component is integrated with[Phalcon\\Events\\Manager](http://docs.iphalcon.cn/api/Phalcon_Events_Manager.html), this means we can create listeners that run when an event is triggered.
~~~
<?php
namespace Store\Toys;
use Phalcon\Mvc\Model;
use Phalcon\Events\Event;
use Phalcon\Events\Manager as EventsManager;
class Robots extends Model
{
public function initialize()
{
$eventsManager = new EventsManager();
// Attach an anonymous function as a listener for "model" events
$eventsManager->attach(
"model:beforeSave",
function (Event $event, $robot) {
if ($robot->name === "Scooby Doo") {
echo "Scooby Doo isn't a robot!";
return false;
}
return true;
}
);
// Attach the events manager to the event
$this->setEventsManager($eventsManager);
}
}
~~~
In the example given above, the Events Manager only acts as a bridge between an object and a listener (the anonymous function). Events will be fired to the listener when ‘robots’ are saved:
~~~
<?php
use Store\Toys\Robots;
$robot = new Robots();
$robot->name = "Scooby Doo";
$robot->year = 1969;
$robot->save();
~~~
If we want all objects created in our application use the same EventsManager, then we need to assign it to the Models Manager:
~~~
<?php
use Phalcon\Events\Event;
use Phalcon\Events\Manager as EventsManager;
// Registering the modelsManager service
$di->setShared(
"modelsManager",
function () {
$eventsManager = new EventsManager();
// Attach an anonymous function as a listener for "model" events
$eventsManager->attach(
"model:beforeSave",
function (Event $event, $model) {
// Catch events produced by the Robots model
if (get_class($model) === "Store\\Toys\\Robots") {
if ($model->name === "Scooby Doo") {
echo "Scooby Doo isn't a robot!";
return false;
}
}
return true;
}
);
// Setting a default EventsManager
$modelsManager = new ModelsManager();
$modelsManager->setEventsManager($eventsManager);
return $modelsManager;
}
);
~~~
If a listener returns false that will stop the operation that is executing currently.
## 记录底层 SQL 语句(Logging Low-Level SQL Statements)
When using high-level abstraction components such as[Phalcon\\Mvc\\Model](http://docs.iphalcon.cn/api/Phalcon_Mvc_Model.html)to access a database, it is difficult to understand which statements are finally sent to the database system.[Phalcon\\Mvc\\Model](http://docs.iphalcon.cn/api/Phalcon_Mvc_Model.html)is supported internally by[Phalcon\\Db](http://docs.iphalcon.cn/api/Phalcon_Db.html).[Phalcon\\Logger](http://docs.iphalcon.cn/api/Phalcon_Logger.html)interacts with[Phalcon\\Db](http://docs.iphalcon.cn/api/Phalcon_Db.html), providing logging capabilities on the database abstraction layer, thus allowing us to log SQL statements as they happen.
~~~
<?php
use Phalcon\Logger;
use Phalcon\Events\Manager;
use Phalcon\Logger\Adapter\File as FileLogger;
use Phalcon\Db\Adapter\Pdo\Mysql as Connection;
$di->set(
"db",
function () {
$eventsManager = new EventsManager();
$logger = new FileLogger("app/logs/debug.log");
// Listen all the database events
$eventsManager->attach(
"db:beforeQuery",
function ($event, $connection) use ($logger) {
$logger->log(
$connection->getSQLStatement(),
Logger::INFO
);
}
);
$connection = new Connection(
[
"host" => "localhost",
"username" => "root",
"password" => "secret",
"dbname" => "invo",
]
);
// Assign the eventsManager to the db adapter instance
$connection->setEventsManager($eventsManager);
return $connection;
}
);
~~~
As models access the default database connection, all SQL statements that are sent to the database system will be logged in the file:
~~~
<?php
use Store\Toys\Robots;
$robot = new Robots();
$robot->name = "Robby the Robot";
$robot->created_at = "1956-07-21";
if ($robot->save() === false) {
echo "Cannot save robot";
}
~~~
As above, the file*app/logs/db.log*will contain something like this:
~~~
[Mon, 30 Apr 12 13:47:18 -0500][DEBUG][Resource Id #77] INSERT INTO robots
(name, created_at) VALUES ('Robby the Robot', '1956-07-21')
~~~
## 分析 SQL 语句(Profiling SQL Statements)
Thanks to[Phalcon\\Db](http://docs.iphalcon.cn/api/Phalcon_Db.html), the underlying component of[Phalcon\\Mvc\\Model](http://docs.iphalcon.cn/api/Phalcon_Mvc_Model.html), it’s possible to profile the SQL statements generated by the ORM in order to analyze the performance of database operations. With this you can diagnose performance problems and to discover bottlenecks.
~~~
<?php
use Phalcon\Db\Profiler as ProfilerDb;
use Phalcon\Events\Manager as EventsManager;
use Phalcon\Db\Adapter\Pdo\Mysql as MysqlPdo;
$di->set(
"profiler",
function () {
return new ProfilerDb();
},
true
);
$di->set(
"db",
function () use ($di) {
$eventsManager = new EventsManager();
// Get a shared instance of the DbProfiler
$profiler = $di->getProfiler();
// Listen all the database events
$eventsManager->attach(
"db",
function ($event, $connection) use ($profiler) {
if ($event->getType() === "beforeQuery") {
$profiler->startProfile(
$connection->getSQLStatement()
);
}
if ($event->getType() === "afterQuery") {
$profiler->stopProfile();
}
}
);
$connection = new MysqlPdo(
[
"host" => "localhost",
"username" => "root",
"password" => "secret",
"dbname" => "invo",
]
);
// Assign the eventsManager to the db adapter instance
$connection->setEventsManager($eventsManager);
return $connection;
}
);
~~~
Profiling some queries:
~~~
<?php
use Store\Toys\Robots;
// Send some SQL statements to the database
Robots::find();
Robots::find(
[
"order" => "name",
]
);
Robots::find(
[
"limit" => 30,
]
);
// Get the generated profiles from the profiler
$profiles = $di->get("profiler")->getProfiles();
foreach ($profiles as $profile) {
echo "SQL Statement: ", $profile->getSQLStatement(), "\n";
echo "Start Time: ", $profile->getInitialTime(), "\n";
echo "Final Time: ", $profile->getFinalTime(), "\n";
echo "Total Elapsed Time: ", $profile->getTotalElapsedSeconds(), "\n";
}
~~~
Each generated profile contains the duration in milliseconds that each instruction takes to complete as well as the generated SQL statement.
- 简介
- 安装
- 安装(installlation)
- XAMPP下的安装
- WAMP下安装
- Nginx安装说明
- Apache安装说明
- Cherokee 安装说明
- 使用 PHP 内置 web 服务器
- Phalcon 开发工具
- Linux 系统下使用 Phalcon 开发工具
- Mac OS X 系统下使用 Phalcon 开发工具
- Windows 系统下使用 Phalcon 开发工具
- 教程
- 教程 1:让我们通过例子来学习
- 教程 2:INVO简介
- 教程 3: 保护INVO
- 教程4: 使用CRUD
- 教程5: 定制INVO
- 教程 6: Vökuró
- 教程 7:创建简单的 REST API
- 组件
- 依赖注入与服务定位器
- MVC架构
- 使用控制器
- 使用模型
- 模型关系
- 事件与事件管理器
- Behaviors
- 模型元数据
- 事务管理
- 验证数据完整性
- Workingwith Models
- Phalcon查询语言
- 缓存对象关系映射
- 对象文档映射 ODM
- 使用视图
- 视图助手
- 资源文件管理
- Volt 模版引擎
- MVC 应用
- 路由
- 调度控制器
- Micro Applications
- 使用命名空间
- 事件管理器
- Request Environmen
- 返回响应
- Cookie 管理
- 生成 URL 和 路径
- 闪存消息
- 使用 Session 存储数据
- 过滤与清理
- 上下文编码
- 验证Validation
- 表单_Forms
- 读取配置
- 分页 Pagination
- 使用缓存提高性能
- 安全
- 加密与解密 Encryption/Decryption
- 访问控制列表
- 多语言支持
- 类加载器 Class Autoloader
- 日志记录_Logging
- 注释解析器 Annotations Parser
- 命令行应用 Command Line Applications
- Images
- 队列 Queueing
- 数据库抽象层
- 国际化
- 数据库迁移
- 调试应用程序
- 单元测试
- 进阶技巧与延伸阅读
- 提高性能:下一步该做什么?
- Dependency Injection Explained
- Understanding How Phalcon Applications Work
- Api
- Abstract class Phalcon\Acl