“This paper mainly introduces the implementation process of the framework
”
Preface
If you don't know how the framework works , So, in many codes, it's just to know the code , Reading the source code is to learn the design ideas and code patterns of its framework .
And the execution process is to link the things we learn together , To better understand . Kaka will also show you the execution process in the way of mind map .
As long as you learn a little bit of knowledge in this article , Kaka is also contented .
This flow chart is only for initialize Implementation process of , The rest of the execution process will be supplemented later , It's all presented in the form of brain maps .
One 、 The data setting of initialization application of framework execution process
The content here is a little bit similar to that of the container , Because the execution process starts from the entry file , And finally, it's done through the container .
And then it goes to the file thinkphp/library/think/App.php
Of run Method , In this method, the main part is the following box , Executive initialize Method .
Came to initialize This method , Let's look at the first half .
-
microtime(true);
The return is unix Microseconds of -
memory_get_usage
The return is assigned to PHP Of memory , The unit is byte -
Next, set up several paths of the framework -
static::setInstance($this);
Here is the general app This instance is set to the container instance -
$this->instance('app', $this);
This was mentioned in the previous chapter on containers , Just to put app This class is bound to the container , That's the registration tree model .
Here is a small question for you to raise , In the method of initializing the application, there is such a line of code .
There's no partner for this $this->env
At the bottom of the and $this->config
These two calls have doubts .
If you're in doubt, follow Kaka , If you don't have any doubts, you can continue to look down .
App This class is an inherited container class , So this env and config Whether in app still container Class does not have these two properties .
So how can I call it directly ! And code tracking will trace back to env Classes and container Class .
We need to know the source and we need to go over it container Class code .
After a hard study , You can see a few lines of code below . These lines of code are all magic .
When accessing env When the class does not exist make Method .
make This method can't be interpreted in detail in the chapter of container .
This make Method will eventually return an instance of a class , And it will be stored in the container .
There's only one make Method code , If there is not, you can read the previous article .
Finally, load a series of data , Please refer to the mind map in the preface for loading details .
Two 、 How to see where a method is executed
In the process of reading the source code , One problem that is hard to control is that a method is called in different places , But we really don't know where to call it for a while and a half .
Here we use init Method to do a demonstration .
init Method is a method of initializing an application or module , But here module The parameter does have a null value .
First make a breakpoint to see the relevant data information .
The printed result is empty , This is a mistake some new learning partners will make , Because this method cannot be called only once .
If the initialization module is empty, then there is no need for this method to exist .
This should be the right way to do it .
There will be a problem , This init The method is obviously called twice , So where is the next call !
If you don't know the new technique , A series of breakpoints will be printed , See where it's executed , Like here init To print on top of .
That is to say initialize In that method, print and make breakpoints , But it's troublesome , And it's possible to waste a lot of time and still not find the right place .
The trick is debug_backtrace()
This method produces a backtracking , All call locations of a method are displayed .
How to use it is shown in the following figure , Only need to debug_backtrace This method can be printed out .
Based on the data obtained , It can be very fast positioning .
The first time was in app Class 215 That's ok .
The second time was in thinkphp/library/think/route/dispatch/Module.php
Class 60 That's ok
You can make a print here , Take a look at this module Is it index
So with this method, you can locate the call location very quickly .
3、 ... and 、 Initialization application of framework execution process init analysis
Here's a tip for you debug_backtrace
The actual combat demonstrates how to see where a method is executed .
And the case is also used init This method is used to demonstrate , Because the next step is to deal with init This is a way to get a deeper understanding of .
stay init The main thing to do in the method is described clearly in the above brain map .
-
Positioning the module from the beginning , That's right in the second verse init Method call , The corresponding module will be passed in -
load app In the catalog tags file , stay tags Inside the file is the file that defines the behavior extension . The hook execution defined in the previous facade article is set in this file . -
load common file , Public documents , So public files are loaded here . -
Load helper function file helper, In the helper function, there is a method that we are particularly familiar with , That's it dump. That's why it's used in some places dump Reasons for reporting errors . -
Load middleware file , The direct here is direct loading app The middleware file under Directory , But in the framework we need to define a directory as http, Define middleware files in this directory . -
Register the container object instance of the service , The registration here uses the container class bindTo
Method for binding registration . -
Read configuration file , This paragraph has been explained in detail in the section of loading configuration file , I won't mention it here . The configuration file will be read in two places. One is under the first step module config file , The other is config The configuration file under the directory . -
Set module path , The module obtained in the first step will be carried out env
In the environment variable configuration -
The last step is to update the configuration of the object instance in the container , What has been updated in the following article will be detailed to you .
/**
* Initialize an application or module
* @access public
* @param string $module Module name
* @return void
*/
public function init($module = '')
{
// Locate the module directory
$module = $module ? $module . DIRECTORY_SEPARATOR : '';
/**
* for the first time :D:\phpstudy_pro\WWW\ThinkPHPSourceCodeAnalysis\application\
* The second time :D:\phpstudy_pro\WWW\ThinkPHPSourceCodeAnalysis\application\index\
*/
$path = $this->appPath . $module;
// Load initialization file
if (is_file($path . 'init.php')) {
include $path . 'init.php';
} elseif (is_file($this->runtimePath . $module . 'init.php')) {
include $this->runtimePath . $module . 'init.php';
} else {
// Load behavior extension file
if (is_file($path . 'tags.php')) {
$tags = include $path . 'tags.php';
if (is_array($tags)) {
$this->hook->import($tags);
}
}
// Load public file
if (is_file($path . 'common.php')) {
include_once $path . 'common.php';
}
if ('' == $module) {
// Loading system helper functions
include $this->thinkPath . 'helper.php';
}
// Loading middleware
if (is_file($path . 'middleware.php')) {
$middleware = include $path . 'middleware.php';
if (is_array($middleware)) {
$this->middleware->import($middleware);
}
}
// Register the container object instance of the service
if (is_file($path . 'provider.php')) {
$provider = include $path . 'provider.php';
if (is_array($provider)) {
$this->bindTo($provider);
}
}
/**
* $path : "D:\phpstudy_pro\WWW\ThinkPHPSourceCodeAnalysis\application\"
* "D:\phpstudy_pro\WWW\ThinkPHPSourceCodeAnalysis\application\index\"
*/
// Auto read configuration file
if (is_dir($path . 'config')) {
$dir = $path . 'config' . DIRECTORY_SEPARATOR;
} elseif (is_dir($this->configPath . $module)) {
// D:\phpstudy_pro\WWW\ThinkPHPSourceCodeAnalysis\config\
$dir = $this->configPath . $module;
}
// scandir: Read the files in the directory in ascending order
// Return is config All files in directory
$files = isset($dir) ? scandir($dir) : [];
foreach ($files as $file) {
/**
* $this->configExt: The suffix of the configuration file
* pathinfo The file suffix is returned , About pathinfo There are three optional parameters PATHINFO_DIRNAME、PATHINFO_BASENAME、PATHINFO_EXTENSION, Return only the file name , File directory name , File extension
*/
if ('.' . pathinfo($file, PATHINFO_EXTENSION) === $this->configExt) {
/**
* The two parameters are
* 1. Catalog +config A file in a directory
* 2.config Directory file name
*/
$this->config->load($dir . $file, pathinfo($file, PATHINFO_FILENAME));
}
}
}
$this->setModulePath($path);
if ($module) {
// Update the configuration of the object instance in the container
$this->containerConfigUpdate($module);
}
}
Here comes a code , You can look at the code above the execution process , Each step is explained briefly .
Kaka personal opinion to optimize the source code
The code click in setting up the module is not very strict , because init Methods are executed in two places .
The first module is empty , This code execution is meaningless .
Next, we make a judgment when updating the configuration of the object instance of the container , Judge whether this parameter of the module is empty , If it is not empty, it will be executed .
So the same thing , I feel that setting the module path should also be in this judgment .
Although the second execution will cover the first result , But it's better to use it in this way .
Four 、 Update the object instance in the container
In the last section, this is the last thing , Then update the configuration of the instance , What's new , How to update is not explained .
It will be explained in this section , You can also look at it with the mind map of the preface .
-
First of all config All configuration information under the directory is obtained -
from app The exception handling class will be registered in the configuration file -
The third block is to register and configure all the configuration information obtained in the first step to the corresponding class . -
The fourth step is to load the corresponding language pack after determining the module , Language pack function can realize multi language function , I've written an article about multilingualism before , If you are interested, you can check it out . -
The last step is based on app The three attributes in the configuration file are used for cache processing
In this section, the most important feeling is the content in the figure below .
We can trace one or two methods at will to see what's going on there .
Tracking methods Db::init()
When the tracking method comes over, you can see that it's right Db Class config Property to assign , hold database Assign the value in to Db Class config attribute .
Tracking methods $this->middleware->setConfig()
Come to the middleware class , You can see that the configuration of this class is merged with the parameter class passed in , It's also going on config Assignment of a property .
Follow the example above Db Class init The effect of method implementation is consistent .
It's in the middle of Update the object instance in the container
In this picture, you can see that the purple part is not referenced in this class .
So how can this be implemented ! Because App Class inherits the container class , There are four magic methods in the container class , One of them __get Method , That method is executed when getting properties that do not exist .
In the magic method __get A method is executed make Method , This make The method has been said many times , This method will eventually return an instance of the application , Then use this instance to call the method of the corresponding instance class .
This part must be understood well , Reading the source code is like this , We need to solve all the unknowns , Only in this way can we improve our programming ability and thinking .
5、 ... and 、 On debugging mode and code redundancy
This section gives a brief description of debugging mode , And the redundancy of framework code will be simply proposed .
No one writes code that has no holes , If there is, then you have not reached certain attainments .
Debug mode
In the first section, we only mention initialize The first half of the method , Because all the talk before this section is about application initialization init The content of .
Next, you will give a brief explanation of the content of this piece .
-
from app From the configuration file app_debug Configuration item for -
Set the environment variable debug Level -
When... In the frame debug It will be executed when it is closed ini_set This method , This method is to assign a value to a configuration option .
The following content is not easy to understand , They are usually not used at work .
-
ob_get_level: Returns the nesting level of the output buffer mechanism , So how to understand ! In fact, when the cache does not work, it will return 0. -
ob_get_clean: This function will return the contents of the output buffer and terminate the output buffer . If the buffer has no valid content, it returns false. In essence, it is equivalent to executing at the same time ob_getcontens() and ob_end_clean(). -
ob_start: Turn on the output control buffer
Let's get to know these three for a while , Later, if you have the opportunity, you will have an article to explain .
About framework code redundancy
This is just a personal view of Kaka .
You can take a look at this part of the code first , These two codes are not very familiar , That's right. That's right init Method in the container object instance configuration update, see .
Pictured
This is the personal opinion of Kaka , Because the click is aimed at 5.1 Do the source code interpretation , I don't know if there are any changes in the new edition .
6、 ... and 、 summary
This section mainly discusses the initialization application in the framework execution process .
As for the app Class run There are also a lot of execution procedures under the method, which are not explained too much in this section .
In the process of reading the source code, I gave you a very good little skill , That's how to see where a method is executed .
This method is debug_backtrace
, You need to use this method several times to know how to use it , Because there is a lot of useless information in the printed results .
This method is very effective in debugging the source code , Make good use of this method .
In is the initialization application init The method is introduced in detail .
Among them, the best design is to update and configure the object instance in the container , Read all the configuration first , Then, the configuration settings are made through the methods of each class .
This code planning and design idea is worth learning .
Finally, we talk about the code redundancy of debugging mode and framework , About debugging mode, here we give you a wake-up project, online debugging mode must be turned off .
Otherwise, your project is similar to the existence of streaking , There's no safety at all .
What's a little hard to understand is the buffer , About this content, Kaka thinks that there is no need to go to the top for the time being , First of all, we should know and understand, and then we should carry out in-depth research .
This content of buffer is estimated to have worked for three or four years, and few people use it , So get to know it first , Know what's going on , After studying in the later stage of Kaka, I will give you a supplement .
Until here, the initialization application of the framework's execution process is finished , There is nothing to learn in this section , It is mainly the code design pattern and implementation ideas .
Finally, we must follow the source code to see the picture !
“Keep learning 、 Keep blogging 、 To insist on sharing is the belief that khaka has been holding since he was employed . I hope the articles in the Internet can bring you a little help . I'm Kaka , See you next time .
”