sd shadow-docs
GitHub
shadow-docs / WordPress / Hooki un filtri

Hooki un filtri

Visas iepriekšējās lapas izmantoja add_action un add_filter — šī lapa paskaidro, kā tie strādā apakšā, un parāda, kā ap tiem uzbūvēt reālu biznesa loģiku: piekļuves piešķiršanu kursam pēc apmaksas.

1. Darbība (action) vs filtrs (filter)

add_actionadd_filter
Nolūksizdarīt kaut ko (nosūtīt e-pastu, ierakstīt log)pārveidot vērtību un atgriezt to
Atgriešanas vērtībatiek ignorētaobligāti jāatgriež vērtība
Piemērs no šīs sadaļaswoocommerce_order_status_completedwoocommerce_account_menu_items
Biežākā kļūda: filtra funkcija, kas neatgriež vērtību
Ja add_filter callback funkcija aizmirst return, filtrētā vērtība pārtop uz null — piemēram, "WooCommerce My Account" izvēlnes lapā tas nozīmētu tukšu, bez cilnēm izvēlni. Katram filtram funkcijas beigās vienmēr jābūt return $vertiba;.

2. Prioritāte un argumentu skaits

add_action( 'hook_nosaukums', 'funkcija', $prioritate, $argumentu_skaits ) — pēdējie divi parametri ir opcionāli, bet svarīgi:

add_filter('gettext', function($translated, $text, $domain) {
	if ($domain === 'woocommerce' && strpos($text, 'From your account dashboard') !== false) {
		return 'Laipni lūdzam savā kontā!';
	}
	return $translated;
}, 20, 3); // <- "3" nepieciešams, citādi $text un $domain vienmēr būtu null

3. Piemērs: biznesa loģika, kas dzīvo hookā

Kad pasūtījums WooCommerce mainās uz statusu "Pabeigts", tas izsauc hooku woocommerce_order_status_completed ar pasūtījuma ID. Tas ir pareizais vieta, kur piešķirt piekļuvi digitālam produktam — nevis maksājumu procesorā vai kaut kur front-end:

add_action( 'woocommerce_order_status_completed', 'asg_grant_course_access', 10, 1 );

function asg_grant_course_access( $order_id ) {
	$order = wc_get_order( $order_id );
	if ( ! $order ) return;

	$user_id = $order->get_user_id();
	if ( ! $user_id ) return; // Viesu pirkums — izlaižam

	foreach ( $order->get_items() as $item ) {
		$product_id = $item->get_product_id();

		$courses = get_user_meta( $user_id, 'asg_course_access', true );
		if ( ! is_array( $courses ) ) $courses = [];

		$now         = time();
		$four_months = 4 * 30 * DAY_IN_SECONDS;

		// Ja piekļuve jau aktīva — pagarina no beigu datuma, nevis no tagad
		if ( isset( $courses[$product_id] ) && $courses[$product_id]['expires'] > $now ) {
			$courses[$product_id]['expires'] += $four_months;
		} else {
			$courses[$product_id] = [
				'granted' => $now,
				'expires' => $now + $four_months,
				'order_id' => $order_id,
			];
		}

		update_user_meta( $user_id, 'asg_course_access', $courses );
	}
}

// Palīgfunkcija — izmanto to jebkur, kur jāpārbauda piekļuve
function asg_has_course_access( $product_id, $user_id = null ) {
	if ( ! $user_id ) $user_id = get_current_user_id();
	if ( ! $user_id ) return false;

	$courses = get_user_meta( $user_id, 'asg_course_access', true );
	if ( ! is_array( $courses ) || ! isset( $courses[$product_id] ) ) return false;

	return $courses[$product_id]['expires'] > time();
}
Kāpēc "pagarina no beigu datuma", ne no tagad
Ja lietotājam jau ir aktīvs abonements un viņš pirkst to pašu kursu atkārtoti (piem. atjauno pirms termiņa beigām), pievienojot 4 mēnešus no šodienas, viņš pazaudētu atlikušo laiku no iepriekšējā perioda. Pievienojot no expires, laiks summējas pareizi.

Kopsavilkums: kā šīs piecas lapas savienojas

Šis ir viens un tas pats functions.php fails, sadalīts pa tēmām: