symfony_单文件Symfony应用程序? 是的,有了MicroKernelTrait!

symfony

This article was peer reviewed by Younes Rafie, Claudio Ribeiro, and Haydar KÜLEKCİ. Thanks to all of SitePoint’s peer reviewers for making SitePoint content the best it can be!

这篇文章由Younes RafieClaudio RibeiroHaydarKÜLEKCİ进行了同行评审。 感谢所有SitePoint的同行评审人员使SitePoint内容达到最佳状态!



A Single Page Application (SPA) offers a desktop experience to users of a web application by loading a single HTML page, and dynamically updating it as required without reloading. However, a Symfony application may have hundreds of classes, and in a basic application we end up with lots of files we don’t really need.

单个页面应用程序(SPA)通过加载单个HTML页面并根据需要动态更新它而无需重新加载,从而为Web应用程序的用户提供了桌面体验。 但是, Symfony应用程序可能具有数百个类,在一个基本应用程序中,我们最终得到了很多我们实际上不需要的文件。

Illustration of a programmer holding up an elephant

The latest versions of Symfony (2.8 and 3.0) introduce us to the concept of a Single File Application (SFA) – a super-slim application or micro-framework implemented in one file.

Symfony的最新版本(2.8和3.0)向我们介绍了单文件应用程序(SFA)的概念–单文件应用程序是一种超薄应用程序或微框架。

To follow along, you need to have a running web server and have your way of running web applications locally. See Laravel Valet article for a quick way of setting up a local development environment that doesn’t require configuring a web server, virtual hosts and mucking about with a hosts file. Another option is our trusty Homestead Improved for a ready-to-go experience.

要继续学习,您需要拥有一个正在运行的Web服务器并拥有在本地运行Web应用程序的方式。 有关设置本地开发环境的快速方法,请参见Laravel Valet的文章 ,该方法不需要配置Web服务器,虚拟主机和处理主机文件。 另一个选择是我们值得信赖的Homestead经过改进 ,可随时提供使用体验。

步骤1:安装准系统Symfony (Step 1: Install Barebones Symfony)

We are going to install Symfony with Composer as it allows us install only the main package. Create a folder where you usually have your web applications and let’s call it sfa. I’ve got mine under ~/Sites/sfa. In it, we install Symfony:

我们将使用Composer安装Symfony,因为它只允许我们安装主软件包。 创建一个通常在其中具有Web应用程序的文件夹,我们将其称为sfa 。 我在~/Sites/sfa 。 在其中安装Symfony:

composer require symfony/symfony

Now, create 2 folders inside sfa and name them app and web.

现在,在sfa创建2个文件夹,并将其命名为appweb

步骤2:前端控制器 (Step 2: The Front Controller)

Inside sfa/web we will house our front controller – a file that receives all requests to the application, passes it to the right place for processing and returns the response to the client that made the request.

sfa/web内部,我们将放置我们的前端控制器-一个文件,该文件接收对应用程序的所有请求,将其传递到正确的位置进行处理,并将响应返回给发出请求的客户端。

You can call this file anything, but you need to make sure your web server has been configured to find it in the correct place. Laravel has public/index.php, Drupal 8 has index.php, and Symfony has web/app_dev.php (during development) and web/app.php (during production). Since this is a Symfony application, let’s call ours app_dev.php:

您可以将该文件命名为任何文件,但是您需要确保已配置Web服务器以在正确的位置找到它。 Laravel具有public/index.php ,Drupal 8具有index.php ,Symfony具有web/app_dev.php (在开发过程中)和web/app.php (在生产过程中)。 由于这是一个Symfony应用程序,因此我们将其称为app_dev.php

<?php

use Symfony\Component\HttpFoundation\Request;

require __DIR__.'/../vendor/autoload.php';
require __DIR__ . '/../app/SfaKernel.php';

$kernel = new SfaKernel('dev', true);
$request = Request::createFromGlobals();
$response = $kernel->handle($request);
$response->send();
$kernel->terminate($request, $response);

Two small differences between this file and a vanilla Symfony 3 installation.

此文件与香草Symfony 3安装之间的两个小区别。

Firstly, our kernel class is going to be in app/SfaKernel.php. Nothing stops us from calling it Kernel.php, but we want something different. Secondly, we opt not to call the loadClassCache() method. Our application is a slim one, without a good number of classes from a standard installation, so we can leave that method out for now.

