From Apprentice To Artisan 翻译 15

Authentication 身份认证

Authentication may be extended the same way as the cache and session facilities. Again, we will use the extend method we have become familiar with:

身份认证模块的扩展方式和缓存与会话的扩展方式一样:使用我们熟悉的extend方法就可以进行扩展:


Auth::extend('riak', function($app)
{
    // Return implementation of Illuminate\Auth\UserProviderInterface
});

The UserProviderInterface implementations are only responsible for fetching a UserInterface implementation out of persistent storage system, such as MySQL, Riak, etc. These two interfaces allow the Laravel authentication mechanisms to continue functioning regardless of how the user data is stored or what type of class is used to represent it.

接口UserProviderInterface负责从各种持久化存储系统——如MySQL,Riak等——中获取数据,然后得到接口UserInterface的实现对象。有了这两个接口,Laravel的身份认证机制就可以不用管用户数据是如何储存的、究竟哪个类来代表用户对象这种事儿,从而继续专注于身份认证本身的实现。

Let's take a look at the UserProviderInterface:

咱们来看一看UserProviderInterface接口的代码:


interface UserProviderInterface {
    public function retrieveById($identifier);
    public function retrieveByCredentials(array $credentials);
    public function validateCredentials(UserInterface $user, array $credentials);
}

The retrieveById function typically receives a numeric key representing the user, such as an auto-incrementing ID from a MySQL database. The UserInterface implementation matching the ID should be retrieved and returned by the method.

方法retrieveById通常接受一个数字参数用来表示一个用户,比如MySQL数据库的自增ID。该方法要找到匹配该ID的UserInterface的实现对象,并且将该对象返回。

The retrieveByCredentials method receives the array of credentials passed to the Auth::attempt method when attempting to sign into an application. The method should then “query” the underlying persistent storage for the user matching those credentials. Typically, this method will run a query with a “where” condition on $credentials['username']. This method should not attempt to do any password validation or authentication.

retrieveByCredentials方法接受一个参数作为登录帐号。该参数是在尝试登录系统时从Auth::attempt方法传来的。那么该方法应该“查询”底层的持久化存储系统,来找到那些匹配到该帐号的用户。通常该方法会执行一个带有“where”条件的查询来匹配参数里的$credentials['username']该方法不应该做任何密码验证。

The validateCredentials method should compare the given $user with the $credentials to authenticate the user. For example, this method might compare the $user->getAuthPassword(); string to a Hash::make of $credentials['password'].

validateCredentials方法会通过比较$user参数和$credentials参数来检测用户是否通过认证。比如,该方法会调用$user->getAuthPassword();方法,将得到的字符串与$credentials['password']经过Hash::make处理后的结果进行比对。

Now that we have explored each of the methods on the UserProviderInterface, let's take a look at the UserInterface. Remember, the provider should return implementations of this interface from the retrieveById and retrieveByCredentials methods:

现在我们探索了UserProviderInterface接口的每一个方法,接下来咱们看一看UserInterface接口。别忘了UserInterface的实例应当是retrieveByIdretrieveByCredentials方法的返回值:


interface UserInterface {
    public function getAuthIdentifier();
    public function getAuthPassword();
}

This interface is simple. The getAuthIdentifier method should return the “primary key” of the user. In a MySQL back-end, again, this would be the auto-incrementing primary key. The getAuthPassword should return the user's hashed password. This interface allows the authentication system to work with any User class, regardless of what ORM or storage abstraction layer you are using. By default, Laravel includes a User class in the app/models directory which implements this interface, so you may consult this class for an implementation example.

这个接口很简单。 getAuthIdentifier方法应当返回用户的“主键”。就像刚才提到的,在MySQL中可能就是自增主键了。getAuthPassword方法应当返回经过散列处理的用户密码。有了这个接口,身份认证系统就可以不用关心用户类到底使用了什么ORM或者什么存储方式。Laravel已经在app/models目录下,包含了一个默认的User类且实现了该接口。所以你可以参考这个类当例子。

Finally, once we have implemented the UserProviderInterface, we can ready to register our extension with the Auth facade:

当我们最后实现了UserProviderInterface接口后,我们可以将该扩展注册进Auth里面:


Auth::extend('riak', function($app)
{
    return new RiakUserProvider($app['riak.connection']);
});

After you have registered the driver with the extend method, you switch to the new driver in your app/config/auth.php configuration file.

使用extend方法注册好驱动以后,你就可以在app/config/auth.php配置文件里面切换到新的驱动了。

IoC Based Extension 使用容器进行扩展

Almost every service provider included with the Laravel framework binds objects into the IoC container. You can find a list of your application's service providers in the app/config/app.php configuration file. As you have time, you should skim through each of these provider's source code. By doing so, you will gain a much better understanding of what each providers adds to the framework, as well as that keys are used to bind various services into the IoC container.

