add_action 클래스를 참조


38

'add_action'에서 함수 대신 클래스를 참조 할 수 있습니까? 알아낼 수 없습니다. 다음은 해당 기능의 기본 예입니다.

add_action( 'admin_init', 'MyClass' );
class MyClass {
     function __construct() {
          .. This is where stuff gets done ..
     }
}

그래서, 그것은 작동하지 않습니다. 나는 또한 시도했다 :

$var = new MyClass();
add_action( 'admin_init', array( &$var ) );

과:

$var = new MyClass();
add_action( 'admin_init', array( &$var, '__construct' ) );

그리고 또한:

add_action( 'admin_init', 'MyClass::__construct' );

어쨌든 클래스를로드하는 별도의 함수를 만들지 않고도이 작업을 수행 할 수 있습니까? add_action을 통해 클래스 생성자를 실행할 수 있기를 원합니다. 볼 롤링을하기 위해로드해야하는 전부입니다.

답변:


69

아니요, 직접적으로가 아니라 후크를 통해 클래스를 '초기화'하거나 인스턴스화 할 수 없습니다. 몇 가지 추가 코드가 항상 필요합니다. 웜 캔을 직접 열 때이를 수행하는 것은 바람직하지 않습니다.

더 좋은 방법은 다음과 같습니다.

class MyClass {
     function __construct() {
          add_action( 'admin_init',array( $this, 'getStuffDone' ) );
     }
     function getStuffDone() {
          // .. This is where stuff gets done ..
     }
}
$var = new MyClass();

물론 일반적인 경우를 위해 인터페이스 클래스를 만들어 더 단순화 할 수 있습니다.

class IGetStuffDone {
    function IGetStuffDone(){
        add_action( 'admin_init',array( $this, 'getStuffDone' ) );
    }
    public abstract function getStuffDone();
}

인터페이스로서이 유형의 객체를 직접 만들 수는 없지만 하위 클래스를 만들면 다음과 같이 말할 수 있습니다.

class CDoingThings extends IGetStuffDone {
    function getStuffDone(){
        // doing things
    }
}
$var = new CDoingThings();

그러면 모든 후크가 자동으로 추가되므로 서브 클래스에서 정확히 수행되는 작업을 정의한 후 작성하면됩니다.

생성자

나는 생성자를 후크 함수로 추가하지 않을 것이고, 나쁜 습관이며, 많은 비정상적인 이벤트를 일으킬 수 있습니다. 또한 대부분의 언어에서 생성자는 인스턴스화되는 객체를 반환하므로 후크가 필터와 같은 것을 반환 해야하는 경우 원하는대로 필터링 된 변수를 반환하지 않지만 대신 클래스 객체를 반환합니다.

생성자 또는 소멸자를 호출하는 것은 어떤 언어를 사용하든 절대 수행 해서는 안되는 프로그래밍 습관 입니다.

또한 생성자는 실제 작업이 아닌 사용 준비를 초기화하기 위해 객체를 구성해야합니다. 객체에 의해 수행되는 작업은 별도의 기능이어야합니다.

정적 클래스 메서드이며 인스턴스화 / 초기화가 필요하지 않습니다

클래스 메소드가 정적 클래스 메소드 인 경우 $this아래 표시된 것처럼 클래스 이름을 따옴표로 묶을 수 있습니다.

class MyClass {
     public static function getStuffDone() {
          // .. This is where stuff gets done ..
     }
}
add_action( 'admin_init', array('MyClass','getStuffDone' ) );

클로저 및 PHP 5.3

슬프게도 새로운 클래스를 만드는 선을 피할 수는 없습니다. 이것을 건너 뛸 수있는 유일한 다른 해결책은 여전히 ​​해당 라인을 가진 보일러 플레이트 코드를 포함하며 PHP 5.3 이상이 필요합니다.

add_action('admin_init',function(){
    $var = new MyClass();
    $var->getStuffDone();
});

어느 시점에서 클래스를 건너 뛰고 함수를 사용할 수 있습니다.

add_action('admin_init',function(){
    // do stuff
});

그러나 이제 익명 함수의 스펙터를 소개했습니다. 를 사용하여 위의 작업을 제거 할 수있는 방법이 없으며 remove_action, 이는 다른 사람의 코드로 작업해야하는 개발자에게 큰 고통을 줄 수 있습니다.

