Home  >  Article  >  Backend Development  >  Detailed explanation of how PHP implements Hook mechanism

Detailed explanation of how PHP implements Hook mechanism

*文
*文Original
2018-01-05 18:04:052505browse

How does PHP implement the Hook mechanism? This article mainly introduces how to implement the Hook mechanism in PHP, and introduces the principle and implementation process of the Hook mechanism in detail. It has certain reference value, and those who are interested can learn about it. I hope to be helpful.

I’m actually not familiar with the concept of “hook”. I recently saw this mechanism used in a PHP framework to expand projects, so I’ll give it a try.

The so-called Hook mechanism is a technology popular in Windows programming. The main idea is to bury (preset) a hook in advance where functionality may be added. This hook has no practical significance. When we need to re-modify or add logic in this place, mount the extended class or method. Just get to this point.

The basic idea of ​​the hook plug-in mechanism:

In the project code, place a hook function in the place where you think you want to expand (not expand it yet), and wait for the expansion that needs to be done. At this time, you can mount the classes and functions that need to be implemented on this hook to achieve expansion.

The idea sounds so general, let’s look at an online implementation example.

The entire plug-in mechanism consists of three parts:

1.hook plug-in manager class: This is the core file and is an application global Global object. It has three main responsibilities

1>Listen to all registered plug-ins and instantiate these plug-in objects.

2>Register all plug-ins.

3>When the hook condition is met, the corresponding object method is triggered.

2. Plug-in function implementation: This is mostly done by third-party developers, but it needs to follow our (manager class definition) rules. This rule is stipulated by the plug-in mechanism and varies depending on the plug-in mechanism. .

3. Plug-in triggering: that is, the triggering condition of the hook. This is a small piece of code placed where you need to call the plugin to trigger this hook.

----------------------------------Look at other people’s solutions--- --------------------------

The first is the plug-in manager class PluginManager. This class should be placed in the global reference. , where the plug-in is needed, it will be loaded first.

<?php
/**
*
* 插件机制的实现核心类
*/
class PluginManager
{
  /**
   * 监听已注册的插件
   *
   * @access private
   * @var array
   */
  private $_listeners = array();
   /**
   * 构造函数
   *
   * @access public
   * @return void
   */
  public function __construct()
  {
    #这里$plugin数组包含我们获取已经由用户激活的插件信息
   #为演示方便,我们假定$plugin中至少包含
   #$plugin = array(
    #  &#39;name&#39; => &#39;插件名称&#39;,
    #  &#39;directory&#39;=>&#39;插件安装目录&#39;
    #);
    $plugins = get_active_plugins();#这个函数请自行实现
    if($plugins)
    {
      foreach($plugins as $plugin)
      {//假定每个插件文件夹中包含一个actions.php文件,它是插件的具体实现
        if (@file_exists(STPATH .&#39;plugins/&#39;.$plugin[&#39;directory&#39;].&#39;/actions.php&#39;))
        {
          include_once(STPATH .&#39;plugins/&#39;.$plugin[&#39;directory&#39;].&#39;/actions.php&#39;);
          $class = $plugin[&#39;name&#39;].&#39;_actions&#39;;
          if (class_exists($class))
          {
            //初始化所有插件
            new $class($this);
          }
        }
      }
    }
    #此处做些日志记录方面的东西
  }

  /**
   * 注册需要监听的插件方法(钩子)
   *
   * @param string $hook
   * @param object $reference
   * @param string $method
   */
  function register($hook, &$reference, $method)
  {
    //获取插件要实现的方法
    $key = get_class($reference).&#39;->&#39;.$method;
    //将插件的引用连同方法push进监听数组中
    $this->_listeners[$hook][$key] = array(&$reference, $method);
    #此处做些日志记录方面的东西
  }
  /**
   * 触发一个钩子
   *
   * @param string $hook 钩子的名称
   * @param mixed $data 钩子的入参
   *  @return mixed
   */
  function trigger($hook, $data=&#39;&#39;)
  {
    $result = &#39;&#39;;
    //查看要实现的钩子,是否在监听数组之中
    if (isset($this->_listeners[$hook]) && is_array($this->_listeners[$hook]) && count($this->_listeners[$hook]) > 0)
    {
      // 循环调用开始
      foreach ($this->_listeners[$hook] as $listener)
      {
        // 取出插件对象的引用和方法
        $class =& $listener[0];
        $method = $listener[1];
        if(method_exists($class,$method))
        {
          // 动态调用插件的方法
          $result .= $class->$method($data);
        }
      }
    }
    #此处做些日志记录方面的东西
    return $result;
  }
}

The next step is the implementation of DEMO_actions, a simple plug-in. This is a simple Hello World plug-in for outputting a sentence. In actual situations, say_hello may include operations on the database or some other specific logic.

<?php
/**
* 这是一个Hello World简单插件的实现
*/
/**
*需要注意的几个默认规则:
*  1. 本插件类的文件名必须是action
*  2. 插件类的名称必须是{插件名_actions}
*/
class DEMO_actions
{
  //解析函数的参数是pluginManager的引用
  function __construct(&$pluginManager)
  {
    //注册这个插件
    //第一个参数是钩子的名称
    //第二个参数是pluginManager的引用
    //第三个是插件所执行的方法
    $pluginManager->register(&#39;demo&#39;, $this, &#39;say_hello&#39;);
  }

  function say_hello()
  {
    echo &#39;Hello World&#39;;
  }
}

The next step is where the plug-in call is triggered. For example, if I want to put say_hello on the homepage of my blog, Index.php, then you write somewhere in index.php:

$pluginManager->trigger(&#39;demo&#39;,&#39;&#39;);

The first parameter represents the name of the hook, and the second parameter is the entry parameter of the corresponding method of the plug-in. Since there are no input parameters in this example, it is empty.

Such an example basically clearly expresses the implementation method and logic of the "hook" plug-in mechanism.

Related recommendations:

Detailed explanation of PHP high-precision operation BC function library

Detailed explanation of using PHP to find the longest common substring of two strings

Detailed explanation of PHP operating database based on ORM

The above is the detailed content of Detailed explanation of how PHP implements Hook mechanism. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn