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


    Symfoy2 是什么?

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

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

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

      其次,基于这些组件,Symfoy2 也可以作为一个独立的web框架使用。

    那么Symfony2 是一个MVC框架吗?

    Fabien Potencier 说Symfony2从来没有把自己定义为一个MVC框架!

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

    但是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

  • 相关阅读:
    23中设计模式详解
    C#中的partial,this关键字以及扩展方法
    笨重WebService与轻快的RestFul
    彻底理解Web Service
    WebService中的瘦客户端与富客户端
    [转]Sql Or NoSql,看完这一篇你就懂了
    [转]Mysql字符串截取总结:left()、right()、substring()、substring
    [转]ASP.NET Core on K8s 入门学习系列文章目录
    [转]CSDN-markdown语法之怎样使用LaTeX语法编写数学公式
    [转]我在传统行业做数字化转型(1)预告篇
  • 原文地址:https://www.cnblogs.com/Seekr/p/2550894.html
Copyright © 2020-2023  润新知