# 教程 3: Securing INVO
# Tutorial 3: Securing INVO
In this chapter, we continue explaining how INVO is structured, we'll talkabout the implementation of authentication, authorization using events and plugins andan access control list (ACL) managed by Phalcon.
### Log into the Application
A “log in” facility will allow us to work on backend controllers. The separation between backend controllers andfrontend ones is only logical. All controllers are located in the same directory (app/controllers/).
To enter the system, users must have a valid username and password. Users are stored in the table “users”in the database “invo”.
Before we can start a session, we need to configure the connection to the database in the application. A servicecalled “db” is set up in the service container with the connection information. As with the autoloader, we areagain taking parameters from the configuration file in order to configure a service:
```
<pre class="calibre14">```
<?php
use Phalcon\Db\Adapter\Pdo\Mysql as DbAdapter;
// ...
// Database connection is created based on parameters defined in the configuration file
$di->set('db', function () use ($config) {
return new DbAdapter(array(
"host" => $config->database->host,
"username" => $config->database->username,
"password" => $config->database->password,
"dbname" => $config->database->name
));
});
```
```
Here, we return an instance of the MySQL connection adapter. If needed, you could do extra actions such as adding alogger, a profiler or change the adapter, setting it up as you want.
The following simple form (app/views/session/index.volt) requests the login information. We've removedsome HTML code to make the example more concise:
```
<pre class="calibre14">```
{{ form('session/start') }}
<fieldset>
<div>
<label for="email">Username/Email</label>
<div>
{{ text_field('email') }}
</div>
</div>
<div>
<label for="password">Password</label>
<div>
{{ password_field('password') }}
</div>
</div>
<div>
{{ submit_button('Login') }}
</div>
</fieldset>
</form>
```
```
Instead of using raw PHP as the previous tutorial, we started to use [*Volt*](#). This is a built-intemplate engine inspired in [Jinja](http://jinja.pocoo.org/) providing a simpler and friendly syntax to create [templates.It](http://templates.It) will not take too long before you become familiar with Volt.
The SessionController::startAction function (app/controllers/SessionController.php) has the task of validating thedata entered in the form including checking for a valid user in the database:
```
<pre class="calibre14">```
<?php
class SessionController extends ControllerBase
{
// ...
private function _registerSession($user)
{
$this->session->set('auth', array(
'id' => $user->id,
'name' => $user->name
));
}
/**
* This action authenticate and logs a user into the application
*
*/
public function startAction()
{
if ($this->request->isPost()) {
$email = $this->request->getPost('email');
$password = $this->request->getPost('password');
$user = Users::findFirst(array(
"(email = :email: OR username = :email:) AND password = :password: AND active = 'Y'",
'bind' => array('email' => $email, 'password' => sha1($password))
));
if ($user != false) {
$this->_registerSession($user);
$this->flash->success('Welcome ' . $user->name);
return $this->forward('invoices/index');
}
$this->flash->error('Wrong email/password');
}
return $this->forward('session/index');
}
}
```
```
For the sake of simplicity, we have used “[sha1](http://php.net/manual/en/function.sha1.php)” to store the password hashes in the database, however, this algorithm isnot recommended in real applications, use “[*bcrypt*](#)” instead.
Note that multiple public attributes are accessed in the controller like: $this->flash, $this->request or $this->session.These are services defined in the services container from earlier (app/config/services.php).When they're accessed the first time, they are injected as part of the controller.
These services are “shared”, which means that we are always accessing the same instance regardless of the placewhere we invoke them.
For instance, here we invoke the “session” service and then we store the user identity in the variable “auth”:
```
<pre class="calibre14">```
<?php
$this->session->set('auth', array(
'id' => $user->id,
'name' => $user->name
));
```
```
Another important aspect of this section is how the user is validated as a valid one,first we validate whether the request has been made using method POST:
```
<pre class="calibre14">```
<?php
if ($this->request->isPost()) {
```
```
Then, we receive the parameters from the form:
```
<pre class="calibre14">```
<?php
$email = $this->request->getPost('email');
$password = $this->request->getPost('password');
```
```
Now, we have to check if there is one user with the same username or email and password:
```
<pre class="calibre14">```
<?php
$user = Users::findFirst(array(
"(email = :email: OR username = :email:) AND password = :password: AND active = 'Y'",
'bind' => array('email' => $email, 'password' => sha1($password))
));
```
```
Note, the use of ‘bound parameters', placeholders :email: and :password: are placed where values should be,then the values are ‘bound' using the parameter ‘bind'. This safely replaces the values for thosecolumns without having the risk of a SQL injection.
If the user is valid we register it in session and forwards him/her to the dashboard:
```
<pre class="calibre14">```
<?php
if ($user != false) {
$this->_registerSession($user);
$this->flash->success('Welcome ' . $user->name);
return $this->forward('invoices/index');
}
```
```
If the user does not exist we forward the user back again to action where the form is displayed:
```
<pre class="calibre14">```
<?php
return $this->forward('session/index');
```
```
### Securing the Backend
The backend is a private area where only registered users have access. Therefore, it is necessaryto check that only registered users have access to these controllers. If you aren't loggedinto the application and you try to access, for example, the products controller (which is private)you will see a screen like this:
![](https://box.kancloud.cn/2015-12-30_568340ffbbd3c.png)
Every time someone attempts to access any controller/action, the application verifies that thecurrent role (in session) has access to it, otherwise it displays a message like the above andforwards the flow to the home page.
Now let's find out how the application accomplishes this. The first thing to know is thatthere is a component called [*Dispatcher*](#). It is informed about the routefound by the [*Routing*](#) component. Then, it is responsible for loading theappropriate controller and execute the corresponding action method.
Normally, the framework creates the Dispatcher automatically. In our case, we want to perform a verificationbefore executing the required action, checking if the user has access to it or not. To achieve this, we havereplaced the component by creating a function in the bootstrap:
```
<pre class="calibre14">```
<?php
use Phalcon\Mvc\Dispatcher;
// ...
/**
* MVC dispatcher
*/
$di->set('dispatcher', function () {
// ...
$dispatcher = new Dispatcher;
return $dispatcher;
});
```
```
We now have total control over the Dispatcher used in the application. Many components in the framework triggerevents that allow us to modify their internal flow of operation. As the Dependency Injector component acts as gluefor components, a new component called [*EventsManager*](#) allows us to intercept the events producedby a component, routing the events to listeners.
### Events Management
An [*EventsManager*](#) allows us to attach listeners to a particular type of event. The type thatinterests us now is “dispatch”. The following code filters all events produced by the Dispatcher:
```
<pre class="calibre14">```
<?php
use Phalcon\Mvc\Dispatcher;
use Phalcon\Events\Manager as EventsManager;
$di->set('dispatcher', function () {
$eventsManager = new EventsManager;
/**
* Check if the user is allowed to access certain action using the SecurityPlugin
*/
$eventsManager->attach('dispatch:beforeDispatch', new SecurityPlugin);
/**
* Handle exceptions and not-found exceptions using NotFoundPlugin
*/
$eventsManager->attach('dispatch:beforeException', new NotFoundPlugin);
$dispatcher = new Dispatcher;
$dispatcher->setEventsManager($eventsManager);
return $dispatcher;
});
```
```
When an event called “beforeDispatch” is triggered the following plugin will be notified:
```
<pre class="calibre14">```
<?php
/**
* Check if the user is allowed to access certain action using the SecurityPlugin
*/
$eventsManager->attach('dispatch:beforeDispatch', new SecurityPlugin);
```
```
When a “beforeException” is triggered then other plugin is notified:
```
<pre class="calibre14">```
<?php
/**
* Handle exceptions and not-found exceptions using NotFoundPlugin
*/
$eventsManager->attach('dispatch:beforeException', new NotFoundPlugin);
```
```
SecurityPlugin is a class located at (app/plugins/SecurityPlugin.php). This class implements the method“beforeDispatch”. This is the same name as one of the events produced in the Dispatcher:
```
<pre class="calibre14">```
<?php
use Phalcon\Acl;
use Phalcon\Events\Event;
use Phalcon\Mvc\User\Plugin;
use Phalcon\Mvc\Dispatcher;
class SecurityPlugin extends Plugin
{
// ...
public function beforeDispatch(Event $event, Dispatcher $dispatcher)
{
// ...
}
}
```
```
The hook events always receive a first parameter that contains contextual information of the event produced ($event)and a second one that is the object that produced the event itself ($dispatcher). It is not mandatory thatplugins extend the class Phalcon\\Mvc\\User\\Plugin, but by doing this they gain easier access to the servicesavailable in the application.
Now, we're verifying the role in the current session, checking if the user has access using the ACL list.If the user does not have access we redirect to the home screen as explained before:
```
<pre class="calibre14">```
<?php
use Phalcon\Acl;
use Phalcon\Events\Event;
use Phalcon\Mvc\User\Plugin;
use Phalcon\Mvc\Dispatcher;
class Security extends Plugin
{
// ...
public function beforeExecuteRoute(Event $event, Dispatcher $dispatcher)
{
// Check whether the "auth" variable exists in session to define the active role
$auth = $this->session->get('auth');
if (!$auth) {
$role = 'Guests';
} else {
$role = 'Users';
}
// Take the active controller/action from the dispatcher
$controller = $dispatcher->getControllerName();
$action = $dispatcher->getActionName();
// Obtain the ACL list
$acl = $this->getAcl();
// Check if the Role have access to the controller (resource)
$allowed = $acl->isAllowed($role, $controller, $action);
if ($allowed != Acl::ALLOW) {
// If he doesn't have access forward him to the index controller
$this->flash->error("You don't have access to this module");
$dispatcher->forward(
array(
'controller' => 'index',
'action' => 'index'
)
);
// Returning "false" we tell to the dispatcher to stop the current operation
return false;
}
}
}
```
```
### Providing an ACL list
In the above example we have obtained the ACL using the method $this->\_getAcl(). This method is alsoimplemented in the Plugin. Now we are going to explain step-by-step how we built the access control list (ACL):
```
<pre class="calibre14">```
<?php
use Phalcon\Acl;
use Phalcon\Acl\Role;
use Phalcon\Acl\Adapter\Memory as AclList;
// Create the ACL
$acl = new AclList();
// The default action is DENY access
$acl->setDefaultAction(Acl::DENY);
// Register two roles, Users is registered users
// and guests are users without a defined identity
$roles = array(
'users' => new Role('Users'),
'guests' => new Role('Guests')
);
foreach ($roles as $role) {
$acl->addRole($role);
}
```
```
Now, we define the resources for each area respectively. Controller names are resources and their actions areaccesses for the resources:
```
<pre class="calibre14">```
<?php
use Phalcon\Acl\Resource;
// ...
// Private area resources (backend)
$privateResources = array(
'companies' => array('index', 'search', 'new', 'edit', 'save', 'create', 'delete'),
'products' => array('index', 'search', 'new', 'edit', 'save', 'create', 'delete'),
'producttypes' => array('index', 'search', 'new', 'edit', 'save', 'create', 'delete'),
'invoices' => array('index', 'profile')
);
foreach ($privateResources as $resource => $actions) {
$acl->addResource(new Resource($resource), $actions);
}
// Public area resources (frontend)
$publicResources = array(
'index' => array('index'),
'about' => array('index'),
'register' => array('index'),
'errors' => array('show404', 'show500'),
'session' => array('index', 'register', 'start', 'end'),
'contact' => array('index', 'send')
);
foreach ($publicResources as $resource => $actions) {
$acl->addResource(new Resource($resource), $actions);
}
```
```
The ACL now have knowledge of the existing controllers and their related actions. Role “Users” has access toall the resources of both frontend and backend. The role “Guests” only has access to the public area:
```
<pre class="calibre14">```
<?php
// Grant access to public areas to both users and guests
foreach ($roles as $role) {
foreach ($publicResources as $resource => $actions) {
$acl->allow($role->getName(), $resource, '*');
}
}
// Grant access to private area only to role Users
foreach ($privateResources as $resource => $actions) {
foreach ($actions as $action) {
$acl->allow('Users', $resource, $action);
}
}
```
```
Hooray!, the ACL is now complete. In next chapter, we will see how a CRUD is implemented in Phalcon and how youcan customize it.
|
- [索引](# "总目录")
- [下一页](# "Tutorial 4: Using CRUDs") |
- [上一页](# "教程 2:Introducing INVO(Tutorial 2: Introducing INVO)") |
- API参考
- API列表
- Abstract class Phalcon\Acl
- Abstract class Phalcon\Acl\Adapter
- Class Phalcon\Acl\Adapter\Memory
- Interface Phalcon\Acl\AdapterInterface
- Class Phalcon\Acl\Exception
- Class Phalcon\Acl\Resource
- Interface Phalcon\Acl\ResourceInterface
- Class Phalcon\Acl\Role
- Interface Phalcon\Acl\RoleInterface
- Class Phalcon\Annotations\Annotation
- Abstract class Phalcon\Annotations\Adapter
- Interface Phalcon\Annotations\AdapterInterface
- Class Phalcon\Annotations\Collection
- Class Phalcon\Annotations\Exception
- Class Phalcon\Annotations\Reader
- Interface Phalcon\Annotations\ReaderInterface
- Class Phalcon\Annotations\Reflection
- Class Phalcon\Assets\Collection
- Class Phalcon\Assets\Exception
- Interface Phalcon\Assets\FilterInterface
- Class Phalcon\Assets\Filters\Cssmin
- Class Phalcon\Assets\Filters\Jsmin
- Class Phalcon\Assets\Filters\None
- Class Phalcon\Assets\Inline
- Class Phalcon\Assets\Inline\Css
- Class Phalcon\Assets\Inline\Js
- Class Phalcon\Assets\Manager
- Class Phalcon\Assets\Resource
- Class Phalcon\Assets\Resource\Css
- Class Phalcon\Assets\Resource\Js
- Abstract class Phalcon\Cache\Backend
- Class Phalcon\Cache\Backend\Apc
- Class Phalcon\Cache\Backend\File
- Class Phalcon\Cache\Backend\Libmemcached
- Class Phalcon\Cache\Backend\Memcache
- Class Phalcon\Cache\Backend\Memory
- Class Phalcon\Cache\Backend\Mongo
- Class Phalcon\Cache\Backend\Redis
- Class Phalcon\Cache\Backend\Xcache
- Interface Phalcon\Cache\BackendInterface
- Class Phalcon\Cache\Exception
- Class Phalcon\Cache\Frontend\Base64
- Class Phalcon\Cache\Frontend\Data
- Class Phalcon\Cache\Frontend\Igbinary
- Class Phalcon\Cache\Frontend\Json
- Class Phalcon\Cache\Frontend\None
- Class Phalcon\Cache\Frontend\Output
- Interface Phalcon\Cache\FrontendInterface
- Class Phalcon\Cache\Multiple
- Class Phalcon\Cli\Router\Route
- Class Phalcon\Config
- Class Phalcon\Config\Adapter\Ini
- Class Phalcon\Config\Adapter\Json
- Class Phalcon\Config\Adapter\Php
- Class Phalcon\Config\Adapter\Yaml
- Class Phalcon\Config\Exception
- Class Phalcon\Crypt
- Class Phalcon\Crypt\Exception
- Interface Phalcon\CryptInterface
- Abstract class Phalcon\Db
- Abstract class Phalcon\Db\Adapter
- Interface Phalcon\Db\AdapterInterface
- Class Phalcon\Db\Column
- Interface Phalcon\Db\ColumnInterface
- Abstract class Phalcon\Db\Dialect
- Interface Phalcon\Db\DialectInterface
- Class Phalcon\Db\Exception
- Class Phalcon\Db\Index
- Interface Phalcon\Db\IndexInterface
- Class Phalcon\Db\Profiler
- Class Phalcon\Db\RawValue
- Class Phalcon\Db\Reference
- Interface Phalcon\Db\ReferenceInterface
- Class Phalcon\Db\Result\Pdo
- Interface Phalcon\Db\ResultInterface
- Class Phalcon\Debug
- Class Phalcon\Debug\Dump
- Class Phalcon\Debug\Exception
- Interface Phalcon\DiInterface
- Abstract class Phalcon\Dispatcher
- Interface Phalcon\DispatcherInterface
- Class Phalcon\Escaper
- Class Phalcon\Escaper\Exception
- Interface Phalcon\EscaperInterface
- Class Phalcon\Events\Event
- Interface Phalcon\Events\EventsAwareInterface
- Class Phalcon\Events\Exception
- Class Phalcon\Events\Manager
- Interface Phalcon\Events\ManagerInterface
- Class Phalcon\Exception
- Class Phalcon\Filter
- Class Phalcon\Filter\Exception
- Interface Phalcon\Filter\UserFilterInterface
- Interface Phalcon\FilterInterface
- Abstract class Phalcon\Flash
- Class Phalcon\Flash\Direct
- Class Phalcon\Flash\Exception
- Class Phalcon\Flash\Session
- Interface Phalcon\FlashInterface
- Class Phalcon\Forms\Form
- Abstract class Phalcon\Forms\Element
- Class Phalcon\Forms\Exception
- Class Phalcon\Forms\Manager
- Class Phalcon\Http\Cookie
- Class Phalcon\Http\Cookie\Exception
- Class Phalcon\Http\Request
- Class Phalcon\Http\Request\Exception
- Class Phalcon\Http\Request\File
- Interface Phalcon\Http\Request\FileInterface
- Interface Phalcon\Http\RequestInterface
- Class Phalcon\Http\Response
- Class Phalcon\Http\Response\Cookies
- Interface Phalcon\Http\Response\CookiesInterface
- Class Phalcon\Http\Response\Exception
- Class Phalcon\Http\Response\Headers
- Interface Phalcon\Http\Response\HeadersInterface
- Interface Phalcon\Http\ResponseInterface
- Class Phalcon\Image
- Abstract class Phalcon\Image\Adapter
- Class Phalcon\Image\Adapter\Imagick
- Interface Phalcon\Image\AdapterInterface
- Class Phalcon\Image\Exception
- Class Phalcon\Kernel
- Class Phalcon\Loader
- Class Phalcon\Loader\Exception
- Abstract class Phalcon\Logger
- Abstract class Phalcon\Logger\Adapter
- Class Phalcon\Logger\Adapter\File
- Class Phalcon\Logger\Adapter\Firephp
- Class Phalcon\Logger\Adapter\Stream
- Class Phalcon\Logger\Adapter\Syslog
- Interface Phalcon\Logger\AdapterInterface
- Class Phalcon\Logger\Exception
- Abstract class Phalcon\Logger\Formatter
- Interface Phalcon\Logger\FormatterInterface
- Class Phalcon\Logger\Item
- Class Phalcon\Logger\Multiple
- Class Phalcon\Mvc\Application
- Class Phalcon\Mvc\Application\Exception
- Abstract class Phalcon\Mvc\Collection
- Abstract class Phalcon\Mvc\Collection\Behavior
- Class Phalcon\Mvc\Collection\Behavior\SoftDelete
- Class Phalcon\Mvc\Collection\Behavior\Timestampable
- Interface Phalcon\Mvc\Collection\BehaviorInterface
- Class Phalcon\Mvc\Collection\Document
- Class Phalcon\Mvc\Collection\Exception
- Class Phalcon\Mvc\Collection\Manager
- Interface Phalcon\Mvc\Collection\ManagerInterface
- Interface Phalcon\Mvc\CollectionInterface
- Abstract class Phalcon\Mvc\Controller
- Interface Phalcon\Mvc\ControllerInterface
- Class Phalcon\Mvc\Dispatcher
- Class Phalcon\Mvc\Dispatcher\Exception
- Interface Phalcon\Mvc\DispatcherInterface
- Interface Phalcon\Mvc\EntityInterface
- Class Phalcon\Mvc\Micro
- Class Phalcon\Mvc\Micro\Collection
- Interface Phalcon\Mvc\Micro\CollectionInterface
- Class Phalcon\Mvc\Micro\Exception
- Class Phalcon\Mvc\Micro\LazyLoader
- Interface Phalcon\Mvc\Micro\MiddlewareInterface
- Abstract class Phalcon\Mvc\Model
- Abstract class Phalcon\Mvc\Model\Behavior
- Class Phalcon\Mvc\Model\Criteria
- Interface Phalcon\Mvc\Model\CriteriaInterface
- Class Phalcon\Mvc\Model\Exception
- Class Phalcon\Mvc\Model\Manager
- Interface Phalcon\Mvc\Model\ManagerInterface
- Class Phalcon\Mvc\Model\Message
- Interface Phalcon\Mvc\Model\MessageInterface
- Abstract class Phalcon\Mvc\Model\MetaData
- Interface Phalcon\Mvc\Model\MetaDataInterface
- Class Phalcon\Mvc\Model\Query
- Interface Phalcon\Mvc\Model\QueryInterface
- Class Phalcon\Mvc\Model\Relation
- Interface Phalcon\Mvc\Model\RelationInterface
- Interface Phalcon\Mvc\Model\ResultInterface
- Abstract class Phalcon\Mvc\Model\Resultset
- Abstract class Phalcon\Mvc\Model\Validator
- Interface Phalcon\Mvc\Model\ResultsetInterface
- Class Phalcon\Mvc\Model\Row
- Class Phalcon\Mvc\Model\Transaction
- Interface Phalcon\Mvc\Model\TransactionInterface
- Class Phalcon\Mvc\Model\ValidationFailed
- Interface Phalcon\Mvc\ModelInterface
- Interface Phalcon\Mvc\ModuleDefinitionInterface
- Class Phalcon\Mvc\Router
- Class Phalcon\Mvc\Router\Annotations
- Class Phalcon\Mvc\Router\Exception
- Class Phalcon\Mvc\Router\Group
- Interface Phalcon\Mvc\Router\GroupInterface
- Class Phalcon\Mvc\Router\Route
- Interface Phalcon\Mvc\Router\RouteInterface
- Interface Phalcon\Mvc\RouterInterface
- Class Phalcon\Mvc\Url
- Class Phalcon\Mvc\Url\Exception
- Interface Phalcon\Mvc\UrlInterface
- Class Phalcon\Mvc\User\Component
- Class Phalcon\Mvc\User\Module
- Class Phalcon\Mvc\User\Plugin
- Class Phalcon\Mvc\View
- Abstract class Phalcon\Mvc\View\Engine
- Interface Phalcon\Mvc\View\EngineInterface
- Class Phalcon\Mvc\View\Exception
- Class Phalcon\Mvc\View\Simple
- Interface Phalcon\Mvc\ViewBaseInterface
- Interface Phalcon\Mvc\ViewInterface
- Abstract class Phalcon\Paginator\Adapter
- Class Phalcon\Paginator\Adapter\Model
- Class Phalcon\Paginator\Adapter\NativeArray
- Class Phalcon\Paginator\Adapter\QueryBuilder
- Interface Phalcon\Paginator\AdapterInterface
- Class Phalcon\Paginator\Exception
- Class Phalcon\Queue\Beanstalk
- Class Phalcon\Queue\Beanstalk\Job
- Final class Phalcon\Registry
- Class Phalcon\Security
- Class Phalcon\Security\Exception
- Abstract class Phalcon\Session
- Abstract class Phalcon\Session\Adapter
- Interface Phalcon\Session\AdapterInterface
- Class Phalcon\Session\Bag
- Interface Phalcon\Session\BagInterface
- Class Phalcon\Session\Exception
- Class Phalcon\Tag
- Class Phalcon\Tag\Exception
- Abstract class Phalcon\Tag\Select
- Abstract class Phalcon\Text
- Abstract class Phalcon\Translate
- Abstract class Phalcon\Translate\Adapter
- Class Phalcon\Translate\Adapter\Csv
- Class Phalcon\Translate\Adapter\Gettext
- Class Phalcon\Translate\Adapter\NativeArray
- Interface Phalcon\Translate\AdapterInterface
- Class Phalcon\Translate\Exception
- Class Phalcon\Validation
- Class Phalcon\Validation\Exception
- Class Phalcon\Validation\Message
- Class Phalcon\Validation\Message\Group
- Interface Phalcon\Validation\MessageInterface
- Abstract class Phalcon\Validation\Validator
- Class Phalcon\Validation\Validator\Alnum
- Class Phalcon\Validation\Validator\Alpha
- Class Phalcon\Validation\Validator\Between
- Class Phalcon\Validation\Validator\Confirmation
- Class Phalcon\Validation\Validator\Digit
- Class Phalcon\Validation\Validator\Email
- Class Phalcon\Validation\Validator\ExclusionIn
- Class Phalcon\Validation\Validator\File
- Class Phalcon\Validation\Validator\Identical
- Class Phalcon\Validation\Validator\InclusionIn
- Class Phalcon\Validation\Validator\Numericality
- Class Phalcon\Validation\Validator\PresenceOf
- Class Phalcon\Validation\Validator\Regex
- Class Phalcon\Validation\Validator\StringLength
- Class Phalcon\Validation\Validator\Uniqueness
- Class Phalcon\Validation\Validator\Url
- Interface Phalcon\Validation\ValidatorInterface
- Class Phalcon\Version
- 参考手册
- 安装(Installation)
- 教程 1:让我们通过例子来学习(Tutorial 1: Let’s learn by example)
- 教程 2:Introducing INVO(Tutorial 2: Introducing INVO)
- 教程 3: Securing INVO
- 教程 4: Using CRUDs
- 教程 5: Customizing INVO
- 教程 6: Vkuró
- 教程 7:创建简单的 REST API(Tutorial 7: Creating a Simple REST API)
- 示例列表(List of examples)
- 依赖注入与服务定位器(Dependency Injection/Service Location)
- MVC 架构(The MVC Architecture)
- 使用控制器(Using Controllers)
- 使用模型(Working with Models)
- 模型元数据(Models Meta-Data)
- 事务管理(Model Transactions)
- Phalcon 查询语言(Phalcon Query Language (PHQL))
- 缓存对象关系映射(Caching in the ORM)
- 对象文档映射 ODM (Object-Document Mapper)
- 使用视图(Using Views)
- 视图助手(View Helpers)
- 资源文件管理(Assets Management)
- Volt 模版引擎(Volt: Template Engine)
- MVC 应用(MVC Applications)
- 路由(Routing)
- 调度控制器(Dispatching Controllers)
- 微应用(Micro Applications)
- 使用命名空间(Working with Namespaces)
- 事件管理器(Events Manager)
- Request Environment
- 返回响应(Returning Responses)
- Cookie 管理(Cookies Management)
- 生成 URL 和 路径(Generating URLs and Paths)
- 闪存消息(Flashing Messages)
- 使用 Session 存储数据(Storing data in Session)
- 过滤与清理(Filtering and Sanitizing)
- 上下文编码(Contextual Escaping)
- 验证(Validation)
- 表单(Forms)
- 读取配置(Reading Configurations)
- 分页(Pagination)
- 使用缓存提高性能(Improving Performance with Cache)
- 安全(Security)
- Encryption/Decryption
- 访问控制列表 ACL(Access Control Lists ACL)
- 多语言支持(Multi-lingual Support)
- Universal Class Loader
- 日志记录(Logging)
- 注释解析器(Annotations Parser)
- 命令行应用(Command Line Applications)
- 队列(Queueing)
- 数据库抽象层(Database Abstraction Layer)
- 国际化(Internationalization)
- 数据库迁移(Database Migrations)
- 调试应用程序(Debugging Applications)
- Phalcon 开发工具(Phalcon Developer Tools)
- 提高性能:下一步该做什么?(Increasing Performance: What’s next?)
- 单元测试(Unit testing)
- 授权(License)