教程:让我们通过例子来学习(Tutorial: Let’s learn by example)

通过这第一个教程,我们将引导您从基础完成创建简单的带有注册表单的应用。我们也将解释框架行为的基本方面。如果您对Phalcon的自动代码生成工具有兴趣,您可以查看 developer tools

确认安装(Checking your installation)

我们假设你已经安装了Phalcon。请检查你的phpinfo()输出了一个”Phalcon”部分引用或者执行以下代码片段:

  1. <?php print_r(get_loaded_extensions()); ?>

Phalcon 拓展应该作为输出的一部分出现:

  1. Array
  2. (
  3. [0] => Core
  4. [1] => libxml
  5. [2] => filter
  6. [3] => SPL
  7. [4] => standard
  8. [5] => phalcon
  9. [6] => pdo_mysql
  10. )

创建项目(Creating a project)

使用本指南的最好方法就是依次按照每一步来做。

文件结构(File structure)

Phalcon不会强制要求应用程序的开发遵循特定的文件结构。因为它是松散耦合的,你可以实现Phalcon驱动的应用程序,以及使用对你来说最舒服的文件结构。

本教程的目的以此为起点,我们建议使用以下结构:

  1. tutorial/
  2. app/
  3. controllers/
  4. models/
  5. views/
  6. public/
  7. css/
  8. img/
  9. js/

需要注意的是,你不需要任何有关Phalcon的 “library” 目录。该框架已经被加载到内存中,供您使用。

优美的 URL(Beautiful URLs)

在本教程中,我们将使用相当(友好)URL。友好的URL不但利于SEO而且便于用户记忆。Phalcon支持一些最流行的Web服务器提供重写模块。让你的应用程序的URL友好不是必要的,没有它们你可以同样轻松地开发。

在这个例子中,我们将使用Apache的重写模块。让我们在 /tutorial/.htaccess 文件中创建几个重写规则:

  1. #/tutorial/.htaccess
  2. <IfModule mod_rewrite.c>
  3. RewriteEngine on
  4. RewriteRule ^$ public/ [L]
  5. RewriteRule ((?s).*) public/$1 [L]
  6. </IfModule>

对该项目的所有请求都将被重定向到为public/文档根目录。此步骤可确保内部项目的文件夹仍然对公共访客隐藏,从而消除了一些安全威胁。

第二组规则将检查是否存在所请求的文件,如果存在所要请求的文件,就不需要Web服务器模块来重写:

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

引导程序(Bootstrap)

你需要创建的第一个文件是引导文件。这个文件很重要,因为它作为你的应用程序的基础,用它来控制应用程序的各个方面。在这个文件中,你可以实现组件的初始化和应用程序的行为。

这个引导文件 tutorial/public/index.php 文件应该看起来像:

  1. <?php
  2.  
  3. try {
  4.  
  5. // Register an autoloader
  6. $loader = new Phalcon\Loader();
  7. $loader->registerDirs(array(
  8. '../app/controllers/',
  9. '../app/models/'
  10. ))->register();
  11.  
  12. // Create a DI
  13. $di = new Phalcon\Di\FactoryDefault();
  14.  
  15. // Setup the view component
  16. $di->set('view', function () {
  17. $view = new Phalcon\Mvc\View();
  18. $view->setViewsDir('../app/views/');
  19. return $view;
  20. });
  21.  
  22. // Setup a base URI so that all generated URIs include the "tutorial" folder
  23. $di->set('url', function () {
  24. $url = new Phalcon\Mvc\Url();
  25. $url->setBaseUri('/tutorial/');
  26. return $url;
  27. });
  28.  
  29. // Handle the request
  30. $application = new Phalcon\Mvc\Application();
  31.  
  32. echo $application->handle()->getContent();
  33.  
  34. } catch (\Exception $e) {
  35. echo "Exception: ", $e->getMessage();
  36. }

自动加载(Autoloaders)