앰퍼샌드

다음과 같이 사용 된 조치가 표시 될 수 있습니다.

array( &$this, 'getStuffDone' );

이것은 나쁘다 . &객체가 참조가 아닌 값으로 전달 될 때 PHP 4에서 다시 추가되었습니다. PHP 4는 10 년이 넘었으며 WordPress에서 오랫동안 지원하지 않았습니다.

후크와 필터를 추가 할 때 사용할 이유없으며&this 참조를 제거해도 아무런 문제가 없으며 향후 PHP 버전과의 호환성을 향상시킬 수 있습니다

대신 이것을 사용하십시오 :

array( $this, 'getStuffDone' );

승인. 그 모든 것에 감사합니다. 정말 많이 배웠습니다. 나는 지금 클래스 기반 PHP에서만 편안 해지고 있습니다. 이것이 내가 한 일이며 효과가 있지만 어떤 식 으로든 나쁜 습관 / 부 정확한지 말해 줄 수 있습니까? 클래스 자체 내에서 정적 함수 내에서 클래스를 시작했습니다. 그런 다음 add_action에서 정적 함수를 참조하십시오. :이 링크를 참조 pastebin.com/0idyPwwY
마태 복음 붉게

네, 그렇게 할 수는 있지만 $class변수 이름으로 사용 하는 것을 피할 수는 있지만 그 단어는 예약되어 있습니다. 나는 당신이 $x = new Y();세계적인 범위에서 비슷한 것을 말하지 않기 위해 당신의 길을 벗어나고 있다고 생각합니다 . 작성된 코드의 양을 줄이려는 시도는 더 많은 코드를 작성하는 것과 관련이 있습니다!
Tom J Nowell

위의 모든 경우에서 지적한 것처럼 클래스 대신 함수를 사용하는 것이 좋습니다. 해당 클래스는 버려지고 동일한 목적을 수행하기 때문입니다. 자원 낭비입니다. 객체를 생성하고 파괴하는 데 비용이 들며, 적은 객체를 원하며 오래 살기를 원합니다.
Tom J Nowell

좋은 지적. 내가보고있는 방식을 바꿨다. 추가 코드를 피하면서 대신 전역 범위에서 호출 할 것이라고 생각합니다.
Matthew Ruddy

1
만약 당신이 클래스를 네임 스페이스에 넣었다면 그것을 추가하거나 add_action () / add_filter ()가 그것을 찾지 못할 것입니다.add_action( 'admin_init', array('MyNamespace\MyClass','getStuffDone' ) );
jschrab

10

예제 클래스

노트:

  • 수업을 한 번만 시작하십시오
    • 우선 순위 0으로 전화하므로 나중에 기본 우선 순위로 동일한 후크를 사용할 수 있습니다.
    • ! class_exists두 번 전화하지 않도록 in에 싸서 init 호출자를 안에 넣으십시오.
  • init함수와 클래스를 var로 만드십시오.static
  • 클래스를 호출 할 때 init 내부에서 생성자를 호출하십시오 new self.

여기에 예가 있습니다

if ( ! class_exists( 'WPSESampleClass' ) )
{
    // Init the class on priority 0 to avoid adding priority inside the class as default = 10
    add_action( 'init', array ( 'WPSESampleClass', 'init' ), 0 );

class WPSESampleClass
{
    /**
     * The Class Object
     */
    static private $class = null;

    public static function init()
    {
        if ( null === self::$class ) 
            self :: $class = new self;

        return self :: $class;
    }

    public function __construct()
    {
        // do stuff like add action calls:
        add_action( 'init', array( $this, 'cb_fn_name' ) );
    }

    public function cb_fn_name()
    {
        // do stuff 
    }
} // END Class WPSESampleClass

} // endif;

PHP 5+

제발 나가 &십시오. 우리는 이미 php4를 넘어 섰습니다. :)