Laravel框架内几乎所有的服务提供者都会绑定一些对象到IoC容器里。你可以在app/config/app.php文件里找到服务提供者列表。如果你有时间的话,你应该大致过一遍每个服务提供者的源码。这么做你便可以对每个服务提供者有更深的理解,明白他们都往框架里加了什么东西,对应的什么键。那些键就用来联系着各种各样的服务。

For example, the PaginationServiceProvider binds a paginator key into the IoC container, which resolves into Illuminate\Pagination\Environment instance. You can easily extend and override this class within your own application by overriding this IoC binding. For example, you could create a class that extend the base Environment:

举个例子,PaginationServiceProvider向容器内绑定了一个paginator键,对应着一个Illuminate\Pagination\Environment的实例。你可以很容易的通过覆盖容器绑定来扩展重写该类。比如,你可以创建一个扩展自Environment类的子类:


namespace Snappy\Extensions\Pagination;
class Environment extends \Illuminate\Pagination\Environment {
    //
}

Once you have created your class extension, you may create a new SnappyPaginationProvider service provider class which overrides the paginator in its boot method:

子类写好以后,你可以再创建个新的SnappyPaginationProvider服务提供者来扩展其boot方法,在里面覆盖paginator:


class SnappyPaginationProvider extends PaginationServiceProvider {
    public function boot()
    {
        App::bind('paginator', function()
        {
            return new Snappy\Extensions\Pagination\Environment;
        }

        parent::boot();
    }
}

Note that this class extends the PaginationServiceProvider, not the default ServiceProvider base class. Once you have extended the service provider, swap out the PaginationServiceProvider in your app/config/app.php configuration file with the name of your extended provider.

注意这里我们继承了PaginationServiceProvider,而非默认的基类ServiceProvider。扩展的服务提供者编写完毕后,就可以在app/config/app.php文件里将PaginationServiceProvider替换为你刚扩展的那个类了。

This is the general method of extending any core class that is bound in the container. Essentially every core class is bound in the container in this fashion, and can be overridden. Again, reading through the included framework service providers will familiarize you with where various classes are bound into the container, and what keys they are bound by. This is a great way to learn more about how Laravel is put together.

这就是扩展绑定进容器的核心类的一般方法。基本上每一个核心类都以这种方式绑定进了容器,都可以被重写。还是那一句话,读一遍框架内的服务提供者源码吧。这有助于你熟悉各种类是怎么绑定进容器的,都绑定的是哪些键。这是学习Laravel框架到底如何运转的好方法。

Request Extension 请求的扩展

Because it is such a foundational piece of the framework and is instantiated very early in the request cycle, extending the Request class works a little differently than the previous examples.

由于这玩意儿是框架里面非常基础的部分,并且在请求流程中很早就被实例化,所以要扩展Request类的方法与之前相比是有些许不同的。

First, extend the class like normal:

首先还是要写个子类:


namespace QuickBill\Extensions;
class Request extends \Illuminate\Http\Request {
    // Custom, helpful methods here...
}

Once you have extended the class, open the bootstrap/start.php file. This file is one of the very first files to be included on each request to your application. Note that the first action performed is the creation of the Laravel $app instance:

子类写好后,打开bootstrap/start.php文件。该文件是应用的请求流程中最早被载入的几个文件之一。要注意被执行的第一个动作是创建Laravel的$app实例:


$app = new \Illuminate\Foundation\Application;

When a new application instance is created, it will create a new Illuminate\Http\Request instance and bind it to the IoC container using the request key. So, we need a way to specify a custom class that should be used as the “default” request type, right? And, thankfully, the requestClass method on the application instance does just this! So, we can add this line at the very top of our bootstrap/start.php file:

当新的应用实例创建后,它将会创建一个Illuminate\Http\Request的实例并且将其绑定到IoC容器里,键名为request。所以我们需要找个方法来将一个自定义的类指定为“默认的”请求类,对不对?而且幸运的是,应用实例有一个名为requestClass的方法就是用来干这事儿的!所以我们只需要在bootstrap/start.php文件最上面加一行:


use Illuminate\Foundation\Application;
Application::requestClass('QuickBill\Extensions\Request');

Once you have specified the custom request class, Laravel will use this class anytime it creates a Request instance, conveniently allowing you to always have an instance of your custom request class available, even in unit test!

一旦你指定了自定义的请求类,Laravel将在任何时候都可以使用这个Request类的实例。并使你很方便的能随时访问到它,甚至单元测试也不例外!

你可能感兴趣的:(From Apprentice To Artisan 翻译 15)