답변:
아주 좋은 질문입니다. 그것은 플러그인 API와 최고의 프로그래밍 관행의 어두운 중심으로 내려갑니다.
다음 답변을 위해 쉽게 읽을 수있는 코드로 문제를 설명하기 위해 간단한 플러그인을 만들었습니다.
<?php # -*- coding: utf-8 -*-
/* Plugin Name: Anonymous OOP Action */
if ( ! class_exists( 'Anonymous_Object' ) )
{
/**
* Add some actions with randomized global identifiers.
*/
class Anonymous_Object
{
public function __construct()
{
add_action( 'wp_footer', array ( $this, 'print_message_1' ), 5 );
add_action( 'wp_footer', array ( $this, 'print_message_2' ), 5 );
add_action( 'wp_footer', array ( $this, 'print_message_3' ), 12 );
}
public function print_message_1()
{
print '<p>Kill me!</p>';
}
public function print_message_2()
{
print '<p>Me too!</p>';
}
public function print_message_3()
{
print '<p>Aaaand me!</p>';
}
}
// Good luck finding me!
new Anonymous_Object;
}
이제 우리는 이것을 본다 :
워드 프레스 에는 필터 이름이 필요합니다 . 우리는 하나를 제공하지 않았으므로 WordPress가 전화를 걸고 _wp_filter_build_unique_id()
만듭니다. 이 이름은를 사용하기 때문에 예측할 수 없습니다 spl_object_hash()
.
우리가 실행하는 경우 var_export()
에 $GLOBALS['wp_filter'][ 'wp_footer' ]
우리는 지금이 뭔가를 얻을 :
array (
5 =>
array (
'000000002296220e0000000013735e2bprint_message_1' =>
array (
'function' =>
array (
0 =>
Anonymous_Object::__set_state(array(
)),
1 => 'print_message_1',
),
'accepted_args' => 1,
),
'000000002296220e0000000013735e2bprint_message_2' =>
array (
'function' =>
array (
0 =>
Anonymous_Object::__set_state(array(
)),
1 => 'print_message_2',
),
'accepted_args' => 1,
),
),
12 =>
array (
'000000002296220e0000000013735e2bprint_message_3' =>
array (
'function' =>
array (
0 =>
Anonymous_Object::__set_state(array(
)),
1 => 'print_message_3',
),
'accepted_args' => 1,
),
),
20 =>
array (
'wp_print_footer_scripts' =>
array (
'function' => 'wp_print_footer_scripts',
'accepted_args' => 1,
),
),
1000 =>
array (
'wp_admin_bar_render' =>
array (
'function' => 'wp_admin_bar_render',
'accepted_args' => 1,
),
),
)
악의적 인 행동을 찾아 제거하려면 후크에 대한 관련 필터를 거쳐야합니다 (동작은 매우 간단한 필터입니다). 이것이 배열인지, 객체가 클래스의 인스턴스인지 확인하십시오. 그런 다음 실제 식별자를 보지 않고 우선 순위를 취하고 필터를 제거합니다 .
자, 그것을 함수에 넣겠습니다.
if ( ! function_exists( 'remove_anonymous_object_filter' ) )
{
/**
* Remove an anonymous object filter.
*
* @param string $tag Hook name.
* @param string $class Class name
* @param string $method Method name
* @return void
*/
function remove_anonymous_object_filter( $tag, $class, $method )
{
$filters = $GLOBALS['wp_filter'][ $tag ];
if ( empty ( $filters ) )
{
return;
}
foreach ( $filters as $priority => $filter )
{
foreach ( $filter as $identifier => $function )
{
if ( is_array( $function)
and is_a( $function['function'][0], $class )
and $method === $function['function'][1]
)
{
remove_filter(
$tag,
array ( $function['function'][0], $method ),
$priority
);
}
}
}
}
}
언제이 함수를 호출합니까? 원본 객체가 언제 만들어 졌는지 확실하게 알 수있는 방법이 없습니다. 아마 가끔 전에 'plugins_loaded'
? 나중에?
우리는 객체와 관련된 훅을 사용하고 우선 순위가 매우 빠르다 0
. 이것이 정말로 확신 할 수있는 유일한 방법입니다. 방법을 제거하는 방법은 다음과 같습니다 print_message_3()
.
add_action( 'wp_footer', 'kill_anonymous_example', 0 );
function kill_anonymous_example()
{
remove_anonymous_object_filter(
'wp_footer',
'Anonymous_Object',
'print_message_3'
);
}
결과:
그리고 그것은 질문에서 조치를 제거해야합니다 (테스트되지 않음).
add_action( 'comments_array', 'kill_FbComments', 0 );
function kill_FbComments()
{
remove_anonymous_object_filter(
'comments_array',
'SEOFacebookComments',
'FbComments'
);
}
'plugins_loaded'
. 당신의 플러그인이 WordPress에 의해 호출되었을 때만이 아닙니다.plugins_loaded
이 호출 될 때 실제로 추가되도록 할 수 있습니다 plugins_loaded
. 물론, 클래스 인스턴스는 싱글 톤 패턴을 통해 여전히 액세스 가능해야합니다.
remove_action()
객체를 알고 있고 PHP 5.2 이상을 사용하는 한 현재 안정적인 PHP 버전은 5.5이고 5.4는 여전히 지원되며 5.3은 수명이 끝났습니다) remove_filter()
메소드를 사용하여 제거 할 수 있습니다 . 기억해야 할 것은 객체, 메소드 이름 및 우선 순위 (사용 된 경우)뿐입니다.
remove_filter('comment_array', [$this, 'FbComments']);
그러나 코드에서 약간의 실수가 있습니다. PHP 4 (!)에서 필요했던 $this
앰퍼샌드 접두어를 사용 하지 마십시오 &
. 이렇게하면 후크를 처리하는 데 문제가 생길 수 있으므로 방해하지 마십시오.
add_filter('comments_array', [$this, 'FbComments]));
그리고 그게 다야.
$this
외부 (다른 플러그인 / 테마)에서 액세스 할 수 없습니다 .
&
귀하의에서&$this
그것이 PHP 4 일이,