Understanding hook hooks and using hooks to extend the behavior under thinkphp
What is a hook function
Personal understanding: Hooks are like a "trap", "listener", when a sends a message to B, when the message has not reached the destination B, the hook interception call out part of the code to do processing, this part of the code is called the hook function or callback function
Refer to the online statement
For example, we use the mouse to double-click on a window, or to a window to enter a letter A;
The first to discover these events is not the window, but the system!
Then the system tells the window: Hey! You got a point, and you've got two mouse clicks, what are you going to do?
Or the system tells the window: Hey! Someone threw bricks at your house, don't believe you look, that brick is a.
At this point the window is ignored for some events and responds to some events:
For example, the mouse click event may be ignored, the window wants to: you click I do not matter, exhausted you I am not responsible;
But once anyone wants to double-click me, I will act immediately, give you some color to see see!
The action that the window prepares to take is the event we have written in advance.
In the words of Windows, the event of a window is the message that the system sends to the window; The action that the window takes (the event code) is the callback function of the window >.
But! Often walls have ears. The system will be notified to the window "words" (messages), may be another guy (such as a thief) in advance to listen to >!
It is possible that this thief is specialized in such information, thieves know, often in the window before the action taken!
And the thief will take a different action plan for different news, and its action plan is generally ready;
Of course, the thief is not interested in any news, the information is not interested in the need to develop a corresponding action plan.
Summary: This "thief" is the hook we want to set; The "Thief" 's "Action Plan" is a hook function, or a callback function called a hook.
The above paragraph of the original link http://www.cnblogs.com/del/archive/2008/02/25/1080825.html
In general, hooks are like a "mount point" that hangs onto a function, and when the function is executed, the mount point (hook) pulls a piece of code out of the load point. For example, we pass in a few parameters to the script, and then insert the operation, we have a hook before inserting (Before_insert) is listen, when the function executes to this hook, will go through the hook to adjust the inside of a piece of code, We can verify or process the data in this part of the hook function to achieve the desired operation.
Why use Hooks
Since the hook is a listener, call a part of the code through the hook to do processing, then I directly in the script to write another function A and then in the execution of function B to call A is not good?
Personally, the hook function is more secure and convenient than invoking another function directly in the function. When we need to modify the extension function, we do not need to modify the hooks in function B, just modify the code block inside the hook, and if you modify function a directly, the class of function B is changed frequently. Violates the principle of closure. Another point, the use of hooks for later maintenance and functional expansion more convenient.
Using hooks in thinkphp (behavior extension)
The use of hooks in TP is actually an extension of behavior.
Behavior
behavior (Behavior) is a relatively abstract concept that you can imagine as an action or a process in the execution of an application, where each position can have a behavior, such as a route detection is a behavior, a static cache is a behavior, User rights detection is also behavior, large to business logic, small to browser detection, multi-language detection and so can be regarded as a behavior, even say you want to give your site users the first access to pop hello,world! These can be seen as a behavior where the presence of the behavior allows you to change or add functionality to the perimeter by extending or configuring it without altering the framework and application.
And the different behavior also has the position common, for example, some behavior's function position all is before the application executes, some behavior is after the template output, we call these behavior function the place to be labeled (bit), when the application runs to this label, will be intercepted, Uniform execution of related behaviors
The behavior here is equivalent to the hook function, want to "use" it, we must rely on hooks hook
Add behavior Extension
There is a systematic behavior extension in thinkphp, and in lib\think\app.class.php, there is this function
/** * Shortcut method used to run the application instance portal file * @access public * @return void */ Static PublicfunctionRun() {//Apply Initialize tagHook::listen (' App_init '); App::init ();//Apply start tagHook::listen (' App_begin ');//Session initialization if(!IS_CLI) {Session (C (' Session_options ')); }//Record application initialization timeG' Inittime '); App::exec ();//Apply end tagHook::listen (' App_end ');return; }
Which inside of the Hook::listen (' App_init '), Hook::listen (' App_begin '); These tags are equivalent to the hook monitoring (these tags are the system built-in behavior, no need to register ). to trigger custom behavior, you must first register the behavior, which provides autoenrollment and manual registration in thinkphp.
Automatic registration
TP inside Lib\think directory below Think.class.php There are these two lines of code
//load mode behavior definition if (isset ( $mode [ Span class= "hljs-string" > ' tags ' ]) {Hook::import (Is_array ( $mode [ ' tags ' ])? $mode [ ' tags ' ]:include $mode [ ' tags ' ]); } //load app behavior definition if (Is_file (conf_path.< Span class= "hljs-string" > ' tags.php ' )) //allow app to add development mode configuration definition Hook::import (include conf_path. tags.php ' );
Mode behavior is built into the system and we can find it in lib\mode\common.php
//Behavior extension definition ' tags '=Array(' App_init '=Array(' Behavior\buildlitebehavior ',//Generate run Lite file),' App_begin '=Array(' Behavior\readhtmlcachebehavior ',//Read static cache),' App_end '=Array(' Behavior\showpagetracebehavior ',//page trace display),' View_parse '=Array(' Behavior\parsetemplatebehavior ',//Template parsing supports PHP, built-in template engine, and third-party template engine),' Template_filter '=Array(' Behavior\contentreplacebehavior ',//Template output substitution),' View_filter '=Array(' Behavior\writehtmlcachebehavior ',//write static cache), ),
User-defined behavior extensions need to be created in Conf_path. ' tags.php ', which is/common/conf/tags.php, for example
return array( "action_begin" => array('Home\\Behaviors\\testBehavior') //一个标签可以有多个行为,我们也可以这样 "action_begin" => array('Home\Behaviors\test1Behavior','Home\\Behaviors\\test2Behavior')); ?>
The TP loads these behaviors automatically at run time. We just have to write our own behavior extension and then listen to it somewhere (Hook::listen tags), and we can trigger these behaviors.
Manual Registration
Speaking of which, let's take a look at the lib\think\hook.class.php code first.
/** * Dynamically add plugins to a tag * @param string $tag tag name * @param mixed $name plug-in name * @return /c3> void * / Static Public function add($tag,$name) { if(!isset( Self::$tags[$tag])){ Self::$tags[$tag] =Array(); }if(Is_array ($name)){ Self::$tags[$tag] = Array_merge ( Self::$tags[$tag],$name); }Else{ Self::$tags[$tag][] =$name; } }
The code is very simple, we only need Hook::add (Tags,name) to register the behavior
Note: Here the name must be a class containing a namespace path, such as Home\behavior\testbehavior, the class name must be followed by the end of Behavior, and the Run method must be implemented in the class. Reason: See the code in the Hook class
/** * Executes a plugin * @param string $name plug-in name * @param String $tag method name * @param Mixed $params parameters passed in * / Static Public function exec($name, $tag,&$params=null) { //This intercepts the post eight-bit class name string, so it must be behavior if(' Behavior '= = substr ($name,-8) ){//if (' testbehavior ' = = substr ($name, -12) // { //$tag = ' test '; // } //Behavior extension must use the Run entry method $tag=' Run '; }Echo $name.'
';$addon=New $name();return $addon-$tag($params); }
Of course, you can also modify the rules, such as I do not want to behavior to the end of the class name, and do not want to call the Run method, this time I want to modify only in the Listen () method inside the judgment changes, if directly in the exec () changes, immediately error, Because the system's built-in behavior is according to this rule! Unless you get rid of the behavior class name and behavior method in the source code, of course I'm sure you're not so stupid.
Other matters:
- The key method of triggering behavior is the Listen method in the hook class that instantiates and invokes the Run method by iterating through all the behaviors under a behavior label
- In the Listen method, if debug mode was previously turned on in the configuration file, it would generate a log of your behavior, which involves a lot of IO operations, so it is recommended to cancel the debug mode to improve the speed when your project is completed.
- In the Listen method, arguments are allowed and only one parameter is allowed (which can be used as an array), but the argument is a reference value, so only the variable is passed in, and the passed-in constant will give an error.
- Finally, lib\think\behavior.class.php, there is only one abstract method run () in this abstract class, and it is recommended to inherit it in your own behavior extension, although this is not necessary, but it is more canonical ... However, TP built-in system behavior did not inherit this abstract class, do not know what
Process and examples
The process of triggering a behavior extension with hooks:
- Autoenrollment (common/conf/tags.php is added in the format itself), or manually registered (class methods such as the initial method, call Hook::add (Tags,name));
- Write your own behavior class, the class name end with behavior, implement the Run method
- In the function that needs to add the behavior, the direct Hook::listen (Tags,prarm), the attention must pass the variable, does not need to pass the constant.
So, the whole process is over, and here's an example.
Example
I recently wrote a personal website (small blog) http://www.huangtianer.com/
I need to record the site's PV, so I basecontroller inside the initialization method
class BaseController extends Controller{ publicfunction _initialize() { //记录访问 //这里我是手动注册的行为 Hook::add('mark_pv','Home\Behaviors\testBehavior'); hook::listen('mark_pv'); }}
And then I'll home\behaviors\testbehavior.class.php.
class testbehavior extends Behavior { Public function run(&$param) { //Record Data $data[' Client_ip '] = Get_client_ip ();$data[' Page_view '] = Controller_name.'/'. Action_name;$data[' Create_time '] = time ();$data[' status '] =0; M' Page_view ')->add ($data); }}
After the normal insertion of data, and if the later my personal site database due to the traffic is too large (hehe) can not record the PV, I directly delete the code inside the hook function, do not need to move the hook, solve the problem, more convenient.
Conclusion: If there are bugs or suggestions, please correct me.
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.