首先,我们的内核类将位于app/SfaKernel.php 。 没有什么可以阻止我们将其Kernel.php ,但是我们想要一些不同的东西。 其次,我们选择不调用loadClassCache()方法。 我们的应用程序是一个苗条的应用程序,没有标准安装中的大量类,因此我们暂时可以省略该方法。

Even though we’re talking about a single file app, you’ll notice it’s not really a single file – we do have a front controller and a mini-kernel which does all the heavy lifting. That’s in addition to all the other classes loaded from vendor. However, for all intents and purposes, starting and running a Symfony app from a single Kernel file can be regarded as a single file application.

即使我们在谈论单个文件应用程序,您也会注意到它实际上不是单个文件–我们确实有一个前端控制器和一个迷你内核,可以完成所有繁重的工作。 这是从vendor加载的所有其他类的补充。 但是,出于所有目的和目的,可以将从单个内核文件启动和运行Symfony应用程序视为单个文件应用程序。

步骤3:核心课程 (Step 3: The Kernel Class)

Create app/SfaKernel.php and add this:

创建app/SfaKernel.php并添加以下内容:

<?php

use Symfony\Component\HttpKernel\Kernel;

class SfaKernel extends Kernel
{
}

Our class should inherit from the Kernel class from Symfony core.

我们的类应该继承自Symfony核心的Kernel类。

Since the Kernel class is an abstract class, our concrete class must implement the registerContainerConfiguration() method. By the way, if you look in the Symfony\Component\HttpKernel\Kernel.php file, you won’t find a registerContainerConfiguration() method – it’s in Symfony\Component\HttpKernel\KernelInterface.php which Kernel itself implements.

由于Kernel类是抽象类,因此我们的具体类必须实现registerContainerConfiguration()方法。 顺便说一句,如果您查看Symfony\Component\HttpKernel\Kernel.php文件,您将找不到registerContainerConfiguration()方法-它位于内核本身实现的Symfony\Component\HttpKernel\KernelInterface.php中。

Here, we are interested in a new feature of Symfony 3 (also available since 2.8), that lets us create a micro-framework and has been aptly named MicroKernelTrait. Inside the class, use this trait:

在这里,我们对Symfony 3的新功能(从2.8开始可用)感兴趣,该功能使我们能够创建微框架,并被恰当地命名为MicroKernelTrait 。 在类中,使用以下特征:

<?php

use Symfony\Component\HttpKernel\Kernel;
use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;

class SfaKernel extends Kernel
{
     use MicroKernelTrait;
}

Now we need to implement three methods in this class – configureRoutes(), configureContainer() and registerBundles(). The first 2 are abstract methods from the trait while registerBundles() is in the Symfony\Component\HttpKernel\KernelInterface which Kernel implements and we, in turn, extend in our micro-kernel. If we take a close look at those methods, we can learn a lot from the comments.