我们可以看出,引导程序的第一部分是注册一个自动加载器。在这个应用程序里,它将用于加载控制器和模型类。例如,我们可以为控制器注册一个或多个目录来增加应用程序的灵活性的。在我们的例子中,我们使用了 Phalcon\Loader 组件。

有了它,我们可以加载使用各种策略类,但在这个例子中,我们选择了在预定义的目录中查找类:

  1. <?php
  2.  
  3. // ...
  4.  
  5. $loader = new Phalcon\Loader();
  6. $loader->registerDirs(
  7. array(
  8. '../app/controllers/',
  9. '../app/models/'
  10. )
  11. )->register();

依赖管理(Dependency Management)

在使用Phalcon时必须理解的一个非常重要的概念是 依赖注入容器(dependency injection container). 这听起来复杂,但实际上非常简单实用。

服务容器是一个全局存储的将要被使用的应用程序功能包。每次框架需要的一个组件时,会请求这个使用协定好名称的服务容器。因为Phalcon是一个高度解耦的框架, Phalcon\Di 作为黏合剂,促使不同组件的集成,以一个透明的方式实现他们一起进行工作。

  1. <?php
  2.  
  3. // ...
  4.  
  5. // Create a DI
  6. $di = new Phalcon\Db\Adapter\Pdo\Mysql();

Phalcon\Di\FactoryDefaultPhalcon\Di 的一个变体。为了让事情变得更容易,它已注册了Phalcon的大多数组件。因此,我们不需要一个一个注册这些组件。在以后更换工厂服务的时候也不会有什么问题。

在接下来的部分,我们注册了“视图(view)”服务,指示框架将去指定的目录寻找视图文件。由于视图并非PHP类,它们不能被自动加载器加载。

服务可以通过多种方式进行登记,但在我们的教程中,我们将使用一个匿名函数 anonymous function:

  1. <?php
  2.  
  3. // ...
  4.  
  5. // Setup the view component
  6. $di->set('view', function () {
  7. $view = new Phalcon\Mvc\View();
  8. $view->setViewsDir('../app/views/');
  9. return $view;
  10. });

接下来,我们注册一个基础URI,这样通过Phalcon生成包括我们之前设置的“tutorial”文件夹在内的所有的URI。我们使用类 Phalcon\Tag 生成超链接,这将在本教程后续部分很重要。

  1. <?php
  2.  
  3. // ...
  4.  
  5. // Setup a base URI so that all generated URIs include the "tutorial" folder
  6. $di->set('url', function () {
  7. $url = new Phalcon\Mvc\Url();
  8. $url->setBaseUri('/tutorial/');
  9. return $url;
  10. });

在这个文件的最后部分,我们发现 Phalcon\Mvc\Application。其目的是初始化请求环境,并接收路由到来的请求,接着分发任何发现的动作;收集所有的响应,并在过程完成后返回它们。

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

正如你所看到的,引导文件很短,我们并不需要引入任何其他文件。在不到30行的代码里,我们已经为自己设定一个灵活的MVC应用程序。

创建控制器(Creating a Controller)

默认情况下Phalcon会寻找一个名为“Index”的控制器。当请求中没有控制器或动作时,则使用“Index”控制器作为起点。这个“Index”控制器 (app/controllers/IndexController.php) 看起来类似:

  1. <?php
  2.  
  3. use Phalcon\Mvc\Controller;
  4.  
  5. class IndexController extends Controller
  6. {
  7.  
  8. public function indexAction()
  9. {
  10. echo "<h1>Hello!</h1>";
  11. }
  12. }

该控制器类必须有“Controller”后缀,且控制器动作必须有“Action”后缀。如果你从浏览器访问应用程序,你应该看到这样的事情:
教程:让我们通过例子来学习(Tutorial: Let’s learn by example) - 图1
恭喜, 让Phalcon带你飞!

输出到视图(Sending output to a view)

从控制器发送输出到屏幕上有时是必要的,但是在MVC社区,大多数纯粹主义者证明这样做不可取。一切必须传递给视图,视图负责在屏幕上输出数据。Phalcon将在最后执行的控制器的同名目录中,查找最后执行的动作的同名的视图。在我们的例子 (app/views/index/index.phtml) :

  1. <?php echo "<h1>Hello!</h1>";

