聽 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

相關文章
相關標籤/搜索