Routing is an important link in project development, each project will use routing management interface, the next article will take you to learn routing from the source.

preface

Anyone who has written a project using a framework must use routing. Routing is used for interface management, so why use routing?

Using routing protects the true request path for the project.

Make the request address more standard and concise, in the development process of Chinese law name sometimes very long, you can directly use routing for concise processing.

Interception of request requests and permission checking operations can be unified.

Annotated routing is also supported in version 5.1 for easy debugging during development.

It facilitates direct caching of requests and supports routing middleware.

Next, kakaka will give a comprehensive analysis of all aspects of the route, and will bring you a brain map to facilitate the most intuitive preview.

1. Simple analysis of route identification

In the framework execution process article, we know that route initialization is performed during the initialization of the application.

And then you go to routeInit, and you parse the code.

To get to this method, look at the code comments that define the rules for importing routes.

All of this code I copy out, the next is to parse this code.

/** * Initializes the import route definition rule *@access public
     * @return void
     */
    public function routeInit()
    {
        // Route detection
        // scandir: returns an array of files for the top directory
        $files = scandir($this->routePath);
        foreach ($files as $file) {
            if (strpos($file.'.php')) {
                $filename = $this->routePath . $file;
                // Import the route configuration
                $rules = include $filename;
                if (is_array($rules)) {
                    $this->route->import($rules); }}}if ($this->route->config('route_annotation')) {
            // Automatically generate route definitions
            if ($this->appDebug) {
                $suffix = $this->route->config('controller_suffix') | |$this->route->config('class_suffix');
                $this->build->buildRoute($suffix);
            }

            $filename = $this->runtimePath . 'build_route.php';

            if (is_file($filename)) {
                include $filename; }}}Copy the code

It first retrieves the files in the route directory. Scandir returns the files in the specified directory as an array.

Three results are returned. The first is the current directory and the second is the parent directory. These two numbers don’t need to be investigated too much.

It then imports the PHP ending file in the route directory, the route.php file.

When the routing file is imported, a judgment is made and the import rule is made.

However, you can see in the routing file that no data is returned.

Return demo of routing files

So what does return do? This was not available prior to version 5.1, but it is available in 5.1. Here’s how to use it.

First configure a piece of data in the return of the routing file.

Then create a new method VPN in the index file

In this case, you can directly access the routed VPN.

$this->route->import($rules); This step is not discussed in this section and will be explained in detail later.

Read the second half of the source code

Does the first line of code know where this data came from?

In the initialize method of the application, init is performed, and init is performed to update the configuration of the instance in the container, where it is set. The following figure

So this is the configuration that you add to the route, and you can see that the configuration file for the route is from the app configuration file.

If you want to know what this configuration does, you need to go back to the root, so you need to look in the app configuration file.

You can see that this parameter refers to the annotated route switch.

This is followed by the automatic generation of routing rules based on comments. That’s enough code for now, which will be explained in more detail below.

Second, by defining the route to talk about the facade

Here is just a simple mention, about some of the use of routing and so on can go directly to the document to see, kakaka also do not have to do porters in moving over.

Start by defining a kAKA route in the routing file.

But how does this get method work! The code trace can not directly catch up with the past, so what should be done at this time?

First, all the base classes in the framework are registered with facade patterns, so introducing a facade into the routing allows code tracing.

But since all the source code of the facade mode have seen how to use the first way, certainly some of the small details to scratch out.

The alias of the facade is already registered in the base file, so you can use use Config or use think\facade\Config when importing the file.

This time will come to thinkphp/library/think/facade/Config. The PHP file.

You can see that it inherits the facade class.

Go to the Facade class and drag down to the end of the file to see a method __callStatic that is executed when a non-existent static method is called.

The method to create the facade class will be executed, and the container will return the corresponding instance, such as Config, which will be returned.

Finally, you go back to the beginning, using call_user_func_array to execute the corresponding instance’s methods.

Static ::createFacade() returns the corresponding instance of Config.

This piece of content said here, although said before in the facade also mentioned but here in the review is also very necessary, to know new!

$this->group; $this->group

By defining the route and talking about the facade section, you can see that the Rule method in the figure below executes that method of that class.

According to before kaka to introduce the method to know will eventually perform thinkphp/library/think/Route. The PHP rule in the file.

Here comes a question about what this group is and how it is executed. In fact, the above picture has been clearly described.

