scrapy立面parse

tech2022-09-03  115

scrapy立面parse

The Facade pattern is a software design pattern which is often used in object oriented programming. A facade is, in fact, a class wrapping a complex library to provide a simpler and more readable interface to it. The Facade pattern can also be used to provide a unified and well-designed API to a group of complex and poorly designed APIs.

Facade模式是一种软件设计模式,通常用于面向对象的编程中。 实际上,外观是包装复杂库以为其提供更简单和可读性的接口的类。 Facade模式还可用于为一组复杂且设计不良的API提供统一且设计良好的API。

The Laravel framework has a feature similar to this pattern, also termed Facades. In this tutorial we will learn how to bring Laravel’s “Facades” to other frameworks. Before we continue, you need to have a basic understanding of Ioc containers.

Laravel框架具有类似于此模式的功能,也称为Facades。 在本教程中,我们将学习如何将Laravel的“外观”引入其他框架。 在继续之前,您需要对Ioc容器有基本的了解。

Let’s first go through the inner working parts of Laravel’s facades, and then we’ll discuss how we can adapt this feature to the other environments.

首先,让我们看一下Laravel立面的内部工作部分,然后讨论如何使此功能适应其他环境。

Laravel的外墙 (Facades in Laravel)

A Laravel facade is a class which provides a static-like interface to services inside the container. These facades, according to the documentation, serve as a proxy for accessing the underlying implementation of the container’s services.

Laravel门面是一个类,它为容器内的服务提供类似静态的接口。 根据文档,这些外观可以用作访问容器服务的基础实现的代理。

There have been many debates in the PHP community about this naming, though. Some have argued that the term should be changed in order to avoid confusion of developers, as it doesn’t fully implement the Facade pattern. If this naming confuses you, feel free to call it whatever feels right to you, but please note that the base class that we’re going to use is called Facade in the Laravel framework.

但是,PHP社区中有很多关于这种命名的争论。 有人认为应更改该术语以避免开发人员的困惑,因为它并未完全实现Facade模式。 如果这种命名使您感到困惑,请随意对其进行命名,但是请注意,我们将要使用的基类在Laravel框架中称为Facade 。

Laravel中如何实施外墙 (How Facades Are implemented in Laravel)

As you probably know, every service inside the container has a unique name. In a Laravel application, to access a service directly from the container, we can use the App::make() method or the app() helper function.

您可能知道,容器内的每个服务都有一个唯一的名称。 在Laravel应用程序中,要直接从容器访问服务,我们可以使用App::make()方法或app()帮助器函数。

<?php App::make('some_service')->methodName();

As mentioned earlier, Laravel uses facade classes to make services available to the developer in a more readable way. By using a facade class, we would only need to write the following code to do the same thing:

如前所述,Laravel使用外观类以更易读的方式使开发人员可以使用服务。 通过使用Facade类,我们只需编写以下代码即可完成相同的操作:

// ... someService::methodName(); // ...

In Laravel, all services have a facade class. These facade classes extend the base Facade class which is part of the Illuminate/Support package. The only thing that they need to implement is the getFacadeAccessor method, which returns the service name inside the container.

在Laravel中,所有服务都有一个Facade类。 这些外观类别扩展了基础外观类别,该类别是Illuminate/Support软件包的一部分。 他们唯一需要实现的就是getFacadeAccessor方法,该方法返回容器内的服务名称。

In the above syntax, someService refers to the facade class. The methodName is in fact a method of the original service in the container. If we look at this syntax outside of the context of Laravel, it would mean that there’s a class named someService exposing a static method named methodName(), but that’s not how Laravel implements this interface. In the next section, we’ll see how Laravel’s base Facade class works behind the scenes.

在以上语法中, someService引用Facade类。 methodName实际上是容器中原始服务的方法。 如果我们在Laravel上下文之外查看此语法,则意味着存在一个名为someService的类, someService暴露了一个名为methodName()的静态方法,但这不是Laravel实现此接口的方式。 在下一节中,我们将了解Laravel的基础Facade类在幕后的工作方式。

基础立面 (Base Facade)

The Facade class has a private property named $app which stores a reference to the service container. If we need to use facades outside of Laravel, we have to explicitly set the container using setFacadeApplication() method. We’ll get to that shortly.

Facade类具有一个名为$app的私有属性,该属性存储对服务容器的引用。 如果需要在Laravel之外使用外观,则必须使用setFacadeApplication()方法显式设置容器。 我们将尽快解决。

Inside the base facade class, the __callStatic magic method has been implemented to handle calling of static methods which don’t actually exist. When we call a static method against a Laravel facade class, the __callStatic method is invoked, because the facade class hasn’t implemented that method. Consequently, __callStatic fetches the respective service from the container and calls the method against it.

在基础外观类内部,已实现__callStatic魔术方法,以处理实际不存在的静态方法的调用。 当我们针对Laravel外观类调用静态方法时,会调用__callStatic方法,因为外观类尚未实现该方法。 因此, __callStatic从容器中获取相应的服务并针对该容器调用方法。

Here is the implementation of the __callStatic method in the base facade class:

这是基础外观类中__callStatic方法的实现:

<?php // ... /** * Handle dynamic, static calls to the object. * * @param string $method * @param array $args * @return mixed */ public static function __callStatic($method, $args) { $instance = static::getFacadeRoot(); switch (count($args)) { case 0: return $instance->$method(); case 1: return $instance->$method($args[0]); case 2: return $instance->$method($args[0], $args[1]); case 3: return $instance->$method($args[0], $args[1], $args[2]); case 4: return $instance->$method($args[0], $args[1], $args[2], $args[3]); default: return call_user_func_array([$instance, $method], $args); } }

In the above method, getFacadeRoot() gets the service from the container.

在以上方法中, getFacadeRoot()从容器获取服务。

外墙类的剖析 (Anatomy of a Facade Class)

Each facade class extends the base class. The only thing that we need to implement is the getFacadeAccessor() method. This method does nothing but return the service’s name in the container.

每个外观类都扩展了基类。 我们唯一需要实现的就是getFacadeAccessor()方法。 该方法除了在容器中返回服务的名称外什么也不做。

<?php namespace App\Facades; use Illuminate\Support\Facades\Facade as BaseFacade; class SomeServiceFacade extends BaseFacade { /** * Get the registered name of the component. * * @return string */ protected static function getFacadeAccessor() { return 'some.service'; } }

别名 (Aliases)

Since Laravel facades are PHP classes, we need to import them before we can use them. Thanks to the namespaces and autoloading support in PHP, all classes are automatically loaded when we access them by the fully-qualified name. PHP also supports aliasing of classes by using the use directive:

由于Laravel外墙是PHP类,因此我们需要先导入它们,然后才能使用它们。 得益于PHP中的命名空间和自动加载支持,当我们使用完全限定的名称访问它们时,所有类都会自动加载。 PHP还通过使用use指令支持类的别名:

use App\Facades\SomeServiceFacade SomeServiceFacade:SomeMethod();

However, we have to do this in each and every script where we need that particular facade class. Laravel handles the aliasing of facades in its own way by using an alias loader.

但是,我们必须在需要该特定外观类的每个脚本中执行此操作。 Laravel通过使用别名加载器以自己的方式处理外墙的别名。

Laravel如何使门面别名 (How Laravel Aliases the Facades)

All alias names are kept in an aliases array inside the app.php config file, which is located inside the /config directory.

所有别名名称都保存在app.php配置文件(位于/config目录中)内的aliases数组中。

If we take a look at the array, we can see that each alias name is mapped to a fully-qualified class name. This means we can use any name that we wish for a facade class:

如果我们看一下数组,可以看到每个别名都映射到一个完全限定的类名。 这意味着我们可以为外观类使用任意名称:

// .. 'aliases' => [ // ... 'FancyName' => 'App\Facades\SomeServiceFacade', ],

Okay, now let’s see how Laravel uses this array for aliasing the facade classes. In the bootstrapping phase, Laravel uses a service named AliasLoader which is part of the Illuminate\Foundation package. AliasLoader takes the aliases array, iterates over all the elements, and creates a queue of __autoload functions using PHP’s spl_autoload_register. Each __autoload function is responsible for creating an alias for the respective facade class by using PHP’s class_alias function.

