微应用Micro Applications

使用Phalcon框架开发者可以创建微框架应用。 这样开发者只需要书写极少的代码即可创建一个PHP应用。 微应用适用于书写小的应用, API或原型等

With Phalcon you can create “Micro-Framework like” applications. By doing this, you only need to write a minimal amount of code to create a PHP application. Micro applications are suitable to implement small applications, APIs and prototypes in a practical way.

  1. <?php
  2. use Phalcon\Mvc\Micro;
  3. $app = new Micro();
  4. $app->get('/say/welcome/{name}', function ($name) {
  5. echo "<h1>Welcome $name!</h1>";
  6. });
  7. $app->handle();

创建微应用Creating a Micro Application

Phalcon中 使用 :doc:`Phalcon\Mvc\Micro <../api/Phalcon_Mvc_Micro>`来实现微应用。

Phalcon\Mvc\Micro is the class responsible for implementing a micro application.

  1. <?php
  2. use Phalcon\Mvc\Micro;
  3. $app = new Micro();

定义路由Defining routes

实例化后, 开发者需要添加一些路由规则。 Phalcon内部使用 :doc:`Phalcon\Mvc\Router <../api/Phalcon_Mvc_Router>`来管理路由。 路由必须以 / 开头。 定义路由时通常会书写http方法约束, 这样路由规则只适用于那些和规则及htttp方法相匹配的路由。 下面的方法展示了如何定义了HTTP get方法路由:

After instantiating the object, you will need to add some routes. Phalcon\Mvc\Router manages routing internally. Routes must always start with /. A HTTP method constraint is optionally required when defining routes, so as to instruct the router to match only if the request also matches the HTTP methods. The following example shows how to define a route for the method GET:

  1. <?php
  2. $app->get('/say/hello/{name}', function ($name) {
  3. echo "<h1>Hello! $name</h1>";
  4. });

get 方法指定了要匹配的请求方法。 路由规则 /say/hello/{name} 中含有一个参数 {$name}, 此参数会直接传递给路由的处理器(此处为匿名函数)。 路由规则匹配时处理器即会执行。 处理器是PHP中任何可以被调用的项。 下面的示例中展示了如何定义不同种类的处理器:

The “get” method indicates that the associated HTTP method is GET. The route /say/hello/{name} also has a parameter {$name} that is passed directly to the route handler (the anonymous function). Handlers are executed when a route is matched. A handler could be any callable item in the PHP userland. The following example shows how to define different types of handlers:

  1. <?php
  2. // With a function
  3. function say_hello($name) {
  4. echo "<h1>Hello! $name</h1>";
  5. }
  6. $app->get('/say/hello/{name}', "say_hello");
  7. // With a static method
  8. $app->get('/say/hello/{name}', "SomeClass::someSayMethod");
  9. // With a method in an object
  10. $myController = new MyController();
  11. $app->get('/say/hello/{name}', array($myController, "someAction"));
  12. //Anonymous function
  13. $app->get('/say/hello/{name}', function ($name) {
  14. echo "<h1>Hello! $name</h1>";
  15. });

Phalcon\Mvc\Micro 提供了一系列的用于定义http方法的限定方法:

Phalcon\Mvc\Micro provides a set of methods to define the HTTP method (or methods) which the route is constrained for:

  1. <?php
  2. //Matches if the HTTP method is GET
  3. $app->get('/api/products', "get_products");
  4. //Matches if the HTTP method is POST
  5. $app->post('/api/products/add', "add_product");
  6. //Matches if the HTTP method is PUT
  7. $app->put('/api/products/update/{id}', "update_product");
  8. //Matches if the HTTP method is DELETE
  9. $app->delete('/api/products/remove/{id}', "delete_product");
  10. //Matches if the HTTP method is OPTIONS
  11. $app->options('/api/products/info/{id}', "info_product");
  12. //Matches if the HTTP method is PATCH
  13. $app->patch('/api/products/update/{id}', "info_product");
  14. //Matches if the HTTP method is GET or POST
  15. $app->map('/repos/store/refs',"action_product")->via(array('GET', 'POST'));

路由参数Routes with Parameters

如上面的例子中展示的那样在路由中定义参数是非常容易的。 参数名需要放在花括号内。 参数格式亦可使用正则表达式以确保数据一致性。 例子如下:

Defining parameters in routes is very easy as demonstrated above. The name of the parameter has to be enclosed in brackets. Parameter formatting is also available using regular expressions to ensure consistency of data. This is demonstrated in the example below:

  1. <?php
  2. //This route have two parameters and each of them have a format
  3. $app->get('/posts/{year:[0-9]+}/{title:[a-zA-Z\-]+}', function ($year, $title) {
  4. echo "<h1>Title: $title</h1>";
  5. echo "<h2>Year: $year</h2>";
  6. });

起始路由Starting Route

通常情况下, 应用一般由 / 路径开始访问, 当然此访问多为 GET方法。 这种情况代码如下:

Normally, the starting route in an application is the route /, and it will more frequent to be accessed by the method GET. This scenario is coded as follows:

  1. <?php
  2. //This is the start route
  3. $app->get('/', function () {
  4. echo "<h1>Welcome!</h1>";
  5. });

重写规则Rewrite Rules

下面的规则用来实现apache重写:

The following rules can be used together with Apache to rewrite the URis:

  1. <IfModule mod_rewrite.c>
  2. RewriteEngine On
  3. RewriteCond %{REQUEST_FILENAME} !-f
  4. RewriteRule ^(.*)$ index.php?_url=/$1 [QSA,L]
  5. </IfModule>

处理响应Working with Responses

开发者可以在路由处理器中设置任务种类的响应:直接输出, 使用模板引擎, 包含视图, 返回json数据等。

You are free to produce any kind of response in a handler: directly make an output, use a template engine, include a view, return a json, etc.:

  1. <?php
  2. //Direct output
  3. $app->get('/say/hello', function () {
  4. echo "<h1>Hello! $name</h1>";
  5. });
  6. //Requiring another file
  7. $app->get('/show/results', function () {
  8. require 'views/results.php';
  9. });
  10. //Returning a JSON
  11. $app->get('/get/some-json', function () {
  12. echo json_encode(array("some", "important", "data"));
  13. });

另外开发者还可以使用 “response” , 这样开发者可以更好的处理结果:

In addition to that, you have access to the service “response”, with which you can manipulate better the response:

  1. <?php
  2. $app->get('/show/data', function () use ($app) {
  3. //Set the Content-Type header
  4. $app->response->setContentType('text/plain')->sendHeaders();
  5. //Print a file
  6. readfile("data.txt");
  7. });

或回复response对象:

Or create a response object and return it from the handler:

  1. <?php
  2. $app->get('/show/data', function () {
  3. //Create a response
  4. $response = new Phalcon\Http\Response();
  5. //Set the Content-Type header
  6. $response->setContentType('text/plain');
  7. //Pass the content of a file
  8. $response->setContent(file_get_contents("data.txt"));
  9. //Return the response
  10. return $response;
  11. });

重定向Making redirections

重定向用来在当前的处理中跳转到其它的处理流:

Redirections could be performed to forward the execution flow to another route:

  1. <?php
  2. //This route makes a redirection to another route
  3. $app->post('/old/welcome', function () use ($app) {
  4. $app->response->redirect("new/welcome")->sendHeaders();
  5. });
  6. $app->post('/new/welcome', function () use ($app) {
  7. echo 'This is the new Welcome';
  8. });

根据路由生成 URLGenerating URLs for Routes

Phalcon中使用 Phalcon\Mvc\Url 来生成其它的基于路由的URL。 开发者可以为路由设置名字, 通过这种方式 “url” 服务可以产生相关的路由:

Phalcon\Mvc\Url can be used to produce URLs based on the defined routes. You need to set up a name for the route; by this way the “url” service can produce the corresponding URL:

  1. <?php
  2. //Set a route with the name "show-post"
  3. $app->get('/blog/{year}/{title}', function ($year, $title) use ($app) {
  4. //.. show the post here
  5. })->setName('show-post');
  6. //produce an URL somewhere
  7. $app->get('/', function() use ($app) {
  8. echo '<a href="', $app->url->get(array(
  9. 'for' => 'show-post',
  10. 'title' => 'php-is-a-great-framework',
  11. 'year' => 2012
  12. )), '">Show the post</a>';
  13. });

与依赖注入的交互Interacting with the Dependency Injector

微应用中, Phalcon\DI\FactoryDefault 是隐含生成的, 不过开发者可以明确的生成此类的实例以用来管理相关的服务:

In the micro application, a Phalcon\DI\FactoryDefault services container is created implicitly; additionally you can create outside the application a container to manipulate its services:

  1. <?php
  2. use Phalcon\Mvc\Micro;
  3. use Phalcon\DI\FactoryDefault;
  4. use Phalcon\Config\Adapter\Ini as IniConfig;
  5. $di = new FactoryDefault();
  6. $di->set('config', function() {
  7. return new IniConfig("config.ini");
  8. });
  9. $app = new Micro();
  10. $app->setDI($di);
  11. $app->get('/', function () use ($app) {
  12. //Read a setting from the config
  13. echo $app->config->app_name;
  14. });
  15. $app->post('/contact', function () use ($app) {
  16. $app->flash->success('Yes!, the contact was made!');
  17. });

服务容器中可以使用数据类的语法来设置或取服务实例:

The array-syntax is allowed to easily set/get services in the internal services container:

  1. <?php
  2. use Phalcon\Mvc\Micro;
  3. use Phalcon\Db\Adapter\Pdo\Mysql as MysqlAdapter;
  4. $app = new Micro();
  5. //Setup the database service
  6. $app['db'] = function() {
  7. return new MysqlAdapter(array(
  8. "host" => "localhost",
  9. "username" => "root",
  10. "password" => "secret",
  11. "dbname" => "test_db"
  12. ));
  13. };
  14. $app->get('/blog', function () use ($app) {
  15. $news = $app['db']->query('SELECT * FROM news');
  16. foreach ($news as $new) {
  17. echo $new->title;
  18. }
  19. });

处理Not-FoundNot-Found Handler

当用户访问未定义的路由时, 微应用会试着执行 “Not-Found”处理器。 示例如下:

When an user tries to access a route that is not defined, the micro application will try to execute the “Not-Found” handler. An example of that behavior is below:

  1. <?php
  2. $app->notFound(function () use ($app) {
  3. $app->response->setStatusCode(404, "Not Found")->sendHeaders();
  4. echo 'This is crazy, but this page was not found!';
  5. });

微应用中的模型Models in Micro Applications

Phalcon中开发者可以直接使用 Models , 开发者只需要一个类自动加载器来加载模型:

Models can be used transparently in Micro Applications, only is required an autoloader to load models:

  1. <?php
  2. $loader = new \Phalcon\Loader();
  3. $loader->registerDirs(array(
  4. __DIR__ . '/models/'
  5. ))->register();
  6. $app = new \Phalcon\Mvc\Micro();
  7. $app->get('/products/find', function(){
  8. foreach (Products::find() as $product) {
  9. echo $product->name, '<br>';
  10. }
  11. });
  12. $app->handle();

微应用中的事件Micro Application Events

当有事件发生时 Phalcon\Mvc\Micro 会发送事件到 EventsManager 。 这里使用 “micro” 来绑定处理事件。 支持如下事件:

Phalcon\Mvc\Micro is able to send events to the EventsManager (if it is present). Events are triggered using the type “micro”. The following events are supported:

Event NameTriggeredCan stop operation?
beforeHandleRouteThe main method is just called, at this point the application doesn’t know if there is some matched routeYes
beforeExecuteRouteA route has been matched and it contains a valid handler, at this point the handler has not been executedYes
afterExecuteRouteTriggered after running the handlerNo
beforeNotFoundTriggered when any of the defined routes match the requested URIYes
afterHandleRouteTriggered after completing the whole process in a successful wayYes

下面的例子中, 我们阐述了如何使用事件来控制应用的安全性:

In the following example, we explain how to control the application security using events:

  1. <?php
  2. use Phalcon\Mvc\Micro,
  3. Phalcon\Events\Manager as EventsManager;
  4. //Create a events manager
  5. $eventManager = new EventsManager();
  6. //Listen all the application events
  7. $eventManager->attach('micro', function($event, $app) {
  8. if ($event->getType() == 'beforeExecuteRoute') {
  9. if ($app->session->get('auth') == false) {
  10. $app->flashSession->error("The user isn't authenticated");
  11. $app->response->redirect("/")->sendHeaders();
  12. //Return (false) stop the operation
  13. return false;
  14. }
  15. }
  16. });
  17. $app = new Micro();
  18. //Bind the events manager to the app
  19. $app->setEventsManager($eventManager);

中间件事件Middleware events

此外, 应用事件亦可使用 ‘before’, ‘after’, ‘finish’等来绑定:

In addition to the events manager, events can be added using the methods ‘before’, ‘after’ and ‘finish’:

  1. <?php
  2. $app = new Phalcon\Mvc\Micro();
  3. //Executed before every route is executed
  4. //Return false cancels the route execution
  5. $app->before(function() use ($app) {
  6. if ($app['session']->get('auth') == false) {
  7. return false;
  8. }
  9. return true;
  10. });
  11. $app->map('/api/robots', function(){
  12. return array(
  13. 'status' => 'OK'
  14. );
  15. });
  16. $app->after(function() use ($app) {
  17. //This is executed after the route was executed
  18. echo json_encode($app->getReturnedValue());
  19. });
  20. $app->finish(function() use ($app) {
  21. //This is executed when the request has been served
  22. });

开发者可以对同一事件注册多个处理器:

You can call the methods several times to add more events of the same type:

  1. <?php
  2. $app->finish(function() use ($app) {
  3. //First 'finish' middleware
  4. });
  5. $app->finish(function() use ($app) {
  6. //Second 'finish' middleware
  7. });

把这些代码放在另外的文件中以达到重用的目的:

Code for middlewares can be reused using separate classes:

  1. <?php
  2. use Phalcon\Mvc\Micro\MiddlewareInterface;
  3. /**
  4. * CacheMiddleware
  5. *
  6. * Caches pages to reduce processing
  7. */
  8. class CacheMiddleware implements MiddlewareInterface
  9. {
  10. public function call($application)
  11. {
  12. $cache = $application['cache'];
  13. $router = $application['router'];
  14. $key = preg_replace('/^[a-zA-Z0-9]/', '', $router->getRewriteUri());
  15. //Check if the request is cached
  16. if ($cache->exists($key)) {
  17. echo $cache->get($key);
  18. return false;
  19. }
  20. return true;
  21. }
  22. }

添加实例到应用:

Then add the instance to the application:

  1. <?php
  2. $app->before(new CacheMiddleware());

支持如下的中间件事件

The following middleware events are available:

Event NameTriggeredCan stop operation?
beforeBefore executing the handler. It can be used to control the access to the applicationYes
afterExecuted after the handler is executed. It can be used to prepare the responseNo
finishExecuted after sending the response. It can be used to perform clean-upNo

使用控制器处理Using Controllers as Handlers

中型的应用可以使用 Micro\MVC 来组织控制器中的处理器。 开发者也可以使用 :doc:`Phalcon\Mvc\Micro\Collection <../api/Phalcon_Mvc_Micro_Collection>`来对控制器中的处理器进行归组:

Medium applications using the Micro\MVC approach may require organize handlers in controllers. You can use Phalcon\Mvc\Micro\Collection to group handlers that belongs to controllers:

  1. <?php
  2. use Phalcon\Mvc\Micro\Collection as MicroCollection;
  3. $posts = new MicroCollection();
  4. //Set the main handler. ie. a controller instance
  5. $posts->setHandler(new PostsController());
  6. //Set a common prefix for all routes
  7. $posts->setPrefix('/posts');
  8. //Use the method 'index' in PostsController
  9. $posts->get('/', 'index');
  10. //Use the method 'show' in PostsController
  11. $posts->get('/show/{slug}', 'show');
  12. $app->mount($posts);

PostsController形如下:

The controller ‘PostsController’ might look like this:

  1. <?php
  2. use Phalcon\Mvc\Controller;
  3. class PostsController extends Controller
  4. {
  5. public function index()
  6. {
  7. //...
  8. }
  9. public function show($slug)
  10. {
  11. //...
  12. }
  13. }

上面的例子中,我们直接对控制器进行了实例化, 使用集合时Phalcon会提供了迟加载的能力, 这样程序只有在匹配路由时才加载控制器:

In the above example the controller is directly instantiated, Collection also have the ability to lazy-load controllers, this option provide better performance loading controllers only if the related routes are matched:

  1. <?php
  2. $posts->setHandler('PostsController', true);
  3. $posts->setHandler('Blog\Controllers\PostsController', true);

返回响应Returning Responses

处理器可能会返回原生的 Phalcon\Http\Response 实例或实现了相关接口的组件。 当返回Response对象时, 应用会自动的把处理结果返回到客户端。

Handlers may return raw responses using Phalcon\Http\Response or a component that implements the relevant interface. When responses are returned by handlers they are automatically sent by the application.

  1. <?php
  2. use Phalcon\Mvc\Micro;
  3. use Phalcon\Http\Response;
  4. $app = new Micro();
  5. //Return a response
  6. $app->get('/welcome/index', function() {
  7. $response = new Response();
  8. $response->setStatusCode(401, "Unauthorized");
  9. $response->setContent("Access is not authorized");
  10. return $response;
  11. });

渲染视图Rendering Views

:doc:`Phalcon\Mvc\View\Simple <views>`可用来渲染视图, 示例如下:

Phalcon\Mvc\View\Simple can be used to render views, the following example shows how to do that:

  1. <?php
  2. $app = new Phalcon\Mvc\Micro();
  3. $app['view'] = function() {
  4. $view = new \Phalcon\Mvc\View\Simple();
  5. $view->setViewsDir('app/views/');
  6. return $view;
  7. };
  8. //Return a rendered view
  9. $app->get('/products/show', function() use ($app) {
  10. // Render app/views/products/show.phtml passing some variables
  11. echo $app['view']->render('products/show', array(
  12. 'id' => 100,
  13. 'name' => 'Artichoke'
  14. ));
  15. });

错误处理Error Handling

在微应用中异常被抛出的时候可以产生一个合适的返回:

A proper response can be generated if an exception is raised in a micro handler:

  1. <?php
  2. $app = new Phalcon\Mvc\Micro();
  3. $app->get('/', function() {
  4. throw new \Exception("An error");
  5. });
  6. $app->error(function($exception) {
  7. echo "An error has occurred";
  8. });

如果返回false则异常处理终止。

If the handler returns “false” the exception is stopped.

相关资源Related Sources