Date: 2017-12-10 22:24:18 Title: Laravel source code interpretation

Yii/Laravel source code quality is extremely high, phper must read

Source code reading: naotu.baidu.com/file/9d4b5a…

Recently wrote a few blog is very long, in detail, the foundation of the students will look a little more comfortable, but the foundation of some of the students will feel not deep enough, the dry goods are not enough. And writing a long article is really very tired, so this article tries to grasp the framework structure, the overall structure and ideas, details of the point, and then slowly share with you.

lifecycle

Those of you who are familiar with me will know that I particularly emphasize this concept. The life cycle is a good bridge between the specific business and the underlying implementation. Being familiar with the life cycle can cultivate both software engineering ability and business understanding ability.

The important thing is an infinite cycle: the life cycle.

Laravel’s life cycle:

Initialize the

  • use$basePathInitialization (new) Illuminate\Foundation\ApplicationThe Application class is actually a container used to resolve class dependencies, followPSRstandard
  • Application binding (bind) 3 singletons:App\Http\Kernel.App\Console\Kernel.App\Exceptions\HandlerThe request is executed by a specific Kernel. Containers are used to resolve class dependenciesOn demandIt’s all declared hereThe singletonNote here the bright spot in Laravel: the binding is in accordance withIlluminate\Contracts\Xxx -> App\xxxConstraint to achieve global unity. Contract we’ll talk more about later.

The specific process

  • Based on the scenario (Web/console), instantiate (make) to the corresponding Kernel
  • Kernel instantiation process, first enter the bootstrap stage:registerServiceProvider, which is executed by ApplicationregisteredIs a mustRelationship thatIt’s actually done by the containerOn demandLoad.
  • Use information in the PHP Global variable to initialize the Request object, for example$_SERVER
  • The Kernel processes the Request object and returns a Response object
  • Finally, the Kernel terminates ()

Kernel Processes the Request process

  • Start with the defined Middleware
  • Pass it to the Router for processing: route matching, logical processing to the closure/Controller, and return data
  • Assemble the data returned above and assemble it into a Response object based on some other configuration, such as format

You will find that you are not familiar with MVC, because MVC also has Application to manage each object, and so do all other services.

With the Container foundation and an understanding of the lifecycle, you can populate the code on demand for your business.

Contract Contract

Life cycles and containers are basically the same for modern frameworks, so let’s talk about laravel’s differences — Contract.

Here are two programming ideas:

Interface oriented programming

Convention greater than Configuration

The fact that these two ideas overlap underscores the need for separation of definition and implementation in system design specifications.

Laravel is always doing this, always defining first, where all the functionality that the framework provides can be found. Some people like to say shadows.

More generally: I don’t care how, just do what I say.

Yeah, that’s the way it is, you have to dance in chains.

In Laravel, defining a function/service goes through the following sequence of steps:

  • Contract defines interfaces
  • Foundation defines the base implementation, a number of traits, and the basic functionality associated with the service
  • To implement specific functions or services, you need to follow the definition in the Contract, add the ServiceProvider, and register the service with the Container
  • Support provides some general auxiliary methods that are independent of specific services or services for the implementation of specific functions or services

Once this is done, we can use $app[‘ XXX ‘] as defined in the register() method of XxxServiceProvider to access the desired service.

Such as:

// AuthServiceProvider protected function registerAuthenticator() { $this->app->singleton('auth', function ($app) { // Once the authentication service has actually been requested by the developer // we will set a variable in the application indicating such. This helps us // know that we need to set any queued cookies in the after event later. $app['auth.loaded'] = true; return new AuthManager($app); }); $this->app->singleton('auth.driver', function ($app) { return $app['auth']->guard(); }); $Auth = $app[' Auth ']Copy the code

As a reminder, it is common to set a class attribute $app to the Application at framework initialization, so that all dependencies can be handled using the $app variable in a concise and simple way.

Why is Laravel so comfortable to write

The title is actually intended to explain Laravel’s slogan:

Love beautiful code? We do too. The PHP Framework For Web Artisans

Now that we have all the core features we need, the rest is up to us. $app[‘auth’] calls the registered auth service.

DI

DI, dependency injection, dependency injection This is a common way:

/** * Handle a registration request for the application. ** @param \Illuminate\Http\ request $request * @return \Illuminate\Http\Response */ public function register(Request $request) { $this->validator($request->all())->validate(); event(new Registered($user = $this->create($request->all()))); $this->guard()->login($user); return $this->registered($request, $user) ? : redirect($this->redirectPath()); }Copy the code

Simply pass the desired class \Illuminate\Http\Request $Request in the function argument, and the container will automatically provide it for us to use

helper function

Let’s start with the helper function in a broad sense, which is implemented by automatic loading of Composer:

// laravel/framework/src/composer.json
"autoload": {
    "files": [
        "src/Illuminate/Foundation/helpers.php",
        "src/Illuminate/Support/helpers.php"
    ],
    "psr-4": {
        "Illuminate\\": "src/Illuminate/"
    }
},
Copy the code

As you can see here, Laravel registers two classes of helper functions:

  • Foundation/helpers.php: help functions related to framework functionality
  • Support/helpers.phpGeneric help functions that are independent of the framework’s functions, such as array handling and string handling

Here are the helper functions related to framework functionality:

Function app($abstract = null, array $parameters = []) { if (is_null($abstract)) { return Container::getInstance(); $app} return Container::getInstance()->make($abstract, $parameters); / / equivalent to the above $} [' auth '] / / app using effect app () - > $app app (' auth ') - > $app [' auth ']Copy the code

To see how convenient this is, take the cache service as an example:

Function cache() {$arguments = func_get_args(); if (empty($arguments)) { return app('cache'); } if (is_string($arguments[0])) { return app('cache')->get($arguments[0], $arguments[1] ?? null); } if (! is_array($arguments[0])) { throw new Exception( 'When setting a value in the cache, you must pass an array of key / value pairs.' ); } if (! isset($arguments[1])) { throw new Exception( 'You must specify an expiration time when setting a value in the cache.' );  } return app('cache')->put(key($arguments[0]), reset($arguments[0]), $arguments[1]); } // use effect cache($key); $key ($value); // Set the cacheCopy the code

Is hin convenient?

Facade

Facade design pattern: Hides detailed objects through Facade wrapping to reduce application complexity

To see how this works, use the same Cache as above:

\Cache::get($key);
\Cache::set($key, $value);
Copy the code

It’s a little bit more complicated than the helper function, so we’ll do it at the end. Let’s look at how the Facade is implemented.

Set a new Facede according to the official documentation:

  • Go to theconfig/app.phpYou can also register the ServiceProvider here
  • Create a new Facede class that inherits fromIlluminate\Support\Facades\Facade

For example, the Cache Facade here:

namespace Illuminate\Support\Facades; Class Cache extends Facade {protected static function getFacadeAccessor() {return 'Cache '; }}Copy the code

What’s the mechanism? Continue with the code for Illuminate\Support\Facades\Facade:

Public static function __callStatic($method, $args) {$instance = static::getFacadeRoot(); $app['cache'] if (!) $app['cache'] if (! $instance) { throw new RuntimeException('A facade root has not been set.'); } return $instance->$method(... $args); }Copy the code

So, execute \Cache::get($key); $app[‘cache’]->get($key);

At this point, you will find that in fact, it is all around $app, packaged, to achieve a variety of different writing methods.

A comparison of the three ways

Let’s start with DI and Facade. I don’t know if you have the same question as me:

Public function index(Request $Request) {$input = $Request ->all(); } public function index() { $input = Request::all(); }Copy the code

When we write a Request, the editor will prompt two items: \Illuminate\Http\Request and \Request. At the beginning, I was puzzled about this place for a long time. Now you can distinguish it. One is DI and the other is Facade, but the names are the same.

This example also shows the difference between DI and Facade.

Let’s take a look at the Facade and helper function, some of which have been mentioned above. At least the above example looks a little cleaner, but this is limited:

Cache::get($key, $timeout); Cache ()->get($key, $timeout); $app[' Cache ']; $app[' Cache ']; $app[' Cache ']Copy the code

Do you feel a little dizzy with so many ways to achieve it, or is it like official art?

With more freedom in writing (shorthand), productivity gains are noticeable.

Of course, shorthand brings up a problem with code hints, which can affect productivity, as can be seen in my previous blog – talk about PHP code hints.

Let’s do one last routine

The Cache service, for example, can be used in many ways, but we use the same way, how to implement this?

  • First of all, Contract, I don’t care how it’s implemented, it’s what I said, it’s all the way through, okay
  • Laravel, however, uses it when there are multiple ways to implement itmanager-driverThis way,

Take the Cache service as an example:

Public function register() {$this->app->singleton('cache'); $this->app->singleton('cache'); Function ($app) {return new CacheManager($app); return new CacheManager($app); }); $this->app->singleton('cache.store', function ($app) {return $app['cache']->driver(); }); . $app['cahe']->get($key); Actually eventually perform $this - > store () - > get ($key) public function __call ($method, $parameters) {return $this - > store () - > $method (... $parameters); } public function store($name = null) { $name = $name ? : $this->getDefaultDriver(); return $this->stores[$name] = $this->get($name); }Copy the code

$name = $this->store(); $this->store();

This manager-driver approach is widely used in Laravel, such as Filesystem, Notification, and Queue

Write in the last

Write to write to find is a long, simply heart tired, it is very simple things ah, look at the code bit by bit to read it, write up the text but to bala bala so much.

It’s a simple thing, figure out the lifecycle and the underlying implementation, and read the rest bit by bit