我们的控制器 (app/controllers/IndexController.php) 现在定义了一个空的动作:

  1. <?php
  2.  
  3. use Phalcon\Mvc\Controller;
  4.  
  5. class IndexController extends Controller
  6. {
  7.  
  8. public function indexAction()
  9. {
  10.  
  11. }
  12. }

浏览器输出应该保持不变。当这个动作已经执行结束 Phalcon\Mvc\View 静态组件会自动创建。学习更多关于 视图使用教程

设计注册表单(Designing a sign up form)

现在我们将改变 index.phtml视图文件,添加一个链接到一个名为“signup”的新控制器。我们的目标是在应用程序中允许用户注册。

  1. <?php
  2.  
  3. echo "<h1>Hello!</h1>";
  4.  
  5. echo $this->tag->linkTo("signup", "Sign Up Here!");

生成的HTML代码显示一个锚 (“a”) HTML标签链接到一个新的控制器:

  1. <h1>Hello!</h1> <a href="/tutorial/signup">Sign Up Here!</a>

我们使用类 Phalcon\Tag 去生成标记。 这是一个让我们构建HTML标记的实用类。 关于生成HTML更详细的文章可以查看 视图助手
教程:让我们通过例子来学习(Tutorial: Let’s learn by example) - 图2
这是一个注册控制器(app/controllers/SignupController.php):

  1. <?php
  2.  
  3. use Phalcon\Mvc\Controller;
  4.  
  5. class SignupController extends Controller
  6. {
  7.  
  8. public function indexAction()
  9. {
  10.  
  11. }
  12. }

这个空index动作整洁的传递了表单定义给一个视图(app/views/signup/index.phtml):

  1. <h2>Sign up using this form</h2>
  2.  
  3. <?php echo $this->tag->form("signup/register"); ?>
  4.  
  5. <p>
  6. <label for="name">Name</label>
  7. <?php echo $this->tag->textField("name") ?>
  8. </p>
  9.  
  10. <p>
  11. <label for="email">E-Mail</label>
  12. <?php echo $this->tag->textField("email") ?>
  13. </p>
  14.  
  15. <p>
  16. <?php echo $this->tag->submitButton("Register") ?>
  17. </p>
  18.  
  19. </form>

在浏览器中查看表单将显示类似的页面:
教程:让我们通过例子来学习(Tutorial: Let’s learn by example) - 图3
Phalcon\Tag 还提供了有用的方法来构建表单元素。

Phalcon\Tag::form() 方法第一个参数,它是一个相对uri到这个应用的一个控制器/动作。

通过单击“Send”按钮,您将注意到框架抛出了一个异常,这表明我们是错过了在控制器中注册“register”动作。我们的 public/index.php 文件抛出这个异常:

Exception: Action “register” was not found on handler “signup”

实现该方法将移除异常:

  1. <?php
  2.  
  3. use Phalcon\Mvc\Controller;
  4.  
  5. class SignupController extends Controller
  6. {
  7.  
  8. public function indexAction()
  9. {
  10.  
  11. }
  12.  
  13. public function registerAction()
  14. {
  15.  
  16. }
  17. }

如果你再点击“Send”按钮,您将看到一个空白页。提供的名称和电子邮件的输入的这个用户应该被存储在数据库中。根据MVC的指导方针,必须通过数据库交互模型,确保整洁的面向对象的代码。

创建模型(Creating a Model)

Phalcon带来的第一个完全用C语言编写的PHP ORM。它简化了开发, 而不是增加了开发的复杂性。

