分享

CATEGORY ARCHIVES: SYMFONY

 sumi2005 2014-04-11

Symfony2 的一些开源学习范例

收集了一些Symfony2在实际应用环境中的开源范例:

KnpBundles

的源代码, 是一个 symfony bundle 展示网站,包含的功能包括搜索、用户管理、内容管理等。

https://github.com/KnpLabs/KnpBundles

 

Sylius

Sylius 是一个基于 Symfony2 的开源商城系统,提供商城的功能并且易于二次开发

https://github.com/Sylius/Sylius

 

Drupal

Drupal 是一个开源的CMS,Drupal 8.x 版本基于Symfony2 框架开发

https://github.com/drupal/drupal

如何通过抽象类与接口来定义关联

Symfony2 文档翻译:http:///doc/current/cookbook/doctrine/resolve_target_entity.html

使用代码包(Bundle)的其中一个目标就是使相互间的依赖更少,这样用户在在其他应用中使用这个功能,而不许要包含不必要的代码。

Doctrine 2.2 中包含了一个新的功能: ResolveTargetEntityListener, 通过此功能你可以拦截Doctrine中的某些调用,在运行时覆写Doctrine 实体(Entity)映射配置中的 targetEntity 参数。这样,在你的代码包中可以使用接口或者抽象类来做实体映射然后在运行时指定正确的 Entity。

这个功能的作用在于你可以通过配置的方式来实现实体见的关系,而不需要在代码包中写死。

 

背景

假设你有一个InvoiceBundle,提供与发票相关的功能;一个CustomerBundle,提供用户管理的功能。你希望将这两个代码包分开,这样在其他系统中他们可以独立使用,但是当前的应用需要同时用到这两个功能。

在这种情况下,你可以定义一个Invoice实体,与之关联的是一个不存在的实体:InvoiceSubjectInterface。这样做的目的是可以用一个实现了以上接口的实体ResolveTargetEntityListener 来代替掉InvoiceSubjectInterface

 

实现

下面用一个简单的例子来示范如何实现ResolveTargetEntityListener。

Customer 实体::

Invoice 实体::

InvoiceSubjectInterface 接口::

然后,你需要配置监听器(Listener),配置好替换关系

 

总结

有了 ResolveTargetEntityListener,代码包间可以更好的解藕。使代码包的功能更加独立,同时又可以通过这种方式来定义不同实体间的关系,使代码包更加容易维护。

FOSUserBundle 入门

这是一篇介绍FOSUserBundle的安装与配置笔记,面向Symfony2.1+,更详细的内容请参考:https://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/Resources/doc/index.md

Symfony2的安全组件提供了一个具有扩展性的安全机制,允许你从配置文件、数据库或者任何你能想象到的地方加载用户。FOSUserBundle就是基于这种安全机制上建立的,为你提供一个简便的方式来将用户保存在数据库中。

下载FOSUserBundle

修改composer.json文件,在require部分增加以下内容:

“friendsofsymfony/user-bundle”: “~2.0@dev”

使用composer更新

$ php composer.phar update friendsofsymfony/user-bundle

使能FOSUserBundle

修改app/AppKernel.php文件,使能FOSUserBundle

 

创建用户类

创建一个自己的UserBundle,建立自己的User Entity。这样做有一个好处是以后可以用这个UserBundle来覆写FOSUserBundle。

 

配置security.yml

 

配置FOSUserBundle

user_class需要按照自己的需求来设置。

加载路由配置文件

需要注意的是,需要配置好SwiftmailerBundle后,重置密码等功能才能正常工作。

更新数据库

可以先看看是不是一切正常

 

然后更新数据库

如无意外,至此FOSUserBundle的功能就已经可以正常功能。可以尝试访问 /login /register 等进行测试。

 

Symfony服务容器 ( Symfony Service Container ) [ Symfony ]

这是一篇关于Symfony2服务容器实现的笔记,原文请查看文章末尾的相关资料部分。

上一篇笔记介绍了依赖注入容器,依赖注入容器使得对各种系统功能的调用变得简便,但同时引入了一个新的问题就是容器的编写与维护变得非常复杂。Symfony2试图通过ServiceContainer、ServiceContainerBuilder以及xml、yml配置文件来使容器的实现变得简单。

ServiceContainer

首先,引入sfServiceContainer类http://svn./components/dependency_injection/trunk/lib/sfServiceContainer.php,将上一篇笔记中的container作点修改,继承sfServiceContainer:

然后通过这种方式来调用:

通过实现__get方法,我们可以通过container对象属性的方式来调用各种服务,可以通过setService对容器进行配置,而需要我们编写的Container类变得更加格式化,都是由一系列get…Service方法组成。

ServiceContainerBuilder

