教程 2:INVO简介(Tutorial 2: Introducing INVO)

在第二部分,我们将会说明一个完整的应用用来加深Phalcon的开发。 INVO是我们创建的一个程序样本。INVO是一个简单的用来允许用户生成发票的网站,并且可以做其他的任务,比如管理他们的客户或者产品。你可以从 Github 中复制它的代码。

同样,INVO使用 Bootstrap 做的前端框架。虽然这个应用不能生成发票,但是它仍然可以作为一个例子来理解框架是如何工作的。

项目结构(Project Structure)

一旦你从你的文档根目录复制了这个项目,你将会看到以下结构:

  1. invo/
  2. app/
  3. config/
  4. controllers/
  5. forms/
  6. library/
  7. logs/
  8. models/
  9. plugins/
  10. views/
  11. cache/
  12. volt/
  13. docs/
  14. public/
  15. css/
  16. fonts/
  17. js/
  18. schemas/

正如你所知道的,Phalcon不会强求应用程序使用特定的文件结构。 这个项目提供了一个简单的MVC模型和公共文档根目录。

一旦你打开浏览器输入 http://localhost/invo 浏览应用程序你将会看到下面这样:

../_images/invo-1.png

这个应用分为两部分,一部分是前端,这个是一个公开的部分,浏览者可以接收关于INVO的信息,也可以请求联系人信息。第二部分是后端,一个管理员区域,一个注册用户可以管理他/她的产品和客户。

路由(Routing)

INVO使用内置的标准路由. Router 组件. 路由符合以下格式:/:controller/:action/:params. 这就意味着第一部分URI是控制器,第二部分是方法,剩余的是参数。

下面的路由 /session/register 执行的是 SessionController 控制器和它的 registerAction方法。

配置(Configuration)

INVO有一个设置应用常规参数的配置文件。这个文件位于 app/config/config.ini,并且他在应用引导文件的最开始就开始加载 (public/index.php):

  1. <?php
  2. use Phalcon\Config\Adapter\Ini as ConfigIni;
  3. // ...
  4. // 读取配置
  5. $config = new ConfigIni(
  6. APP_PATH . "app/config/config.ini"
  7. );

Phalcon\Config 允许我们使用面向对象的方式来操作文件。在这个例子中,我们使用ini文件作为配置文件,然而,它对于配置文件有更多的适配支持。这个配置文件包含以下配置:

  1. [database]
  2. host = localhost
  3. username = root
  4. password = secret
  5. name = invo
  6. [application]
  7. controllersDir = app/controllers/
  8. modelsDir = app/models/
  9. viewsDir = app/views/
  10. pluginsDir = app/plugins/
  11. formsDir = app/forms/
  12. libraryDir = app/library/
  13. baseUri = /invo/

Phalcon没有任何提前预约好的惯例配置。节帮助我们组织相应选项. 在这个文件里面有两个部分被用于后面的”application” 和 “database”.

自动加载(Autoloaders)

在启动文件(public/index.php)的第二部分是自动加载器:

  1. <?php
  2. /**
  3. * 自动加载配置
  4. */
  5. require APP_PATH . "app/config/loader.php";

The autoloader registers a set of directories in which the application will look for the classes that it eventually will need.

  1. <?php
  2. $loader = new Phalcon\Loader();
  3. // We're a registering a set of directories taken from the configuration file
  4. $loader->registerDirs(
  5. [
  6. APP_PATH . $config->application->controllersDir,
  7. APP_PATH . $config->application->pluginsDir,
  8. APP_PATH . $config->application->libraryDir,
  9. APP_PATH . $config->application->modelsDir,
  10. APP_PATH . $config->application->formsDir,
  11. ]
  12. );
  13. $loader->register();

注意, 以上代码注册的目录是在配置文件中定义的. 唯一没有注册的目录是viewsDir, 因为它包含 HTML + PHP 文件但不是类. 同时, 也要注意我们使用了常量 APP_PATH, 这个常量在引导文件(public/index.php)中被定义, 允许我们对我们项目的根路径有一个参考:

  1. <?php
  2. // ...
  3. define(
  4. "APP_PATH",
  5. realpath("..") . "/"
  6. );

注册服务(Registering services)

在引导文件中加载的另外一个文件是 (app/config/services.php). 这个文件允许我们组织 INVO 不需要的文件.

  1. <?php
  2. /**
  3. * 加载应用服务
  4. */
  5. require APP_PATH . "app/config/services.php";

服务注册已经在前面的教程中实现了, 利用一个闭包来实现惰性加载组件:

  1. <?php
  2. use Phalcon\Mvc\Url as UrlProvider;
  3. // ...
  4. /**
  5. * URL组件被用来生成应用中的各种URL
  6. */
  7. $di->set(
  8. "url",
  9. function () use ($config) {
  10. $url = new UrlProvider();
  11. $url->setBaseUri(
  12. $config->application->baseUri
  13. );
  14. return $url;
  15. }
  16. );

稍后我们将会深入讨论这个文件.

处理请求(Handling the Request)

如果我们忽略文件(public/index.php)的结束, 请求最终会被 Phalcon\Mvc\Application 处理, 初始化并运行所有必须的代码来让程序执行:

  1. <?php
  2. use Phalcon\Mvc\Application;
  3. // ...
  4. $application = new Application($di);
  5. $response = $application->handle();
  6. $response->send();

依赖注入(Dependency Injection)

看上面代码的第一行, Application 类的构造方法接受一个 $di 变量作为一个参数. 这个变量的用意是什么呢? Phalcon 是一个高度解耦的框架, 所以我们一个组件来充当胶水来让每个组件都能正常工作. 这个组件就是 Phalcon\Di. 这是一个服务容器, 可以执行依赖注入和服务定位, 实例化应用所需要的所有组件.

在容器中有多种注册服务的方法. 在INVO里, 大部分服务使用匿名函数或者闭包来进行注册的. 多亏了这个, 对象以惰性的方式被实例化, 减少了应用程序所需要的资源.

例如, 下面摘录了 Session 服务的注册. 当应用程序需要访问Session数据的时候, 匿名函数才会被调用:

  1. <?php
  2. use Phalcon\Session\Adapter\Files as Session;
  3. // ...
  4. // 在一个组件请求Session服务的时候, 启动Sesssion
  5. $di->set(
  6. "session",
  7. function () {
  8. $session = new Session();
  9. $session->start();
  10. return $session;
  11. }
  12. );

这里, 我们可以自动的更改适配器, 执行额外的初始化或者更多. 注意, 这个服务器是使用 “session” 名字进行注册的. 这是一个惯例, 来允许框架在服务容器中识别正在活动的服务.

一个请求可以使用多个服务和单独注册每个服务可以说是一个繁重的任务. 因此, 框架提供了 Phalcon\Di 的一个变种, 称作 Phalcon\Di\FactoryDefault 其任务是注册所有的服务来提供一个全栈框架.

  1. <?php
  2. use Phalcon\Di\FactoryDefault;
  3. // ...
  4. // FactoryDefault 依赖注入自动注册了正确的服务来提供了一个全栈框架
  5. $di = new FactoryDefault();

它通过框架注册大部分组件服务作为标准提供. 如果我们需要重写某些已经定义的服务, 我们仅仅需要重新定义它, 就像上面的 “session” 和 “url”一样. 这就是变量 $di 存在的原因.

在下一章, 我们将会看到如何在INVO中实施认证和授权.