বেনামে থাকা একটি ফিল্টার কীভাবে সরিয়ে ফেলবেন?


62

আমার functions.phpফাইলে আমি নীচের ফিল্টারটি মুছে ফেলতে চাই, তবে এটি ক্লাসে থাকায় এটি কীভাবে করবেন তা নিশ্চিত নই। দেখতে কেমন হবে remove_filter()?

add_filter('comments_array',array( &$this, 'FbComments' ));

এটি এখানে 88 লাইনে রয়েছে


&আপনার থেকে &$thisএটি অপসারণ করা উচিত , এটি একটি পিএইচপি 4 জিনিস
টম জে নওয়েল

উত্তর:


79

এটা খুব ভাল প্রশ্ন। এটি প্লাগইন এপিআই এবং সেরা প্রোগ্রামিং অনুশীলনের অন্ধকারে চলে যায়।

নিম্নলিখিত উত্তরের জন্য আমি কোড পড়তে সহজ সঙ্গে সমস্যাটি বর্ণনা করার জন্য একটি সাধারণ প্লাগইন তৈরি করেছি।

<?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;
}

এখন আমরা এটি দেখতে পাচ্ছি:

এখানে চিত্র বর্ণনা লিখুন

ওয়ার্ডপ্রেস ফিল্টার জন্য একটি নাম প্রয়োজন । আমরা একটি সরবরাহ করি নি, তাই ওয়ার্ডপ্রেস কল করে _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'। যখন আপনার প্লাগইনটি ওয়ার্ডপ্রেস দ্বারা ডাকা হয় তখনই নয়।


@ মাইকচিন্কেল সম্পর্কিত ধারণা , এখন পর্যন্ত এটি বাস্তবে প্রয়োগ করা হয়নি।
ফুসিয়া

মজাদার. আমি আপনার উত্তরটি খুব ভাল পেয়েছি তবে আপনার শেষ সিদ্ধান্তটি খুব খারাপ। আমার মতে, ক্লাস উদাহরণগুলি, সাধারণভাবে, ওয়ার্ডপ্রেস প্লাগইনটি লোড করার সাথে সাথে তা ইনস্ট্যান্ট করা উচিত। তারপরে, শ্রেণীর উদাহরণটির নির্মাণকারীর কোনও আসল ক্রিয়া সম্পাদন করা উচিত নয়, কেবল ক্রিয়া এবং ফিল্টার যুক্ত করুন। এইভাবে, আপনার শ্রেণীর উদাহরণ থেকে ক্রিয়াগুলি এবং ফিল্টারগুলি সরাতে ইচ্ছুক এমন প্লাগইনগুলি নিশ্চিত হতে পারে যে plugins_loadedডাকা হওয়ার সময় সেগুলি আসলে যুক্ত করা হয়েছিল , যা ঠিক সেটির plugins_loadedজন্য। অবশ্যই, ক্লাস উদাহরণটি এখনও অ্যাক্সেসযোগ্য হওয়া দরকার, সম্ভবত সিঙ্গলটন প্যাটার্নের মাধ্যমে।
engelen

@ এজেনেল এটি একটি পুরানো উত্তর। আজকাল আমি কলব্যাকগুলি সরিয়ে ফেলার জন্য একটি পদক্ষেপ দেব। তবে সিঙ্গেলটন নয়, এটি বহু কারণে অ্যান্টি-প্যাটার্ন
ফুসিয়া

এই উত্তরটি ক্রিয়াগুলি সরানোর জন্যও কাজ করে যেমনremove_action()
নিক পাইট

0

আমি নিশ্চিত নই তবে আপনি একটি সিঙ্গলটন ব্যবহার করে দেখতে পারেন।
আপনাকে অবশ্যই অবশ্যই নিজের শ্রেণীর স্থিতিশীল সম্পত্তিতে অবজেক্টের রেফারেন্স সংরক্ষণ করতে হবে এবং তারপরে স্থির পদ্ধতি থেকে স্ট্যাটিক ভেরিয়েবলটি ফিরিয়ে আনতে হবে। এটার মতো কিছু:

class MyClass{
    private static $ref;
    function MyClass(){
        $ref = &$this;
    }
    public static function getReference(){
        return self::$ref;
    }
}

0

যতক্ষণ আপনি অবজেক্টটি জানেন (এবং আপনি পিএইচপি 5.2 বা উচ্চতর ব্যবহার করেন - বর্তমান স্থিতিশীল পিএইচপি সংস্করণ 5.5, 5.4 এখনও সমর্থিত, 5.3 জীবনের শেষ), আপনি কেবল remove_filter()পদ্ধতিটি দিয়ে এটিকে সরাতে পারবেন । আপনাকে যা মনে রাখতে হবে তা হ'ল অবজেক্ট, পদ্ধতি-নাম এবং অগ্রাধিকার (যদি ব্যবহৃত হয়):

remove_filter('comment_array', [$this, 'FbComments']);

তবে আপনি আপনার কোডটিতে কিছুটা ভুল করেন। অ্যাম্পারস্যান্ডের $thisসাথে উপসর্গ ব্যবহার করবেন না &, এটি পিএইচপি 4 (!) এ প্রয়োজন ছিল এবং এটি দীর্ঘ সময় ধরে ছাড়। এটি আপনার হুককে সমস্যাযুক্ত হিসাবে কাজ করতে পারে তাই কেবল এটিকে এড়িয়ে চলুন:

add_filter('comments_array', [$this, 'FbComments]));

এবং এটাই.


1
$thisবাইরে থেকে আপনার কোনও অ্যাক্সেস নেই (অন্য একটি প্লাগইন / থিম)।
ফুসিয়া
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.