听 Fabien Potencier 谈Symfony2 之 《What is Symfony2 ?》


Symfoy2 是什么?php

PHP世界里又一广受关注的web MVC框架? Fabien Potencier 却不这么说!html

Fabien Potencier这样定义Symfoy2 是个什么东西:web

首先,Symfony2 是一个独立,松散的,有组织严密的PHP组件集合,它能够为你解决一些web开发中遇到的通常性问题。api

其次,基于这些组件,Symfoy2 也能够做为一个独立的web框架使用。浏览器

那么Symfony2 是一个MVC框架吗?缓存

Fabien Potencier 说Symfony2历来没有把本身定义为一个MVC框架!服务器

那它是什么? Fabien Potencier 咱们历来不关心MVC模式,关心的只有各个关注点的分离(separation of concerns)。app

可是Symfony2 仍是提供了部分的MVC模式的实现:好比Controller部分,View部分却没有Mode部分不过你能够经过和它紧密继承的ORM(Doctrine2和Propel)实现。框架

 

从这个角度看Symfony的确也没有逃出web MVC框架的圈子啊!!!分布式

Fabien Potencier 又说Symfony2历来就没有想靠这些ORM来使本身成为另外一个MVC的追随者,咱们的目标更远大!

 

告诉你吧, Symfony2 是一个HTTP框架或者说是一个Request/Response 框架。咱们紧盯的目标不是MVC模式,而是HTTP协议,咱们是更低级的更基础的框架。

咱们为何要这么说呢? 有根据的!

近几年随着web的发展,有时候你只须要建立一组REST API,全部的逻辑都放到浏览器端,服务器端只提供数据就是一种web了。不信你看 backbone.js !

再说了,MVC模式只不过是Web 应用程序的其中一种实现方式罢了。

剥去全部框架模式的皮,你看看那个web程序不是处理一个接收到的Request而后返回一个Response啊?

咱们Symfony2 抓住的就是web程序的根本! 再说咱们众多的HTTP流媒体有哪一个会选择使用MVC呢?

总之,咱们Symfony2比MVC更靠近根本,咱们更底层,更通用!!!

 

提及Symfony2,Fabien Potencier说咱们有着更加远大的目标,怎么解释呢?

Symfony2 将继续专一于Pack技术的研究和创新!咱们相信她会继续推进web的向前发展。

先看看Symfony2 中咱们已经包含的创新吧!

从Bundles,HTTP 缓存,分布式,依赖注入,模板引擎,声明式配置,资产管理,稳定的API到web分析器等等一系列技术都对web的发展起到了巨大的推进做用。

 

“ 要知道一个独立的框架永远不可能成为PHP世界里的一个标准,因此Symfony2 在探寻另一条路!”

“ 共享无处不在。”

“ 咱们不能重复制造轮子。”

所以,咱们紧密的集成了Monolog,Composer,Doctrine,Propel,Assetic,Twig,Swiftmailer等伟大产品。

更重要的是咱们想跟你们分享咱们的工做!

因此,咱们最终选择了走组件(components)化这条路!

咱们将为一切web项目提供建筑模块,不管是我的项目仍是商业项目,更或者是开源项目!

 

听说在Symfony2 的代码中可能会有标志为@api的类或者方法,它意味着一个方法从名字到参数以及返回值都不会由于Symfony2发展版本而变化,因此,若是

你的项目只使用了这些,那么你就不用担忧Symfony2的版本升级问题。

 

看看Symfony2 如今拥有的组件吧:

DependencyInjection
EventDispatcher
HttpFoundation
DomCrawler
ClassLoader
CssSelector
HttpKernel
BrowserKit
Templating
Translation
Serializer
Validator
Security
Routing
Console
Process
Config
Finder
Locale
Yaml
Form

Fabien 简单介绍了几个bundle:

1. ClassLoader:

实现了PSR-o 标准(自动加载具备命名空间的类,适用于PHP5.3以上)的自动加载器,同时它也能按照PEAR命名规则加载类。它很是灵活能够基于子命名空间在不一样的目录中查询要加载的类。你甚至能够为一个命名空间指定多个目录。

 

复制代码
require_once __DIR__.'/src/Symfony/Component/ClassLoader/UniversalClassLoader.php';
 