2
if (!class_exists("AllInOneWoo")){
    class AllInOneWoo {
        function __construct(){
            add_action('admin_menu', array($this, 'all_in_one_woo') );
        }
        function all_in_one_woo(){
            $page_title = 'All In One Woo';
            $menu_title = 'All In One Woo';
            $capability = 'manage_options';
            $menu_slug  = 'all-in-one-woo-menu';
            $function   = array($this, 'all_in_one_woo_menu');
            $icon_url   = 'dashicons-media-code';
            $position   = 59;

            add_menu_page($page_title, $menu_title, $capability, $menu_slug, $function, $icon_url, $position);
        }
        function all_in_one_woo_menu(){?>
            <div class="wrap">
                <h1><?php _e('All In One Woo', 'all_in_one_woo'); ?></h1>
            </div>
        <?php }
    }// end class
}// end if

if (class_exists("AllInOneWoo")){       
    $all_in_one_woo = new AllInOneWoo();
}

제발 편집 답변을 하고, 설명을 추가 : 문제를 해결할 수있는?
fuxia

0

처음 에로드 할 필요없이 클래스에서 이벤트를 트리거 할 수 있습니다 . 전체 클래스를 미리로드하지 않고 WordPress 필터 및 작업에 액세스해야하는 경우에 유용합니다.

다음은 매우 간단한 예입니다

<?php
class MyClass
{
    public static function init()
    {
        add_filter( 'the_content', array('MyClass', 'myMethod') );
    }

    public static function myMethod($content)
    {
        $content = $content . 'Working without loading the object';
    }
}

MyClass::init();

이것은 카이저의 대답의 매우 단순화 된 버전이지만 간단한 용어로 행동을 보여줍니다. 이 스타일을 처음 보는 사람들에게 유용 할 수 있습니다.

필요한 경우 다른 방법으로도 객체를 시작할 수 있습니다. 개인적 으로이 방법을 사용하여 플러그인의 선택적 부분이 스크립트를 대기열에 넣을 수 있지만 AJAX 요청에서 객체를 트리거하는 것만 허용합니다.


0

이것은 나를 위해 작동합니다 :

class foo
{
    public static function bar()
    {
        echo 'it works!';
    }
}

add_action('foo_bar', array('foo', 'bar'));

0

일반적으로 전체 클래스 를 후크에 추가하지는 않습니다 . add_action()/의 add_filter()후크 콜백 기대 기능 , 에서 참조 할 클래스 내를 .

init()클래스 내에 함수가 있고 WordPress init후크 에 연결하려고 한다고 가정 해 봅시다 .

당신 넣어 add_action()전화를 안쪽 과 같이 콜백을 식별 한 후 클래스 및 :

add_action( 'init', array( $this, 'init' ) );

(참고 : 클래스의 네임 스페이스가 적절하다고 가정합니다. 그렇지 않으면 콜백 함수의 네임 스페이스를 사용해야합니다.)


현재 수업이 아직 시작되지 않은 경우는 어떻습니까? 실제로 시작하기 위해 add_action을 사용하려고했기 때문에 $ var = new MyClass ()를 추가 할 필요가 없습니다. 다른 곳에서 미리.
Matthew Ruddy

클래스를 인스턴스화하기 위해 콜백을 작성할 수 있습니까 init?
Chip Bennett

0

인스턴스화 된 객체 대신 클래스 이름을 전달하여이를 수행 할 수 있어야합니다.

add_action( 'init', array( 'MyClass', '__construct' ) );

(이론적으로 다른 솔루션도 작동해야합니다.

$var = new MyClass();
add_action( 'admin_init', array( $var, '__construct' ) );

왜 그렇지 않은지 확실하지 않습니다. 어쩌면 참조로 전화하지 않으면?)


첫 번째는 작동하지 않습니다. 페이지를 비 웁니다. 두 번째는 작동하지만 클래스가 첫 번째 줄에서 시작 되었기 때문에 가능합니다. 클래스가 이미 시작되었으므로 조치를 추가하려는 목적을 무효화합니다. 그러나 그것은 내가하려는 일을하지 않습니다. 이는 행동을 통해 수업을 시작합니다. 내가 작업하고있는 실제 코드에서 작업은 'admin_init'가 아니라 다른 클래스 내의 사용자 지정 작업입니다. 다른 클래스의 작업이없는 경우 'MyClass'기능을 시작하고 싶지 않습니다. 내가 뭔가를 놓친다면 죄송합니다. 내가가는 동안 배우기
Matthew Ruddy

그래, 내가 틀렸어 정적 init메소드를 호출하는 경우에만 작동합니다 . wordpress.stackexchange.com/a/48093/14052
분 협곡
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.