The example in this article describes how to create a page with Symfony2. Share it with everyone for your reference, the details are as follows:
Creating a page in Symfony2 only requires two steps:
1. Create a route: The route defines the URI of your page (such as /about) and specifies it The controller (PHP function) to execute. When the incoming request URL matches this route, Symfony2 will execute the specified controller;
2. Create a controller: The controller is a PHP function that accepts the incoming request and converts it into Symfony2 Response object.
We like this simple implementation because it fits the way the web works. Every web interaction begins with an HTTP request, and it is the application's job to simply interpret the request and return a corresponding HTTP response. Symfony2 follows this principle and provides you with the tools to ensure that your application remains well organized as its users and complexity grow.
“Hello Symfony2” Page
Let’s start with the classic “hello, world” program. When we’re done, the user can get a hello by visiting the following URL:
http://localhost/app_dev.php/hello/Symfony
Actually, you can change Symfony to another name for greetings. To create this page, we only need to follow two simple steps:
This tutorial has assumed that you have downloaded Symfony2 and configured the web server. The above URL assumes localhost points to your new Symfony2 project. For installation details, see Installing Symfony2.
Create a Bundle
Before you begin, you need to create a Bundle. In Symfony2, Bundle is equivalent to a plug-in, and all code in your application needs to be placed in Bundle. A Bundle is just a directory (with a PHP namespace) whose contents are related to a specific function (see Bundle system). Run the following command to create the AcmeStudyBundle (the game built in this chapter).
php app/console Acme/StudyBundle[/]
Next, the following statements were added to the app/autoloader.php file to ensure that the Acme namespace is bootstrapped (see the Autoloading chapter):
$loader->registerNamespaces(array( 'Acme' => __DIR__.'/../src', // ... ));
Finally initialize the Bundle in the registerBundles() method of the app/AppKernel.php file.
// app/AppKernel.php public function registerBundles() { $bundles = array( // ... new Acme\StudyBundle\AcmeStudyBundle(), ); // ... return $bundles; }
Now that you have set up your Bundle, you can build your application in your Bundle.
Create routing
By default, the routing configuration file of Symfony2 is placed in the app/config/routing.yml directory. All configuration files in Symfony2 can also be written in PHP or XML format.
# app/config/routing.yml homepage: pattern: / defaults: { _controller: FrameworkBundle:Default:index } hello: resource: "@AcmeStudyBundle/Resources/config/routing.yml"
The first few lines of the routing configuration file define the code called by the user to request the "/" (home page) resource. What is more interesting is the last part. Imported other routing configuration files located in AcmeStudyBundle.
# src/Acme/StudyBundle/Resources/config/routing.yml hello: pattern: /hello/{name} defaults: { _controller: AcmeStudyBundle:Hello:index }
Routing consists of two basic parts. The pattern determines which URI matches this route, and the defaults array specifies the controller to run. The placeholder {name} in pattern is a wildcard, which indicates that a URI such as /hello/Ryan, /hello/Fabien or other similar matches this route. The {name} placeholder parameter is also sent to the controller so that we can use its value to greet the user.
The routing system has many amazing functions in creating powerful and flexible URL structures for applications. For details, please refer to "Symfony2 Study Notes: Detailed Explanation of System Routing"
Creating Controllers
When a URI like /hello/Ryan is processed by the application, the hello route is matched and the AcmeStudyBundle:Hello:index controller is executed through the Symfony2 framework. The second step in the process of creating the page is to create this controller
In fact, the controller is nothing more than a PHP function that you create and execute through Symfony2. This custom application code uses the request information to build and prepare all Requires resources. Except for some advanced cases, the final output of the controller is the same: a Response object.
// src/Acme/StudyBundle/Controller/HelloController.php namespace Acme\StudyBundle\Controller; use Symfony\Component\HttpFoundation\Response; class HelloController { public function indexAction($name) { return new Response('<html><body>Hello '.$name.'!</body></html>'); } }
The controller is simple, it creates a new Response object whose first parameter is the response content it returns (in this case It's a small HTML page).
Congratulations, just after creating a route and controller, you have got a fully functional page! If your settings are correct, your application will be able to greet you:
http://localhost/app_dev.php/hello/Ryan
An optional but often used step is Create a template.
Controllers are the main entry point and key part when creating pages, more information can be found in the Controllers chapter.
Create Templates
Templates allow you to put all presentation (such as HTML code) into a single file and reuse different parts of the page layout. The following code uses a template to replace the HTML code in the controller.
// src/Acme/StudyBundle/Controller/HelloController.php namespace Acme\StudyBundle\Controller; use Symfony\Bundle\FrameworkBundle\Controller\Controller; class HelloController extends Controller { public function indexAction($name) { return $this->render('AcmeStudyBundle:Hello:index.html.twig', array('name' => $name)); // 渲染PHP模板 // return $this->render('AcmeStudyBundle:Hello:index.html.php', array('name' => $name)); } }
In order to use the render() method, you must inherit the Controller class, which adds shortcut methods for some common tasks. The
render() method creates a Response object that is filled with specific content and rendered through a template. Like other controllers, what you end up with is a Response object.
注意,这里有两种不同渲染模板的例子,缺省情况下,Symfony2支持两种渲染模板的方式:传统的PHP模板和简洁强大的Twig模板。你可以随意选择使用其中的一种,也可以在同一项目中混用它们,这都不成问题。
控制器渲染AcmeStudyBundle:Hello:index.html.twig模板,该模板使用以下命名约定:
Bundle名:Controller名:Template名
在本例中,AcmeStudyBundle是Bundle名,Hello是控制器,index.html.twig是模板名。
{# src/Acme/StudyBundle/Resources/views/Hello/index.html.twig #} {% extends '::layout.html.twig' %} {% block body %} Hello {{ name }}! {% endblock %}
让我们一行行地来:
第2行:extends定义了一个父模板,模板明确定义了一个将被替换的布局文件;
第4行:block表示其中的内容将会替换掉名为body的block,如我们所知,它在最终渲染时将负责layout.html.twig中名为body的block的渲染。
父模板::layout.html.twig省略了它的bundle名和控制器名(所以用两个冒号::代替),这意味着该模板在bundle外面,在app目录中。
{# app/Resources/views/layout.html.twig #} <!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>{% block title %}Hello Application{% endblock %}</title> </head> <body> {% block body %}{% endblock %} </body> </html>
基本模板文件定义了HTML布局,并用我们在index.html.twig模板中定义的名为body的区块渲染。这里还定义了一个名为title的区块,我们也可以选择在index.html.twig模板中定义。由于我们没有在子模板中定义title区块,所以它还是使用缺省值”Hello Application”。
模板在渲染和组织页面内容方面的功能非常强大,它可以是HTML标识语言、CSS代码或者控制器可能需要返回的东东。模板引擎只是达到目标的手段。每个控制器的目标是返回一个Response对象,模板虽然强大,但它却是可选的,它只是为Response对象创建内容的工具而已。
目录结构
经过前面几段的学习,你已经理解了在Symfony2中创建和渲染页面的步骤,也开始明白了Symfony2的组织和结构,在本章的最后,你将学会在哪儿找到和放置不同类型的文件以及为什么这样做。
虽然Symfony2的目录结构相当灵活,但在缺省状态下,Symfony2还是有着相同的、被推荐的基本目录结构:
app/ : 该目录包含应用程序配置;
src/ : 所有项目的PHP代码都保存在该目录下;
vendor/ : 根据约定放置所有供应商的库文件;
web/ : 这是web根目录,包括一些公众可以访问的文件。
WEB目录
web根目录是所有静态的、公共文件的家目录,包括图像、样式表和javascript文件,这里也是前端控制器所在的地方。
// web/app.php require_once __DIR__.'/../app/bootstrap.php'; require_once __DIR__.'/../app/AppKernel.php'; use Symfony\Component\HttpFoundation\Request; $kernel = new AppKernel('prod', false); $kernel->handle(Request::createFromGlobals())->send();
前端控制器(在这里是app.php)其实是一个PHP文件,在使用Symfony2应用程序时执行。它的功能就是使用内核类AppKernel,让应用程序自举。
使用前端控制器意味着要比使用传统的纯PHP程序有着更为灵活多变的URL,当使用前端控制器时,URL格式如下所示:
http://localhost/app.php/hello/Ryan
前端控制器app.php被执行,URI(/hello/Ryan)通过路由配置被内部路由。如果使用Apache的重写规则,你可以在不指定app.php的情况下强制执行它:
http://localhost/hello/Ryan
虽然前端控制器在处理请求时必不可少,但你很少会去修改甚至想到它,我们只是在环境一章中简要地提及它。
应用程序(app)目录
正如你在前端控制器所看到的那样,AppKernel类是整个应用程序的主入口,它负责所有的配置,它被保存在app/目录中。
这个类必须实现三个方法,这些方法是Symfony2需要让应用程序了解的。你甚至在一开始就无须担心这些方法,因为Symfony2会智能地为你填充它们:
1、registerBundles(): 返回所有需要在应用程序中运行的bundle数组 (参见Bundle系统 );
2、registerContainerConfiguration(): 引导应用程序的主配置资源文件 (参见应用程序配置章节);
3、registerRootDir(): 返回app根目录 (缺省是 app/)
在日常开发中,你会经常用到app/目录,你会在app/config/目录中修改配置和路由文件(参见应用程序配置),也会使用app/cache/目录做为应用程序的缓存目录、使用app/logs/目录做为日志目录、使用app/Resources/目录做为应用程序级别的资源目录。在下面的章节中你将会学到更多关于这些目录的内容。
自动加载
当应用程序自举时,将包含一个特殊的文件:app/autoload.php。该文件负责自动加载src/和vender/目录中的所有文件。
因为有自动加载器,你永远无须为使用include或require语句担心。Symfony2利用类的名称空间确定它的位置,并自动加载包含你所需的类文件。
$loader->registerNamespaces(array( 'Acme' => __DIR__.'/../src', // ... ));
在这个配置中,Symfony2将查找src/目录下Acme名称空间(假想公司的名称空间)的所有类。为了能够自动加载,Class Name文件和Path必须遵循同一模式:
Class Name:
Acme\StudyBundle\Controller\HelloController
Path:
src/Acme/StudyBundle/Controller/HelloController.php
app/autoload.php配置自动加载器在不同的目录查找不同的PHP名称空间,也可以在必要时自定义。有关自动加载器的更多情况,参见如何自动加载类。
源(src)目录
简而言之,src/目录包括所有在应用程序中运行的PHP代码。实际上在开发时,大部分工作都是在该目录下完成的。缺省情况下,src/目录是空的,当你开始进行开发时,你将开始填充bundle所在的目录,该目录包含你应用程序的代码。
然而bundle究竟是什么呢?
Bundle系统
Bundle与其它软件中的插件类似,但比它们更好。关键的不同点在于在Symfony2中什么都是bundle,包括框架的核心功能和你为应用程序所写的代码。在Symfony2中,Bundle是一类公民,这让使用第三方Bundle的预建功能包或发布你自己的Bundle变得十分灵活。它也可以使你很容易地选择应用程序所需功能,并用你自己的方式去优化它们。
Bundle简单来说就是在一个目录里用来实现单一功能的结构化文件集。你可以创建BlogBundle、ForumBundle或用户管理的Bundle(许多都已经以开源Bundle的形式存在)。每个目录都包含与功能相关的内容,如PHP文件、模板、样式表、Javascripts、测试等。每个Bundle都包含某种功能的方方面面,而每种功能都必须在Bundle中实现。
应用程序由在AppKernel类中的registerBundles()方法中定义的Bundle组成:
// app/AppKernel.php public function registerBundles() { $bundles = array( new Symfony\Bundle\FrameworkBundle\FrameworkBundle(), new Symfony\Bundle\SecurityBundle\SecurityBundle(), new Symfony\Bundle\TwigBundle\TwigBundle(), new Symfony\Bundle\MonologBundle\MonologBundle(), new Symfony\Bundle\SwiftmailerBundle\SwiftmailerBundle(), new Symfony\Bundle\DoctrineBundle\DoctrineBundle(), new Symfony\Bundle\AsseticBundle\AsseticBundle(), new Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle(), new JMS\SecurityExtraBundle\JMSSecurityExtraBundle(), // register your bundles new Acme\StudyBundle\AcmeStudyBundle(), ); if (in_array($this->getEnvironment(), array('dev', 'test'))) { $bundles[] = new Symfony\Bundle\WebProfilerBundle\WebProfilerBundle(); } return $bundles; }
通过registerBundles()方法,你就拥有了应用程序所有Bundles的全部控制权(包含Symfony2的核心Bundle)
无论Bundle在什么地方,它都可以被Symfony2自动加载。举个例子,如果AcmeStudyBundle放在src/Acme目录中,请确保Acme的名称空间被添加到app/autoload.php文件中,并映射到src/目录,这样它就可以被Symfony2自动加载了。
创建Bundle
为了向你展示Bundle系统是如何之简单,让我们创建一个名为AcmeTestBundle的新Bundle,并激活它。
首先,创建一个src/Acme/TestBundle/ 目录,并添加一个名为AcmeTestBundle.php的新文件:
// src/Acme/TestBundle/AcmeTestBundle.php namespace Acme\TestBundle; use Symfony\Component\HttpKernel\Bundle\Bundle; class AcmeTestBundle extends Bundle { }
AcmeTestBundle遵循Bundle命名约定
这个空类仅仅只是我们需要创建新Bundle的一部分。虽然是空的,但这个类已经足够强大,并能够用来自定义Bundle的行为。
现在我们已经创建了我们的Bundle,我们需要通过Appkernel类激活它:
// app/AppKernel.php public function registerBundles() { $bundles = array( // ... // register your bundles new Acme\TestBundle\AcmeTestBundle(), ); // ... return $bundles; }
虽然目前它还不能做任何事情,但AcmeTestBundle现在已经可以使用了。
同样方便的是,Symfony也提供命令行接口去生成Bundle的基本框架
php app/console init:bundle "Acme\TestBundle" src
生成的Bundle框架包括一个基本控制器、模板和可自定义的路由资源。接下来我们将会讨论更多的Symfony2命令行工具。
无论何时,创建一个新的Bundle或使用第三方Bundle,都是需要确保该Bundle在registerBundles()中被激活。
Bundle的目录结构
Bundle的目录结构是简单而灵活的。缺省状态下,Bundle系统遵循Symfony2所有Bundle之间保持代码一致性的约定集。让我们看看AcmeStudyoverBundle,因为它包含了Bundle的大多数元素:
1、Controller/目录:包含该Bundle的控制器(如:HelloController.php);
2、Resources/config/目录:配置目录,包括路由配置(如:routing.yml);
3、Resources/views/目录:通过控制器名组织的模板(如:Hello/index.html.twig);
4、Resources/public/目录:包含web资源(图片、样式表等),并被拷贝或软链接到项目的web/目录;
5、Tests/目录:存放该Bundle的所有测试。
根据Bundle实现的功能,它可小可大,它只包含你所需要的文件。
你在本书中还将学习到如何持久化对象到数据库、创建和验证表单、翻译你的应用程序和编写测试等等,它们在Bundle中都有自己的位置和所扮演的角色。
应用程序配置
应用程序由代表应用程序所有功能和特征的Bundle集构成。每个Bundle都可以通过YAML、XML或PHP编写的配置文件来自定义。缺省情况下,主配置文件放置在app/config/目录中,被命名为config.yml、config.xml或config.php,这取决于你所使用的格式:
# app/config/config.yml framework: charset: UTF-8 secret: xxxxxxxxxx form: true csrf_protection: true router: { resource: "%kernel.root_dir%/config/routing.yml" } validation: { annotations: true } templating: { engines: ['twig'] } #assets_version: SomeVersionScheme session: default_locale: en lifetime: 3600 auto_start: true # Twig Configuration twig: debug: %kernel.debug% strict_variables: %kernel.debug%
我们将在下一节环境中展示如何准确地选择要引导的文件/格式。
每一个顶级条目,如framework或twig都被配置成一个特定的Bundle。例如,framework被配置成Symfony2的核心FrameworkBundle,并包含路由、模板和其它核心系统的配置。
现在别担心配置文件中各段中的特定配置选项,配置文件缺省值都是合理的。当你浏览Symfony2的各部分时,你将学到每个部分的特定配置选项。
配置格式
纵观整个章节,所有的配置示例都用三种格式(YAML、XML和PHP)展示。它们每个都有自己的优缺点,以下是三种格式的说明:
1、YAML:简单、干净和易读
2、XML:有时比YAML更强大且支持IDE的自动完成
3、PHP:非常强大,但与标准配置格式相比易读性差
环境
应用程序可以在不同的环境中运行。不同的环境共享相同的PHP代码(由前端控制 器区分),但却有着完全不同的配置。开发环境记录警告和错误,而生产环境只记录错误。在开发环境中一些文件在每次请求之后被重构,而在生产环境中却被缓存 。所有的环境都在同一机制中生活。
虽然创建新的环境是容易的,但Symfony2项目通常会从三个环境开始(开发、测试和生产)。通过在你浏览器中改变前端控制器,你可以很方便地让应用程序在不同的环境中切换。要将应用程序切换到开发环境,只需要通过开发前端控制器去访问应用程序即可。
http://localhost/app_dev.php/hello/Ryan
如果你想看看你的应用程序在生产环境中的表现 ,可以调用生产前端控制器:
http://localhost/app.php/hello/Ryan
如果你打开 web/app.php文件,你将发现它已经很明确地被配置成使用生产环境:
$kernel = new AppCache(new AppKernel('prod', false));
你可以为一个新的环境创建一个新的前端控制器,只需要拷贝该文件,并将prod修改成其它值。
因为生产环境是为速度优化的,配置、路由和Twig模板都被编译成纯的PHP类,同时被缓存 。在生产环境中改变视图时,你需要清除这些缓存文件,从而让它们重构:
rm -rf app/cache/*
当进行自动测试时使用测试环境,它并不能从浏览器直接访问。参见测试章节以得到更多细节。
环境配置
AppKernel类负责加载你所选的配置文件:
// app/AppKernel.php public function registerContainerConfiguration(LoaderInterface $loader) { $loader->load(__DIR__.'/config/config_'.$this->getEnvironment().'.yml'); }
我们已经知道.yml扩展名可以转换成.xml或.php,只要你喜欢使用XML或PHP来写配置。注意每种环境也可以加载它们自己的配置文件。下面是为生产环境准备的配置文件。
# app/config/config_dev.yml imports: - { resource: config.yml } framework: router: { resource: "%kernel.root_dir%/config/routing_dev.yml" } profiler: { only_exceptions: false } web_profiler: toolbar: true intercept_redirects: true zend: logger: priority: debug path: %kernel.logs_dir%/%kernel.environment%.log
import关键词与PHP格式中include语句一样,都是首先引导主配置文件(config.yml),文件的其它部分是为了增长的日志和其它有利于开发环境的设置而对缺省配置进行的调整。
在生产环境和测试环境都遵循同样一个模型:每个环境导入基本配置文件,然后修改它们的配置值去适应特殊环境的需要。
小结
恭喜你,你现在已经明白了Symfony2的基本原理,并惊喜地发现它是那样的方便灵活。尽管有许多的功能,但我们可以牢记以下几个基本点:
1、创建页面需要三个步骤,包括路由、控制器和模板(可选);
2、每个应用程序都应该包含四个目录:web/(web资源和前端控制器)、app/(配置)、src/(你的Bundle)和vendor/(第三方代码);
3、Symfony2的每个功能(包括Symfony2框架核心)都被组织进一个Bundle,Bundle是该功能的结构化文件集;
4、每个Bundle的配置都存放在app/config目录中,可以使用YAML、XML和PHP编写;
5、通过不同的前端控制器(如:app.php或app_dev.php)和配置文件,每种环境都可以被访问。
希望本文所述对大家基于Symfony框架的PHP程序设计有所帮助。
更多Symfony2创建页面实例详解相关文章请关注PHP中文网!