因此我们可以通过一个ServiceContainerBuilder对ServiceContainer进行动态配置,sfServiceContainerBuilder: http://svn./components/dependency_injection/trunk/lib/sfServiceContainerBuilder.php

sfServiceContainerBuilder通过register函数来创建一个service,传入service的id以及对应的类,再通过addArgument传入将类实例化时传给构造函数的参数,通过addMethodCall来设置对象创建后调用的初始化函数,通过setShared来指定service是否全局共享。

sfServiceContainerBuilder继承自sfServiceContainer,覆写了getService方法,使得既可以调用静态设置的service,也可以使用动态添加的service。

使用配置文件来描述Service

既然service可以通过php动态添加,那么是否可以通过读取配置文件来动态生成呢?答案是肯定的。Symfony提供 sfServiceContainerLoader*** 类,通过读取配置文件,将配置文件转换成 sfServiceDefinition 并且对其进行配置,然后通过containerbuilder的setServiceDefinition方法来添加service,实现方式可以参考 http://svn./components/dependency_injection/trunk/lib/sfServiceContainerLoader.php 以及相关loader 的类。

使用缓存提升性能

使用配置文件来描述service非常强大而灵活,但会引入一个问题,如果每次运行都要读取配置文件,动态生成service,导致性能问题,而使用PHP代码扩展sfServiceContainer类则可以获得最大的性能优化。

Symfony除了有sfServiceContainerLoader来加载service以外,还可以通过sfServiceContainerDumper来将service的写入到文件中,譬如 sfServiceContainerDumperXml 可以生成上面的使用的配置文件,而sfServiceContainerDumperPhp则可以将service生成一个sfServiceContainer子类的代码。

通过这种方式,Symfony2可以将配置文件的灵活与PHP代码的性能很好的结合起来。

Symfony2中的实现

在Symfony2启动流程分析中,有以下的代码段:

这就是Symfony对container的实现。

相关资料:

http://svn./components/dependency_injection/trunk/lib/

http://fabien./article/13/introduction-to-the-symfony-service-container

http://fabien./article/14/symfony-service-container-using-a-builder-to-create-services

http://fabien./article/15/symfony-service-container-using-xml-or-yaml-to-describe-services

http://fabien./article/16/symfony-service-container-the-need-for-speed

依赖注入容器(Dependency Injection Container)[ Symfony ]

这是一篇关于Symfony依赖注入容器 Dependency Injection Container 的笔记,原文地址:http://fabien./article/12/do-you-need-a-dependency-injection-container

上一篇文章介绍过依赖注入,通过一种非常简单的方式很好的降低了类之间的耦合。但是当业务中使用的类原来越多,譬如在很多地方都需要用到User,每次创建User时都需要记住传递给User的每个参数,这是不可能的,因此就需要用到依赖注入容器。

A Dependency Injection Container is an object that knows how to instantiate and configure objects. And to be able to do its job, it needs to knows about the constructor arguments and the relationships between the objects.

依赖注入容器的作用就是初始化与配置各类对象,管理对象间的依赖关系。下面是一个简单的实现:

使用起来也很简便:

这样,系统的所有功能都是通过container来统一管理。为了是container更加实用,需要添加一些配置参数:

然后这样初始化:

为了不用每次使用某个功能时都新建一个对象,再对container进行一些改进:

使用依赖注入容器后,对系统功能的初始化与调用变得非常简单,但同时很明显的,当系统变得庞大后,创建与维护Contianer类将是一个噩梦,因此Symfony2提供了一个ContainerBuilder类,根据用户的配置自动生成Container类的代码。

参考资料:

http://fabien./article/12/do-you-need-a-dependency-injection-container

依赖注入(Dependency Injection)[ Symfony ]

这是一篇关于Symfony依赖注入(Dependency Injection)的笔记,原文地址:http://fabien./article/11/what-is-dependency-injection

假设需要实现下面的需求:编写一个User类,需要实现Session的相关操作

下面是一种简单的实现方式:

我们可以这样调用上面的代码:

但这里有一个问题:代码中将User的storage属性写死了,第三方调用User时无法对storage进行配置。因此,对User代码进行下面的修改:

不在User类中创建SessionStorage对象,而是将storage对象作为参数传递给User的构造函数,这就是依赖注入。

“Dependency Injection is where components are given their dependencies through their constructors, methods, or directly into fields.”

上面就是依赖注入的定义,根据其定义,依赖注入可以通过下面三种方式进行:

构造器注入 Constructor Injection:

设值注入 Setter Injection:

属性 Property Injection:

 

相关资料:

http://fabien./article/11/what-is-dependency-injection

http://www./articles/injection.html