好的,现在让我们看看Laravel如何使用该数组为Facade类进行别名。 在引导阶段,Laravel使用名为AliasLoader的服务,该服务是Illuminate\Foundation软件包的一部分。 AliasLoader使用aliases数组,遍历所有元素,并使用PHP的spl_autoload_register创建__autoload函数队列。 每个__autoload函数负责通过使用PHP的class_alias函数为相应的外观类创建别名。

As a result, we won’t have to import and alias the classes before using them as we normally do with the use directive. So whenever we try to access a class that doesn’t exist, PHP will check the __autoload queue to get the proper autoloader. By that time, AliasLoader has already registered all the __autoload functions. Each autoloader takes a fancy class name and resolves it to the original class name according to the aliases array. Finally, it creates an alias for that class. Consider the following method call:

结果,我们将不需要像以前通常use指令那样导入和别名化类。 因此,每当我们尝试访问一个不存在的类时,PHP都会检查__autoload队列以获取正确的自动加载器。 到那时, AliasLoader已经注册了所有__autoload函数。 每个自动装带器都使用特殊的类名,并根据aliases数组将其解析为原始类名。 最后,它为该类创建一个别名。 考虑以下方法调用:

<?php // FancyName is resolved to App\Facades\SomeServiceFacade according to the aliases array FancyName::someMethod()

Behind the scenes, FancyName is resolved to App\Facades\SomeServiceFacade.

在幕后, FancyName解析为App\Facades\SomeServiceFacade 。

在其他框架中使用外墙 (Using Facades in Other Frameworks)

Okay, now that we have a good understanding of the way Laravel handles its facades and aliases, we can adapt Laravel’s facade approach to other environments. In this article, we’re going to use facades in the Silex framework. However, you can adapt this feature to other frameworks as well by following the same concept.

好的,现在我们对Laravel处理其外观和别名的方式有了很好的了解,我们可以将Laravel的外观方法适应其他环境。 在本文中,我们将在Silex框架中使用Facades。 但是,您也可以通过遵循相同的概念将此功能适应于其他框架。

Silex has its own container, as it extends Pimple. To access a service inside the container, we can use the $app object like so:

Silex在扩展Pimple拥有自己的容器。 要访问容器内的服务,我们可以使用$app对象,如下所示:

<?php $app['some.service']->someMethod()

With the help of facade classes, we can provide a static-like interface to our Silex services as well. In addition to that, we can use the AliasLoader service to make meaningful aliases for those facades. As a result, we would be able to refactor the above code like so:

在外观类的帮助下,我们也可以为Silex服务提供类似静态的接口。 除此之外,我们可以使用AliasLoader服务为这些外观创建有意义的别名。 结果,我们将能够像上面那样重构上面的代码:

<?php SomeService::someMethod();

要求 (Requirements)

To use the the base facade class, we need to install the Illuminate\Support package using composer:

要使用基础外观类,我们需要使用composer安装Illuminate\Support软件包:

composer require illuminate\support

This package contains other services as well, but for now we just need its base Facade class.

该软件包还包含其他服务,但是现在我们只需要其基础Facade类。

创建立面 (Creating the Facades)

To create a facade for a service, we just need to extend the base Facade class and implement the getFacadeAccessor method.

要为服务创建外观,我们只需要扩展基础Facade类并实现getFacadeAccessor方法即可。

For this tutorial, let’s keep all the facades under src/Facades path. As an example, for a service named some.service, the facade class would be as follows:

对于本教程,让我们将所有立面都保留在src/Facades路径下。 例如,对于名为some.service的服务,facade类将如下所示:

<?php namespace App\Facades use Illuminate\Support\Facades\Facade; class SomeServiceFacade extends Facade { /** * Get the registered name of the component. * * @return string */ protected static function getFacadeAccessor() { return 'some.service'; } }

Please note that we have namespaced the class under app\facades.

请注意,我们已在app\facades下为该类命名空间。

The only thing that remains is setting the application container on the facade class. As pointed out earlier, when we call a method in a static context against a facade class, __callStatic is triggered. _callStatic uses data returned by getFacadeAccessor() to identify the service inside the container and tries to fetch it. When we’re using the base Facade class outside of Laravel, the container object isn’t set automatically, so we will need to do this manually.