现在,我们需要在此类中实现三种方法configureRoutes()configureContainer()registerBundles() 。 前两个是来自特征的抽象方法,而registerBundles()位于Symfony\Component\HttpKernel\KernelInterface ,由Kernel实现,而我们又在我们的微内核中扩展。 如果我们仔细研究一下这些方法,可以从注释中学到很多东西。

  1. registerBundles()

    registerBundles()

    A bundle in Symfony is a set of files that implement a feature. Other applications or frameworks talk about plugins or modules. The only thing we need at the moment is the Symfony framework itself. The comment says, “Returns an array of bundles to register.”, so our method should look like this:

    Symfony中的捆绑软件是一组实现功能的文件。 其他应用程序或框架谈论插件或模块。 目前,我们唯一需要的就是Symfony框架本身。 评论说: “返回一组捆绑软件进行注册。” ,因此我们的方法应如下所示:

    public function registerBundles()
    {
        return [
            new FrameworkBundle()
        ];
    }
  2. configureRoutes()

    configureRoutes()

    This is where we add or import routes for our application. Routing is looking at the path in the request and determining where to direct it to eventually get a response back. The comment is helpful as usual and it tells us about two ways:

    这是我们为应用程序添加或导入路由的地方。 路由正在查看请求中的路径,并确定将其定向到何处以最终获得响应。 该评论照常有用,它告诉我们两种方法:

    $routes->import('config/routing.yml');

    You add a configuration file where you define your routes and import it here.

    您可以在其中定义路由的位置添加配置文件,并将其导入此处。

    $routes->add('/admin', 'AppBundle:Admin:dashboard', 'admin_dashboard');

    You specify a path (/admin), add a controller class with a method (AppBundle:Admin:dashboard), and optionally give it a name or alias (admin_dashboard).

    您指定路径( /admin ),添加带有方法( AppBundle:Admin:dashboard )的控制器类,并可以选择为其指定名称或别名( admin_dashboard )。

    However, there’s a third way, rather a second way of specifying your controller. For example, 'kernel:home' refers to a method home() in the current kernel class. In effect, this SfaKernel class is doubling as a controller. How nice! Let’s add 2 routes.

    但是,有第三种方法,而不是指定控制器的第二种方法。 例如, 'kernel:home'是指当前内核类中的home()方法。 实际上,此SfaKernel类将作为控制器加倍。 多好! 让我们添加2条路线。

    $routes->add('/', 'kernel:home');

    When we go to our home page, the request will be routed to the home() method in this class.

    当我们转到主页时,该请求将被路由到此类中的home()方法。

    $routes->add('/greet/{who}', 'kernel:greet');

    Similarly, this route will match all requests to /greet/{who} with a route parameter represented by {who} and pass them to a method called greet, with a $who parameter.

    类似地,此路由将使用/greet/{who}表示的路由参数将对/greet/{who}所有请求进行匹配{who}然后将它们传递给带有$who参数的greet方法。

    Let’s go ahead and implement the methods. Once again, make sure you have use Symfony\Component\HttpFoundation\Response; at the top of the class.

    让我们继续实施这些方法。 再次确保您已use Symfony\Component\HttpFoundation\Response; 在全班最高。

    public function home() {
        return new Response(
            '<p>Home, sweet home</p>'
        );
    }
    
    public function greet($who)
    {
        return new Response(
            "<h1>Greeting</h1><p>Hello $who</p>"
        );
    }

    Bear in mind that you need to return a Response object from the methods.

    请记住,您需要从方法中返回Response对象。

  3. configureContainer()

    configureContainer()

    The container holds a wide variety of classes and they often need different parameters or any other configuration passed to them. This is where you register any extensions, services or parameters, e.g.

    容器包含各种各样的类,它们通常需要不同的参数或传递给它们的任何其他配置。 在这里注册任何扩展,服务或参数,例如

    $c->loadFromExtension('framework', array(
           'secret' => '%secret%'
    ));
    
    $c->register('halloween', 'FooBundle\HalloweenProvider');
    
    $c->setParameter('halloween', 'lot of fun');

    The only extension we’ve got is the FrameworkBundle which has a number of configuration options, but only one – secret – is required. They are provided as an associative array keyed by the options. The value of our secret should be unique, so our method should look like this:

    我们获得的唯一扩展是FrameworkBundle,它具有许多配置选项 ,但是只需要一个secret 。 它们作为由选项键控的关联数组提供。 我们的secret的价值应该是唯一的,因此我们的方法应如下所示:

    protected function configureContainer(ContainerBuilder $c, LoaderInterface $loader)
    {
        $c->loadFromExtension('framework', [
            'secret' => 'micr0',
        ]);
    }

Provided you’ve configured your webserver, go to the home page and you should see, Home, sweet home. Append /greet/Symfony to the URL. Hello Symfony should be displayed in the browser.

如果已经配置了Web服务器,请转至主页,您应该看到Home,Sweet home 。 将/greet/Symfony附加到URL。 Hello Symfony应该显示在浏览器中。

You can register as many routes as you wish in registerRoutes() and return a response from this same class. You’ve got a working Symfony single file application.

您可以在registerRoutes()registerRoutes()任意数量的路由,并从同一类返回响应。 您已经有了一个可以正常工作的Symfony单文件应用程序。

Before continuing, let’s go back to the beginning when we first extended the Kernel class. We needed to implement only one method – registerContainerConfiguration(). When we added the MicroKernelTrait, we needed 3 methods.

在继续之前,让我们回到第一次扩展Kernel类的开始。 我们只需要实现一种方法– registerContainerConfiguration() 。 当我们添加MicroKernelTrait时,我们需要3种方法。