use Symfony\Component\ClassLoader\UniversalClassLoader;
 
$loader = new UniversalClassLoader();
$loader->registerNamespaces(array(
    'Symfony'          => array(__DIR__.'/src', __DIR__.'/symfony/src'),
    'Doctrine\\Common' => __DIR__.'/vendor/doctrine-common/lib',
    'Doctrine\\DBAL'   => __DIR__.'/vendor/doctrine-dbal/lib',
    'Doctrine'         => __DIR__.'/vendor/doctrine/lib',
    'Monolog'          => __DIR__.'/vendor/monolog/src',
));
$loader->registerPrefixes(array(
    'Twig_' => __DIR__.'/vendor/twig/lib',
));
$loader->register();
 
复制代码

若是你想获取更加高的执行效率,能够选择使用APC缓存版Universal类加载器。

 

2.Console 命令行工具

在建立web应用程序时使用命令行工具很方便,你能够想以下代码同样建立本身的命令行工具:

 

复制代码
use Symfony\Component\Console\Application;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
 
$console = new Application();
$console
    ->register('ls')
    ->setDefinition(array(
        new InputArgument('dir', InputArgument::REQUIRED, 'Directory name'),
    ))
    ->setDescription('Displays the files in the given directory')
    ->setCode(function (InputInterface $input, OutputInterface $output) {
        $dir = $input->getArgument('dir');
 
        $output->writeln(sprintf('Dir listing for <info>%s</info>', $dir));
    })
;
$console->run();
复制代码

 

3.YAML  一种如今很流行的配置格式。

 

use Symfony\Component\Yaml\Yaml;
 
$array = Yaml::parse($file);
 
print Yaml::dump($array);
 

 

4. Finder 优秀文件资源的操做接口。

复制代码
use Symfony\Component\Finder\Finder;
 
$finder = new Finder();
 
$iterator = $finder
  ->files()
  ->name('*.php')
  ->depth(0)
  ->size('>= 1K')
  ->in(__DIR__);
 
foreach ($iterator as $file) {
    print $file->getRealpath()."\n";
}
复制代码

你甚至能够用它获取远程服务器文件系统中的资源,好比获取Amazon S3上的文件:

复制代码
$s3 = new \Zend_Service_Amazon_S3($key, $secret);
$s3->registerStreamWrapper("s3");
 
$finder = new Finder();
$finder->name('photos*')->size('< 100K')->date('since 1 hour ago');
foreach ($finder->in('s3://bucket-name') as $file) {
    print $file->getFilename()."\n";
}
复制代码

 

5.Process 进程组件,你能够用来在一个外部进程中执行命令!下面例子是执行一个简单的目录列表命令并返回结果:

复制代码
use Symfony\Component\Process\Process;
 
$process = new Process('ls -lsa');
$process->setTimeout(3600);
$process->run();
if (!$process->isSuccessful()) {
    throw new RuntimeException($process->getErrorOutput());
}
 
print $process->getOutput();
复制代码

若是你想监控执行过程,你能够给run方法传入一个匿名方法:

复制代码
use Symfony\Component\Process\Process;
 
$process = new Process('ls -lsa');
$process->run(function ($type, $buffer) {
    if ('err' === $type) {
        echo 'ERR > '.$buffer;
    } else {
        echo 'OUT > '.$buffer;
    }
});
复制代码

 

6.DomCrawler jQuery的php版本!你能够用它导航定位HTML的DOM结构或者XML文档。

use Symfony\Component\DomCrawler\Crawler;
 
$crawler = new Crawler();
$crawler->addContent('<html><body><p>Hello World!</p></body></html>');
 
print $crawler->filterXPath('descendant-or-self::body/p')->text();

 

7.CssSelector 咱们常常用XPath来访问Dom结构,其实用Css 选择器更加容易,这个组件就是把Css选择器转为XPath等效的东西。

use Symfony\Component\CssSelector\CssSelector;
 
print CssSelector::toXPath('div.item > h4 > a');
 

因此你可使用CssSelector 和DomCrawler来替代XPath:

use Symfony\Component\DomCrawler\Crawler;
 
$crawler = new Crawler();
$crawler->addContent('<html><body><p>Hello World!</p></body></html>');
 
print $crawler->filter('body > p')->text();

 

8.HttpFoundation 

该组件只是在PHP的相关web内容上面增长了一个面向对象层,包括Request,Response,Uploaded files,Cookies,Sessions...

use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
 
$request = Request::createFromGlobals();
echo $request->getPathInfo();

你用它能够很容易的建立本身的Request 和 Response:

$request = Request::create('/?foo=bar', 'GET');
echo $request->getPathInfo();


$response = new Response('Not Found', 404, array('Content-Type' => 'text/plain'));
$response->send();

 

9.Routing 

路由组件和Request对象是相互配合着把Request转换为Response。

复制代码
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\Matcher\UrlMatcher;
use Symfony\Component\Routing\RequestContext;
use Symfony\Component\Routing\RouteCollection;
use Symfony\Component\Routing\Route;
 
$routes = new RouteCollection();
$routes->add('hello', new Route('/hello', array('controller' => 'foo')));
 
$context = new RequestContext();
 
// this is optional and can be done without a Request instance
$context->fromRequest(Request::createFromGlobals());
 
$matcher = new UrlMatcher($routes, $context);
 
$parameters = $matcher->match('/hello');
复制代码

 

10.EventDispatcher

复制代码
use Symfony\Component\EventDispatcher\EventDispatcher;
use Symfony\Component\EventDispatcher\Event;
 
$dispatcher = new EventDispatcher();
 
$dispatcher->addListener('event_name', function (Event $event) {
    // ...
});
 
$dispatcher->dispatch('event_name');
复制代码

 

11.DependencyInjection

复制代码
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Reference;
 
$sc = new ContainerBuilder();
$sc
    ->register('foo', '%foo.class%')
    ->addArgument(new Reference('bar'))
;
$sc->setParameter('foo.class', 'Foo');
 
$sc->get('foo');
复制代码

 

12.HttpKernel

Http 内核组件提供了HTTP协议中最有活力的部分,如下面接口的形式定义展现,它也是Symfony2框架的核心。

复制代码
interface HttpKernelInterface
{
    /**
     * Handles a Request to convert it to a Response.
     *
     * @param  Request $request A Request instance
     *
     * @return Response A Response instance
     */
    function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true);
}
复制代码

它接受一个Request输入并返回一个Response输出。 只要遵循这个接口规定,你就能使用Symfony2中全部的精彩内容。

 

下面使用Symfony2 组件来建立一个简单的框架:

复制代码
$routes = new RouteCollection();
$routes->add('hello', new Route('/hello', array('_controller' =>
    function (Request $request) {
        return new Response(sprintf("Hello %s", $request->get('name')));
    }
)));
 
$request = Request::createFromGlobals();
 
$context = new RequestContext();
$context->fromRequest($request);
 
$matcher = new UrlMatcher($routes, $context);
 
$dispatcher = new EventDispatcher();
$dispatcher->addSubscriber(new RouterListener($matcher));
 
$resolver = new ControllerResolver();
 
$kernel = new HttpKernel($dispatcher, $resolver);
 
$kernel->handle($request)->send();
复制代码

ok, 这就是框架了!

若是想添加一个HTTP反向代理以获取HTTP caching和ESI(Edge Side Includes)带来的好处,那么这样作!

$kernel = new HttpKernel($dispatcher, $resolver); 
 
$kernel = new HttpCache($kernel, new Store(__DIR__.'/cache'));

想对它作一下功能测试:

$client = new Client($kernel);
$crawler = $client->request('GET', '/hello/Fabien');
 
$this->assertEquals('Fabien', $crawler->filter('p > span')->text());

想要一个好看的错误展现页面?

$dispatcher->addSubscriber(new ExceptionListener(function (Request $request) {
    $msg = 'Something went wrong! ('.$request->get('exception')->getMessage().')';
 
    return new Response($msg, 500);
}));

你能够继续发挥你的想象...

 

看看HttpKernelInterface 有多么强大! 

 

总结一下,Symfony2 好像很牛啊,继续研究研究!!!

 

 

关注URL: http://fabien.potencier.org/article/49/what-is-symfony2

相关文章
相关标签/搜索