剩下的唯一事情是在Facade类上设置应用程序容器。 如前所述,当我们在静态环境中针对Facade类调用方法时,会触发__callStatic 。 _callStatic使用getFacadeAccessor()返回的数据来识别容器内的服务,并尝试获取该服务。 当我们在Laravel外部使用Facade基类时,容器对象不会自动设置,因此我们需要手动执行此操作。

To do this, the base facade class exposes a method named setFacadeApplication which sets the application container for that facade class.

为此,基础Facade类公开了一个名为setFacadeApplication的方法,该方法为该Facade类设置应用程序容器。

In our app.php file, we need to add the following code:

在我们的app.php文件中,我们需要添加以下代码:

<?php Illumiante\Support\Facade::setFacadeApplication($app);

This will set the container for all the facades which are extending the base facade class.

这将为扩展基础立面类的所有立面设置容器。

Now, instead of accessing the service from our container, we can use the facade class we just created, also allowing us to call all methods in a static context.

现在,我们可以使用刚创建的Facade类,而不是从容器中访问服务,还可以在静态上下文中调用所有方法。

实施别名 (Implementing the Aliases)

To alias the facade classes, we’re going to use the AliasLoader that we introduced earlier. Aliasloader is part of the illuminate\foundation package. We can either download the whole package or just borrow the code and keep it as a file.

为了给Facade类起别名,我们将使用前面介绍的AliasLoader 。 Aliasloader是illuminate\foundation软件包的一部分。 我们可以下载整个程序包,也可以只借用代码并将其保存为文件。

If you just want to copy the source file, I suggest you keep it under src/Facades. You can namespace the AliasLoader class based on your project’s architecture.

如果只想复制源文件,建议将其保留在src/Facades 。 您可以根据项目的体系结构为AliasLoader类命名空间。

For this example, let’s copy the code and namespace it under app/facades.

对于此示例,我们将代码复制并在app/facades下命名空间。

创建别名数组 (Creating the Aliases Array)

Let’s create a file in our config directory called aliases.php and put the alias-facade bindings in there like so:

让我们在config目录中创建一个名为aliases.php的文件,并在其中放置alias-facade绑定,如下所示:

<?php return [ 'FancyName' => 'App\Facades\SomeService', ];

FancyName is a name that we want to use instead of App\Facades\SomeService.

FancyName是我们要使用的名称,而不是App\Facades\SomeService 。

注册别名 (Registering the Aliases)

AliasLoader is a singleton service. To create or get the alias loader’s instance, we need to call the getInstance method with the array of aliases as an argument. Finally, to register all the aliases, we need to call its register method.

AliasLoader是单例服务。 要创建或获取别名加载器的实例,我们需要使用别名数组作为参数来调用getInstance方法。 最后,要注册所有别名,我们需要调用其register方法。

Again in the app.php file, add the following code:

再次在app.php文件中,添加以下代码:

<?php // ... $aliases = require __DIR__ . '/../../config/aliases.php'; App\Facades\AliasLoader::getInstance($aliases)->register();

And that’s all there is to it! Now we can use the service like so:

这就是全部! 现在我们可以像这样使用该服务:

<?php FancyName::methodName();

结语 (Wrapping Up)

A Facade class only needs to implement the getFacadeAccessor method which returns the service name inside the container. Since we’re using this feature outside of the Laravel environment, we have to explicitly set the service container using the setFacadeApplication() method.

Facade类仅需要实现getFacadeAccessor方法,该方法将返回容器内的服务名称。 由于我们在Laravel环境之外使用此功能,因此必须使用setFacadeApplication()方法显式设置服务容器。

To refer to the facade classes, we either have to use the fully-qualified class names or import them with PHP’s use directive. Alternatively, we can follow Laravel’s way of aliasing the facades by using an alias loader.

要引用Facade类,我们要么使用完全限定的类名,要么使用PHP的use指令导入它们。 另外,我们可以通过使用别名加载器来遵循Laravel的对外观进行别名的方法。

Questions? Comments? Leave them below! Thanks for reading!

有什么问题吗 注释? 把它们留在下面! 谢谢阅读!

翻译自: https://www.sitepoint.com/how-laravel-facades-work-and-how-to-use-them-elsewhere/

scrapy立面parse

最新回复(0)