If you open Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait.php, you’ll notice that the registerContainerConfiguration() method has been implemented for us, in order to make it more flexible and configurable. Let’s go through it.

如果打开Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait.php ,您会注意到为我们实现了registerContainerConfiguration()方法,以使其更加灵活和可配置。 让我们经历一下。

public function registerContainerConfiguration(LoaderInterface $loader)
{
    $loader->load(function (ContainerBuilder $container) use ($loader) {
        $container->loadFromExtension('framework', array(
            'router' => array(
                'resource' => 'kernel:loadRoutes',
                'type' => 'service',
            ),
        ));

        $this->configureContainer($container, $loader);

        $container->addObjectResource($this);
    });
}

Inside the closure, look at the resource array key for router and you’ll see kernel:loadRoutes. We’ve come across something like this when we looked at specifying a controller class for our route. It’s the same concept here. kernel refers to the class using this trait when extending the Kernel class, and :loadRoutes will look for a method in this trait.

在闭包内部,查看routerresource阵列键,然后将看到kernel:loadRoutes 。 在为路由指定控制器类时,我们遇到了类似的情况。 这里是相同的概念。 kernel在扩展Kernel类时引用使用该特性的类, :loadRoutes将在此特性中寻找一个方法。

public function loadRoutes(LoaderInterface $loader)
{
    $routes = new RouteCollectionBuilder($loader);
    $this->configureRoutes($routes);

    return $routes->build();
}

It’s from this method our configureRoutes() gets called. To make sure it’s implemented in any micro-framework using this trait, it’s been defined as an abstract method.

通过这种方法,我们的configureRoutes()被调用。 为了确保使用此特征在任何微框架中实现,已将其定义为抽象方法。

用例 (Use cases)

Implementing a real-life application in a single file wasn’t the primary goal of the MicroKernelTrait. It’s to give developers more flexibility in how they structure applications, what bundles they add, and when. Instead of a huge package they only use a fraction of, they are able to start off from a very slim installation and progressively build more functionality. Our example has no templating, for example, but it can be easily added.

在单个文件中实现真实的应用程序并不是MicroKernelTrait的主要目标。 这将使开发人员在如何构造应用程序,添加什么捆绑包以及何时添加更多灵活性。 他们无需使用庞大的软件包,而只使用其中的一小部分,而是可以从非常苗条的安装开始,逐步构建更多功能。 例如,我们的示例没有模板,但可以轻松添加。

Others are suggesting building microservices from the MicrokernelTrait based on the full-stack Symfony framework. Another possibility would be the separation of GET requests to be handled by a much leaner application of the MicrokernelTrait while other requests for more resource-intensive processes are managed by a more traditional Symfony application.

其他人则建议基于全栈Symfony框架从MicrokernelTrait构建微服务。 另一种可能性是将GET请求分离,而该请求将由更精简的MicrokernelTrait应用程序处理,而其他对资源密集型过程的请求则由更传统的Symfony应用程序管理。

结论 (Conclusion)

Prior to Symfony 2.8 and 3.0, micro-frameworks such as Silex and Lumen were the available options for projects that had reservations about implementing the full framework. However, the single file application concept has offered another middle ground.

在Symfony 2.8和3.0之前,Silex和Lumen等微框架是那些对实施完整框架有所保留的项目的可用选项。 但是,单一文件应用程序概念提供了另一个中间立场。

This is an exciting thing for Symfony and in the days ahead, one can expect developers to squeeze out ingenious use cases from this new feature. Personally, I hope the vendor folder receives further scrutiny. Should a barebones installation with composer require symfony/symfony really pull in all those dependencies?

对于Symfony来说,这是一件令人兴奋的事情,并且在未来的日子里,可以期望开发人员从这一新功能中挤出精巧的用例。 我个人希望vendor文件夹得到进一步的审查。 使用composer require symfony/symfony的准系统安装是否composer require symfony/symfony真正吸收所有这些依赖项?

It’s still early days but the potential is there, and the direction in which developers are going to take this new feature remains to be seen. Are you using it yet? Let us know!

仍处于初期,但潜力仍然存在,开发人员采用此新功能的方向还有待观察。 你在用吗? 让我们知道!

翻译自: https://www.sitepoint.com/single-file-symfony-apps-yes-with-microkerneltrait/

symfony

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值