鉤子系統

From Dolibarr ERP CRM Wiki
Jump to navigation Jump to search
The printable version is no longer supported and may have rendering errors. Please update your browser bookmarks and please use the default browser print function instead.


簡介

Hooks 是一項開發功能,允許開發人員將自定義代碼添加到Dolibarr的標準頁面,而無需修改Dolibarr的核心文件。與連結到Dolibarr事件的 觸發系統(與Dolibarr代碼交互的另一種方式)不同,Hooks可以預埋在Dolibarr核心代碼的任何時間、任何地點運行。這些是程序中的插入點(被視為代碼執行從當前頁面「轉移」並運行自定義代碼,然後返回的點)。

每個Hook都有一個名字,例如,代碼:$reshook=$hookmanager->executeHooks('doActions',$parameters,$object,$action)中的「doActions」;然而,Hook的名稱通常不是唯一的(可能在各種代碼模塊中重複使用),因此為了準確識別位置,代碼模塊具有一個「上下文」名稱,該名稱將被該代碼模塊位置中的所有Hooks引用。因此,要使用Hooks,您需要知道它的上下文名稱(位置)和Hooks名稱。

  • Hook是否處於活動狀態取決於上下文(通常每個模塊有一個上下文:例如,產品模塊的「productcard」,發票模塊的「invoicecard」等等)。要查找現有的Hooks,請在php文件中搜索「initHooks(」。

這將找到諸如「$hookmanager->initHooks(array('thirdpartycomm','globalcard'));」的結果,其中「thirdpartycomm」是上下文名稱

  • Hooks是用於插入或替換標準代碼的函數。要查找可以覆蓋的代碼,請搜索「executeHooks(」。找不到就可能沒有預埋Hook,所以你可以添加自己的Hook(並在Github中提交相應的拉取請求,以便將其包含在未來的版本中)。

這將找到諸如「$reshook = $hookmanager->executeHooks('addMoreBoxStatsCustomer', $parameters, $object, $action);」的結果,其中「addMoreBoxStatsCoustomer」是Hook名稱。

添加/預埋hook點以允許插入代碼

要在您自己的模塊中預埋hook(以便您的模塊可以被其他模塊「掛接」),您需要執行兩個步驟。

這些步驟必須為模塊中要預埋hook的每個PHP腳本複製。當然,這也是hook在每個核心Dolibarr模塊中實現的方式。

1 - 初始化HookManager對象

對於一個頁面,將這段代碼放在PHP腳本的開頭(在 main 的 include 之後):

// Initialize technical object to manage hooks of thirdparties. Note that conf->hooks_modules contains array array
include_once(DOL_DOCUMENT_ROOT.'/core/class/hookmanager.class.php');
$hookmanager=new HookManager($db);
$hookmanager->initHooks(array('context'));

$hookmanager->initHooks() 接受1個參數(上下文數組),並啟用此腳本的鉤子支持。

- 'context' 是包含執行上下文的字符串。這是一個簡單的指示符,鉤子函數可以使用它來檢測何時調用它們(多個頁面/模塊可以在不同的位置調用同一個鉤子,而一個鉤子函數可能只想為一個給定的上下文運行,而不想為其他上下文運行)。

注意:您可以同時放置多個上下文(例如,如果您需要多個頁面共享一個上下文,但也需要特定於給定頁面的上下文)。

對於方法或函數,可以通過以下方式獲取鉤子管理器:

global $hookmanager;

2 - 然後將

$parameters=array();
$reshook=$hookmanager->executeHooks('hookname',$parameters,$object,$action); // See description below
// Note that $action and $object may have been modified by hook
if (empty($reshook))
{
   ... // standard code that can be disabled/replaced by hook if return code > 0.
}

調用放置在允許添加代碼的位置:

$parameters=array();
$reshook=$hookmanager->executeHooks('hookname',$parameters,$object,$action); // See description below
// Note that $action and $object may have been modified by hook
if (empty($reshook))
{
   ... // standard code that can be disabled/replaced by hook if return code > 0.
}

$hookmanager->executeHooks() 接受4個參數並添加鉤子(這是腳本和模塊外部函數的腳本入口點):

- 'hookname' 是將被調用的hook的名稱(可以是您想要的任何內容,也可以遵循 Dolibarr 的命名法,查看下面的鉤子列表)。例如:「formObjectOptions」

- $parameters 是一個自定義數組,用於向鉤子傳遞更多自定義數據(鉤子中的函數可以處理這些數據)。把你想要的放在這裡,它可以是一個文件、一個字符串數組、或任何東西...

例如:

$parameters=array('file'=>'my/path/to/a/file', 'customnames'=>array('henry','david','john'));

- $object 是您要傳遞給鉤子函數的對象,通常是當前模塊的數據(例如,如果您在發票模塊中,則是發票對象等)。它可以是您想要的任何東西,但請記住,它將是鉤子函數使用的主要組件。

- $action 是一個指示當前操作的字符串(可以是null或類似於「create」或「edit」的內容)。

注意:如果要在腳本的不同位置添加多個鉤子,則需要多次重複此步驟。

現在您的模塊應該可以被掛接了,您可以按照下面的實現鉤子中的過程來實現一個鉤子函數,該函數將利用您剛才添加的hook(還可以測試它是否有效)。

實現Hook

要使用鉤子(即添加或覆蓋部分代碼),必須首先定義模塊描述符(請參閱模塊開發#創建模塊描述符(必做))。然後,您必須執行以下步驟:

1 - 將模塊添加到鉤子應該運行的上下文中。這意味著,在給定的上下文中,將調用您的代碼。為此,請編輯模塊的描述符(/htdocs/yourmodulename/core/modules/modYourModuleName.class.php),並輸入變量$this->module_parts,如示例所示:

$this->module_parts = array(
'hooks' => array('hookcontext1','hookcontext2')  // Set here all hooks context you want to support
);

不要忘記將 YourModuleName 更改為您自己的模塊名稱!

注意:可以通過添加以下內容來查找模塊的上下文:

print('Module context: '.$object->context);

(將這段代碼添加到鉤子調用所在的PHP文件中,並在檢索到上下文值後將其刪除)。

Warning.png 警告:不要忘記在模塊管理界面中禁用和重新激活模塊,以便使更改生效。因為當您將新的上下文名稱添加到

$this->module_parts = array(
'hooks' => array('hookcontext1','hookcontext2')  // Set here all hooks context you want to support
);

時,此上下文列表必須存儲在資料庫中。僅當啟用自定義模塊時,才會發生這種情況。 因此,當您添加/刪除/修改/重命名任何上下文名稱時,您必須禁用並啟用自定義模塊才能使更改生效。

2 - 用您的函數替換現有函數(重載)

在模塊中創建 /htdocs/yourmodulename/class/actions_yourmodulename.class.php,代碼包含鉤子調用的方法(該方法的名稱在調用executeHooks時可見)。下面是一個例子:

class ActionsYourModuleName
{ 
	/**
	 * Overloading the doActions function : replacing the parent's function with the one below
	 *
	 * @param   array()         $parameters     Hook metadatas (context, etc...)
	 * @param   CommonObject    &$object        The object to process (an invoice if you are in invoice module, a propale in propale's module, etc...)
	 * @param   string          &$action        Current action (if set). Generally create or edit or null
	 * @param   HookManager     $hookmanager    Hook manager propagated to allow calling another hook
	 * @return  int                             < 0 on error, 0 on success, 1 to replace standard code
	 */
	function doActions($parameters, &$object, &$action, $hookmanager)
	{
		$error = 0; // Error counter
		$myvalue = 'test'; // A result value

		print_r($parameters);
		echo "action: " . $action;
		print_r($object);

		if (in_array('somecontext', explode(':', $parameters['context'])))
		{
		  // do something only for the context 'somecontext'
		}

		if (! $error)
		{
			$this->results = array('myreturn' => $myvalue);
			$this->resprints = 'A text to show';
			return 0; // or return 1 to replace standard code
		}
		else
		{
			$this->errors[] = 'Error message';
			return -1;
		}
	}
}

然後,在調用包含executeHooks的代碼時,將自動調用該方法,executeHooks為您的代碼提供參數 $parameters、$Object和$action。

參數:

  • $parameters 是一個集成鉤子數據的元數據數組(其上下文可通過 $parameters['context'] 訪問,但根據具體情況,其他信息可能可用)。
  • $object 是您要處理的對象(例如,productcard上下文中的product)
  • $action 指定要執行的操作(例如 "create", "edit" or "view")。
  • $hookmanager 傳遞它只是為了讓您的鉤子可以調用其他鉤子。

返回值:

  • 執行成功時掛鈎的返回代碼必須為0或1;錯誤時為負數。

返回0。如果後續的核心模塊代碼被包裹於 if (empty($reshook)) {...},它將正常執行,但數據由自定義函數修改。

返回1。如果後續的核心模塊代碼被包裹於 if (empty($reshook)) {...},它根本不會執行。這意味著你的鉤子所做的完全取代了Dolibarr在調用鉤子後所做的。

返回負數。則可以通過設置 $this->errors[]='Error message to report to user' 向用戶提供錯誤消息。

  • 如果該方法將一個數組賦給屬性 $this->results,則數組 $hookManager->resArray 將自動加載該數組的內容,以便以後重用。
  • 如果該方法將一個字符串賦給屬性 $this->resprints ,則該字符串將在方法退出時由掛接處理程序(executeHook)列印出來。
  • 您的鉤子還可以更改$object和$action的值。

Dolibarr中可用的Hooks清單

要查找Dolibarr中可用的掛鈎點,只需在原始碼中搜索「executeHooks(」即可,您將很容易找到所有已預埋的掛鈎點。

以下是一個可用的掛鈎點清單(不完整):Category:Hooks...

請注意:此清單會隨著版本升級而不斷增長,因此如果您真的想知道是否存在特定的鉤子或上下文,請使用上面列出的方法直接搜索原始碼。

Dolibarr中可用的上下文清單

要查找Dolibarr中可用的上下文,查找過程類似於查找掛鈎點。

在原始碼中搜索「initHooks(」,您將很容易找到所有已實現的上下文。

這是其中的一小部分(不完整):

adherents\card.php(111): membercard
adherents\type.php(73): membertypecard
categories\categorie.php(96): categorycard
comm\card.php(72): commcard
comm\propal.php(99): propalcard
comm\action\card.php(85): actioncard
comm\action\index.php(112): agenda
comm\mailing\card.php(55): mailingcard
commande\card.php(93): ordercard
compta\facture.php(105): invoicecard
compta\paiement.php(70): paiementcard
compta\deplacement\card.php(50): tripsandexpensescard
compta\dons\card.php(53): doncard
compta\localtax\clients.php(172): externalbalance
compta\salaries\card.php(47): salarycard
compta\tva\card.php(45): taxvatcard
contact\card.php(77): contactcard
contrat\card.php(70): contractcard
expedition\card.php(85): expeditioncard
fichinter\card.php(80): interventioncard
fourn\card.php(54): suppliercard
fourn\commande\card.php(80): ordersuppliercard
fourn\commande\orderstoinvoice.php(88): orderstoinvoicesupplier
fourn\facture\card.php(72): invoicesuppliercard
fourn\facture\paiement.php(71): paymentsupplier
livraison\card.php(68): deliverycard
product\card.php(91): productcard
product\composition\card.php(55): productcompositioncard
product\fournisseurs.php(62): pricesuppliercard
product\stats\commande.php(45): productstatsorder
product\stats\commande_fournisseur.php(45): productstatssupplyorder
product\stats\contrat.php(45): productstatscontract
product\stats\facture.php(48): productstatsinvoice
product\stats\facture_fournisseur.php(47): productstatssupplyinvoice
product\stats\propal.php(45): productstatspropal
product\stock\card.php(54): warehousecard
projet\card.php(48): projectcard
projet\tasks.php(67): projecttaskcard
resource\card.php(60): resource_card
resource\element_resource.php(58): element_resource
societe\agenda.php(41): agendathirdparty
societe\commerciaux.php(40): salesrepresentativescard
societe\consumption.php(80): consumptionthirdparty
societe\info.php(41): infothirdparty
societe\soc.php(80): thirdpartycard
user\card.php(93): usercard
user\list.php(72): userlist
user\passwordforgotten.php(56): passwordforgottenpage
...

請注意:此清單會隨著版本升級而不斷增長,因此如果您真的想知道是否存在特定的鉤子或上下文,請使用上面列出的方法直接搜索原始碼。

參考