Kakaka in the text to say again, can be compared to view the source code.

Let’s see if this method is familiar.

Yes, this method is specifically explained in the container section, so if you don’t understand it, go to the preface and check out the previous article.

So where this method is implemented, ka-ka will directly say, will not say so fine.

When using the Route: : (rule); Is executed to the __callStatic method of the facade.

This method has been stated many times that it is executed when the static method being executed does not exist.

The createFacade method is then implemented.

In this method you need to pay special attention to the last line, which line of code is circled.

Static ::class returns a Route class. Static ::class returns a Route class.

So the first argument to the make method is Route.

You will then go to the make method of the container class, where you notice the two places of the click circle.

Four properties that must be noted in a container class are graphed.

The first entry is stored in the container identifier name.

And the second execution of the make method passes the value of the identifying name.

Until you get to the second point in the ka-ring, you execute the invokeClass method.

Go to the invokeClass method.

The main use in this method is the knowledge of reflection.

The reflection class will first be instantiated with the passed Think \Route.

It then determines whether there is a __make method in think\Route.

Finally, the Route class’s __make method is executed.

And dependency injection App class and Config class.

$route = new static($app, $config);

The constructor will be executed.

Then go to the constructor’s methods.

Be sure to note the comment on step 2 here, which has been said many times.

If in doubt, ArrayAccess is used.

Just to get you straight, the App class inherits the Container class.

The Container class in turn inherits from the ArrayAccess class, so you can access objects like an array, as mentioned earlier.

  • The injected App class
  • ArrayAccess is used to access objects like an array, but there is no request property in $app, so it executes the __get magic method in the container class. In the __get method, it calls the make method in the container. The first argument is request. Eventually, an instance of Request will be returned.
  • The injected Config class
  • This property returns the domain name,
  • Example Initialize the default domain name

And then we go to the method setDefaultDomain.

Note the ka-ring here, the property used at the beginning of this section to execute the addRule method in the rule.

This group is the think\Route\Domain class.

Because think\Route\Domain inherits think\Route\Group

So think\Route\Group is executed into this class.

Now all the procedures have been straightened out.

Through the above analysis and milling we believe that the content of this piece is very well understood.

4. Preprocessing of routing rules

The next step is to parse how routing rules are handled.

Just do a simple print of the first two parameters and see what they are.

Parameters of the rule

Parameter $route

You can see that these two parameters are the first half of the route, and one is the second half of the route.

This tells you that the code executes to the first circle in the figure below.

One thing to note at this point is the second place circled in the figure above. When will this place be executed?

That’s when the graph route is set up like this.

The route Settings here are just for demonstration purposes. You can’t set routes like this in real work. The second routing address overwrites the first.

The code then executes to create the routing rule instance, which is circled below.

The parameters for creating a routing rule instance need to be briefly described

$this->router

$this = think\route\Domain.

The next few addresses are routing rules and addresses, so there is no need to read them, mainly the first parameter.

Next you need to get into the method of creating an instance of the routing rule

Code will be traced to thinkphp/library/think/route/RuleItem PHP in this class.

What you do in this class is set the rules, which are shown in the click circle below.

Routing rule preprocessingsetRuleMethod interpretation.

The last process executed in the figure above comes to the setRule method.

This code is not as container readable as we see it, so let’s go through the code step by step.

1. The code executes this part first

A simple judgment $was made from the beginning, so where did this come from?

In the file thinkphp/library/think/route/RuleGroup PHP was done here for $.

So under what circumstances will the first part of the preprocessing be executed!

Let’s look at a simple case.

Then print in the route preprocessing, you will find that the printed result will be followed by an extra $sign.

Introduce the substr

Here is a brief explanation of substr, and a brief review of every point you encounter.

This method is used for string interception.

Parameter 1: The string to be intercepted

Parameter 2: Where does the truncation start, left to right for positive numbers, end of negative numbers, 0 – at the first character in the string

Parameter 3: length. Positive numbers are returned from parameter 2, negative numbers from the end.

Therefore, the final execution of this code will cancel the $symbol, leaving only a /, and print the result as shown below.

Then the lower part of route preprocessing is analyzed.

I’m going to remove all the slashes on the left.

$this->parent $this->parent $this->parent

This is where the parameters are passed from.

$this->group = think\route\Domain

$this = think\route\Domain $this = think\route\Domain

If you have a problem with this one, go to section 3.

$parent = think\route\Domain

So this piece of code is solved.

So the third section where did not see clearly must take a good look at their own code, otherwise the more back the more do not understand.

$this->parent $this->parent $this->parent

And then there’s this piece of code that does two things to the reason argument.

Converts the parameter with the: symbol.

For example: :name is converted to

.

$this->rule =

Quick access to parse generated route identifiers

The next step after the routing rules is to generate quick access to the route id.

Variables in routing rules

But we need to do a little bit more about the variables in the routing rules.

The area circled below is what will be parsed.

Came to parseVar this method, the method is in thinkphp/library/think/route/Rule. The PHP in this class, because this class inheritance Rule class.

So the next step is to elaborate on this whole block.

The first thing to understand is what the three arguments to preg_match_all are.

Parameter 1: the string to search for

Parameter 2: The input string

Parameter 3: multi-dimensional array, output all matching results as an output parameter, array sorting specified by flags.

So the final match is stored in the $matches variable.

So let’s print the $matches variable.

There is a PHP version that needs to be addressed.

The following figure shows the routing example used this time

Kakaka had a bit of a problem printing this value, the data cannot be displayed using dump in PHP7.3.4, but will be displayed under Dubug debugging.

Dump is displayed in PHP version 7.2.9.

On this question, kaka will first bypass, if there is a big guy know the situation can give kaka a simple Lao Lao, here kaka will use PHP7.2.9 to explain.

Later period kakaka is in the light of this problem to undertake simple explanation, encounter a problem to need to solve!

So do you know that

< p style =” max-width: 100%; If you don’t know, look at the picture below.

Here to say once ha!

The preg_replace method has been changed in different versions, and the regex aspect has been changed.

So once that’s done, the rest of the code is just drizzle!

This is the basis, right? Judge for the first time.

In the routing case given by kaka above, I believe you have also seen another route that is very similar to the case.

These two groups of routing parameters are mandatory parameters and optional parameters respectively.

Clicking in a printed screenshot only illustrates one case, and the other is something you need to test.

The result will eventually be returned to $var, and we’ll just print out the return values for both cases.

Case 1: the Route: : get (‘ hello / [: name] ‘, ‘index/index/hello);

Route::get(‘hello/:name’, ‘index/index/hello’);

This leads to the conclusion that the parameter is 2 when optional and 1 when required.

So much for dealing with variables in routing rules.

This code is not too difficult, as long as you know preg_match_all and strpos and substr.

Quick access to parse generated route identifiers

So let’s move on.

Click the circle below is not to see for the time being, in the next article will be separately put forward to talk about this piece.

So then we need to look at a $value and see what that value is.

The following figure is the printed result, which includes routing rules, whether parameters are optional, request domain name and request mode.

Container::get(‘rule_name’)->set($name, $value, $first); That’s this line of code.

The parameter is rule_name.

Then execute the make method because rule_name is bound to the container class.

Finally, the object(Think \route\RuleName) is returned by reflection and stored in the container.

$this->instances[‘think route\RuleName’] = object(think route\RuleName); $this->instances[‘think route\RuleName’] = object(think route\RuleName);

The last step is to set the routing rules.

At this point, the quick access to the route identifier is resolved.

With nearly half of the routing section left, this article is a bit too long to write

That’s the end of this article, and the next one will move on to the rest of routing.

Six, summarized

In this paper, mainly for the implementation of routing process, through the definition of routing in a way to the facade.

At the same time, the group in the rule method is explained in particular in detail, which must be well studied, and the inheritance between classes must be paid attention to.

In is about the preprocessing of routing rules, is to process the first half of the route.

It is mainly the following three sentences.

Converts the parameter with the: symbol.

For example: : Name is converted to.

$this->rule =

This is followed by a quick access to the source code of the birth route identifier reading, in this section the most important is to deal with variables.

Check whether the parameter is optional or not. 2 is optional, and 1 is not optional.

Here is a map of the brain drawn by kaka.

This brain map is not yet complete, and there is more to come, which will be added in detail below.

Finally, I will show you this diagram, which is the most detailed implementation process.

The execution relationships between classes are described in detail in the diagram.

Adhering to learning, blogging and sharing is the belief that Kakha has been upholding since she started her career. I hope the articles on the Internet can bring you a little help. I’m Kaka. See you next time.