创建我们的第一个模型之前,我们需要在Phalcon以外创建一个数据库表。一个用来存储注册用户的简单表,可以这样定义:

  1. CREATE TABLE `users` (
  2. `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  3. `name` varchar(70) NOT NULL,
  4. `email` varchar(70) NOT NULL,
  5. PRIMARY KEY (`id`)
  6. );

模型应该位于 app/models 目录 (app/models/Users.php). 这个模型对应“users”表:

  1. <?php
  2.  
  3. use Phalcon\Mvc\Model;
  4.  
  5. class Users extends Model
  6. {
  7. public $id;
  8.  
  9. public $name;
  10.  
  11. public $email;
  12. }

设置数据库连接(Setting a Database Connection)

为了能够使用一个数据库连接,然后通过我们的模型访问数据,我们需要在我们的引导过程指定它。数据库连接是我们的应用程序可以使用的数个组件中的另一个服务:

  1. <?php
  2.  
  3. use Phalcon\Loader;
  4. use Phalcon\Di\FactoryDefault;
  5. use Phalcon\Mvc\View;
  6. use Phalcon\Mvc\Application;
  7. use Phalcon\Mvc\Url as UrlProvider;
  8. use Phalcon\Db\Adapter\Pdo\Mysql as DbAdapter;
  9.  
  10. try {
  11.  
  12. // Register an autoloader
  13. $loader = new Loader();
  14. $loader->registerDirs(array(
  15. '../app/controllers/',
  16. '../app/models/'
  17. ))->register();
  18.  
  19. // Create a DI
  20. $di = new FactoryDefault();
  21.  
  22. // Setup the database service
  23. $di->set('db', function () {
  24. return new DbAdapter(array(
  25. "host" => "localhost",
  26. "username" => "root",
  27. "password" => "secret",
  28. "dbname" => "test_db"
  29. ));
  30. });
  31.  
  32. // Setup the view component
  33. $di->set('view', function () {
  34. $view = new View();
  35. $view->setViewsDir('../app/views/');
  36. return $view;
  37. });
  38.  
  39. // Setup a base URI so that all generated URIs include the "tutorial" folder
  40. $di->set('url', function () {
  41. $url = new UrlProvider();
  42. $url->setBaseUri('/tutorial/');
  43. return $url;
  44. });
  45.  
  46. // Handle the request
  47. $application = new Application($di);
  48.  
  49. echo $application->handle()->getContent();
  50.  
  51. } catch (\Exception $e) {
  52. echo "Exception: ", $e->getMessage();
  53. }

使用正确的数据库参数,我们的模型已经准备和应用程序的其余部分工作。

使用模型保存数据(Storing data using models)

下一个步骤是从表单接收数据存储在表中。

  1. <?php
  2.  
  3. use Phalcon\Mvc\Controller;
  4.  
  5. class SignupController extends Controller
  6. {
  7.  
  8. public function indexAction()
  9. {
  10.  
  11. }
  12.  
  13. public function registerAction()
  14. {
  15.  
  16. $user = new Users();
  17.  
  18. // Store and check for errors
  19. $success = $user->save($this->request->getPost(), array('name', 'email'));
  20.  
  21. if ($success) {
  22. echo "Thanks for registering!";
  23. } else {
  24. echo "Sorry, the following problems were generated: ";
  25. foreach ($user->getMessages() as $message) {
  26. echo $message->getMessage(), "<br/>";
  27. }
  28. }
  29.  
  30. $this->view->disable();
  31. }
  32. }

然后我们实例化用户类,它对应于一个用户记录。类的公共属性映射到用户表中的记录的字段。在新记录中设置相应的值并调用save()将在数据库中存储的数据记录。save()方法返回一个布尔值,表示存储的数据是否成功。

ORM自动转义输入以防止SQL注入,所以我们只需要将请求传递给save()方法。

附加的自动验证会验证字段定义为not null(必需)。如果我们不输入任何必需的注册表单中的字段,我们的屏幕将会看起来像这样:
教程:让我们通过例子来学习(Tutorial: Let’s learn by example) - 图4

结束语(Conclusion)

这是一个非常简单的教程,正如你所看到的,使用Phalcon很容易开始构建应用程序。Phalcon是一个在你的web服务器上没有干扰、易于开发、特性优良的扩展。我们邀请你继续阅读手册,这样你就可以发现Phalcon提供的附加功能!

原文: http://www.myleftstudio.com/reference/tutorial.html