http://www.cnblogs.com/xingyukun/archive/2007/10/20/931331.html

Symfony2 启动流程分析

入口文件app.php

入口文件app_dev.php

app_dev.php相对于app.php的主要区别在于 environment 与 debug 参数。

app/bootstrap.php.cache:bootstrap.php.cache 在运行composer update或者composer install 的时候由脚本生成,主要的功能是将Symfony中必须要用到的核心类打包到单个文件中,同时提供classloader。

app/AppKernel.php;扩展自Kernel类,对系统进行配置。创建AppKernel的时候会传入environment 与 debug 参数,environment参数会影响配置文件路径,缓存文件路径,debug参数会影响到缓存文件路径以及系统对cache的处理。

 

$kernel->loadClassCache(); :做一个需要加载cache的标记,但不会进行加载工作。

Request::enableHttpMethodParameterOverride(); 是否允许通过发送的参数来修改请求的方法,只对POST有效。

$request = Request::createFromGlobals();创建request对象,通过获取$_GET,$_POST等数据,创建request对象。

$response = $kernel->handle($request); 处理请求。symfony内核在此处启动。

boot方法启动内核,进行初始化配置

doLoadClassCache会根据前面loadClassCache的调用,将加载cache目录下的classes.php,如果缓存不存在,则根据classes.map文件来生成。如果debug=true则还会检测每个classes对应原文件的修改时间来判断是否需要重新生成。

初始化bundle,主要是处理bundle的继承关系

初始化container,为symfony的核心,原理与实现方式请参考下面的文章。基本流程为:如果container缓存存在,则直接使用缓存,如果不存在则创建container,获取每个bundle与container相关的信息,加载配置文件,配置每个bundle,打包生成缓存。

Introduction to the Symfony Service Container

Dependency Injection

 

getHttpKernel()->handle(),此时可以通过contianer来获取http_kernel服务对请求进行处理。

$response->send(); 发送内容

$kernel->terminate($request, $response); 结束

 

使用capifony对Symfony网站进行发布

以前一直使用Drupal来搭建网站,由于需要定制的代码量不是很大,所以每次修改都是直接用sftp传到服务器,再到Drupal后台清一下缓存。最近使用Symfony2进行开发,到了发布环节遇到了问题。Symfony代码的发布并不像其他CMS那么方便,因为更新代码后还需要assetic:dump,assets:install,cache:clear等一系列操作,因此每次更新往往需要登录到服务器去更新代码,运行清理cache的一系列命令。

capifony是针对Symfony开发的应用部署脚本,基于Capistrano。使用capifony只需要进行简单的配置,就可以很方便的将代码部署到不同的服务器上。

capifony可以非常方便的使用RubyGems进行安装:

在本地生成配置文件:

上面的命令会在本地生成 ./Capfile 以及 app/config/deploy.rb

参考官网跟https://github.com/everzet/capifony/blob/master/lib/capifony_symfony2.rbhttps://github.com/capistrano/capistrano/wiki/2.x-Significant-Configuration-Variables 对deploy.rb 进行配置。

命令会在服务器上生成Symfony的目录结构current指向最新版本目录,shared里面为公用文件,需要修改 parameters.yml。

在本地运行:

就可以方便的将代码发布到服务器。

另外,还可已使用回调函数使capifony在完成某个任务后运行指定的命令:

.

Symfony2 备忘录

本文用于记录Symfony2使用中常用的文档与命令

常用命令
命令行创建bundle
$ php app/console generate:bundle –namespace=Acme/HelloBundle –format=yml
删除缓存
$ php app/console cache:clear –env=prod –no-debug
1. 创建Entity文件 如:

$ php app/console doctrine:generate:entity –entity=”AcmeStoreBundle:Product” –fields=”name:string(255) price:float description:text”

2. 生成getters与setters
$ php app/console doctrine:generate:entities Acme/StoreBundle/Entity/Product
3. 更新数据库
$ php app/console doctrine:schema:update –dump-sql
$ php app/console doctrine:schema:update –force
4. 生成crud
$ php app/console doctrine:generate:crud

文档索引
Symfony2入门文档 the book:http:///doc/current/book/index.html
使用Git来管理Symfony项目:http:///doc/current/cookbook/workflow/new_project_git.html
Symfony名词解释:http:///doc/current/glossary.html
Symfony学习资源列表:http://www./tutorial/symfony-tutorial/leanring-symfony2-re…
Practical-Symfony2. Jobeet2 Documentation: http:///doc/jobeet/en/index
入门教程:http://www./tag/symfony2-jobeet/

Demos:
stfalcon.com 源代码:https://github.com/stfalcon/portfolio
blog:http://tutorial./
knplabs的一系列demo,bundle:http://ipsum./

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多