যোগ_অ্যাকশন একটি শ্রেণীর রেফারেন্স


38

'যোগ_অ্যাকশন' এ ফাংশনের পরিবর্তে কোনও শ্রেণি রেফারেন্স করা কি সম্ভব? এটি বের করার মতো মনে হচ্ছে না। এখানে প্রশ্নাবলির কার্যকারিতার একটি প্রাথমিক উদাহরণ।

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' );

ক্লাস লোড করে এমন একটি পৃথক ফাংশন তৈরি না করেই আমি কি এটি করতে পারি? আমি কেবল অ্যাড-অ্যাকশনটির মাধ্যমে ক্লাস কনস্ট্রাক্টর চালাতে সক্ষম হতে চাই। বল রোলিংয়ের জন্য এগুলিই বোঝা দরকার।

উত্তর:


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' ) );

বন্ধ এবং পিএইচপি 5.3

দুঃখজনকভাবে আপনি নতুন বর্গ তৈরির লাইন এড়াতে পারবেন না। এটি এড়িয়ে যাওয়ার একমাত্র অন্য সমাধানের মধ্যে বয়লার প্লেট কোড জড়িত যা এখনও সেই লাইন রয়েছে এবং পিএইচপি 5.3+ প্রয়োজন যেমন:

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

কোন পর্যায়ে আপনি ক্লাসটি এড়িয়ে যেতে পারেন এবং কেবল একটি ফাংশন ব্যবহার করতে পারেন:

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

তবে মনে রাখবেন আপনি এখন বেনাম ফাংশনগুলির স্পেক্টারটি চালু করেছেন। উপরের ক্রিয়াটি ব্যবহার করে সরানোর কোনও উপায় remove_actionনেই এবং এটি এমন ডেভেলপারদের জন্য প্রচন্ড ব্যথা সৃষ্টি করতে পারে এবং যা অন্যান্য লোকের কোডের সাথে কাজ করতে হয়।

আম্পারসন্ডসে

আপনি এর মতো ব্যবহৃত ক্রিয়া দেখতে পাবেন:

array( &$this, 'getStuffDone' );

এটা খারাপ&পিএইচপি 4 এ আবার যুক্ত করা হয়েছিল যখন বস্তুগুলিকে রেফারেন্স হিসাবে নয় মান হিসাবে পাস করা হয়। পিএইচপি 4 এক দশকেরও বেশি পুরানো, এবং খুব দীর্ঘ সময়ে ওয়ার্ডপ্রেস সমর্থন করে না।

নেই কোনো কারণ ব্যবহার করতে &thisযখন আঙ্গুলসমূহ এবং ফিল্টার যুক্ত করা এবং রেফারেন্স কোন সমস্যা হবে সরানোর, এবং এমনকি পিএইচপি ভবিষ্যত সংস্করণের সাথে সামঞ্জস্যের উন্নতি হতে পারে

পরিবর্তে এটি ব্যবহার করুন:

array( $this, 'getStuffDone' );

ঠিক আছে. সে সব থেকে আপনাকে ধন্যবাদ; সত্যিই কিছুটা শিখেছি। আমি এখন কেবল ক্লাস ভিত্তিক পিএইচপি-তে স্বাচ্ছন্দ্য বোধ করছি। এটি আমিই করেছি এবং এটি কাজ করে তবে আপনি কি আমাকে বলতে পারেন এটি কোনওভাবে অনুশীলন / ভুল হলে? আমি ক্লাসটি একটি স্ট্যাটিক ফাংশন এর ভিতরে ক্লাসে শুরু করেছি, ক্লাসের মধ্যেই। তারপরে অ্যাডঅ্যাকশনটিতে স্থির ফাংশনটি উল্লেখ করা হয়েছে। এই লিঙ্কটি দেখুন: pasbin.com/0idyPwwY
ম্যাথু রুডি

হ্যাঁ আপনি সেভাবে এটি করতে পারেন, যদিও আমি $classআপনার পরিবর্তনশীল নাম হিসাবে এড়াতে পারি না , এই শব্দগুলি সংরক্ষিত থাকে। আমি মনে করি আপনি $x = new Y();বৈশ্বিক পরিমণ্ডলে অনুরূপ কিছু বলা এড়াতে আপনার পথে চলে যাচ্ছেন এবং আপনি জটিলতা যুক্ত করছেন যেখানে কোনওটিরই প্রয়োজন নেই। আপনার লিখিত কোডের পরিমাণ হ্রাস করার প্রয়াসে আরও কোড লেখা জড়িত!
টম জে নওয়েল

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

ভাল যুক্তি. আমি যেভাবে দেখছি সেভাবে পরিবর্তন হয়েছে। আমি মনে করি অতিরিক্ত কোডটি এড়িয়ে আমি এটির পরিবর্তে বৈশ্বিক সুযোগে কল করব।
ম্যাথু রুডি

1
আমি যুক্ত করতে চাই যে আপনি যদি নিজের ক্লাসটিকে একটি নামস্থানে স্থাপন করে থাকেন তবে আপনাকে এটিও যুক্ত করতে হবে বা যোগ_অ্যাকশন () / অ্যাড_ফিল্টার () এটি খুঁজে পাবেন না - এর মতো:add_action( 'admin_init', array('MyNamespace\MyClass','getStuffDone' ) );
jschrab

10

উদাহরণ ক্লাস

নোট:

  • ক্লাসটি একবার শুরু করুন
    • অগ্রাধিকার 0 এ কল করুন, যাতে আপনি পরে ডিফল্ট অগ্রাধিকার সহ একই হুক ব্যবহার করতে পারেন
    • ! class_existsএটিকে দু'বার কল করা এড়াতে এবং এন্টার কলারটি ভিতরে রাখুন in
  • initফাংশন এবং বর্গটি তৈরি করুনstatic
  • আপনি ক্লাসটি কল করার সময় আপনার আরম্ভের ভিতরে থেকে কনস্ট্রাক্টরকে কল করুন 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;

পিএইচপি 5+

দয়া করে , ছেড়ে দিন &। আমরা ইতিমধ্যে পিছুপি 4 এর বাইরে আছি। :)


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();
}

দয়া করে আপনার উত্তর সম্পাদনা করুন , এবং একটি ব্যাখ্যা যুক্ত করুন: কেন এটি সমস্যার সমাধান করতে পারে?
ফুসিয়া

0

আপনার ক্লাসে ইভেন্টগুলি প্রাথমিকভাবে লোড করার প্রয়োজন ছাড়াই ট্রিগার করতে পারে । আপনি যদি পুরো ক্লাস আপ সামনের দিকে লোড করতে না চান তবে এটি কার্যকর, তবে ওয়ার্ডপ্রেস ফিল্টার এবং ক্রিয়া অ্যাক্সেস করতে হবে।

এখানে একটি খুব সাধারণ উদাহরণ

<?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();

এটি কায়সারের উত্তরের একটি খুব সরলিকৃত সংস্করণ তবে সহজ শর্তে আচরণটি দেখায়। যারা প্রথমবার এই স্টাইলটি দেখছেন তাদের পক্ষে কাজ করতে পারেন।

অন্যান্য পদ্ধতিগুলি প্রয়োজন হলে এখনও অবজেক্টটি শুরু করতে পারে। আমি ব্যক্তিগতভাবে এই পদ্ধতিটি ব্যবহার করছি আমার প্লাগইনের alচ্ছিক অংশগুলি স্ক্রিপ্টগুলি সজ্জিত করার জন্য, তবে কেবলমাত্র একটি এজেএক্স অনুরোধে অবজেক্টটি ট্রিগার করছে।


0

এটি আমার পক্ষে কাজ করে:

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

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

0

সাধারণভাবে বলতে গেলে, আপনি একটি হুককে পুরো ক্লাস যুক্ত করবেন না । add_action()/ add_filter()আঙ্গুলসমূহ কলব্যাক আশা ফাংশন , যা করতে পারেন থেকে উল্লেখিত করা একটি বর্গ মধ্যে

ধরা যাক যে init()আপনার ক্লাসের ভিতরে আপনার একটি ফাংশন রয়েছে যা আপনি ওয়ার্ডপ্রেস initহুকটিতে প্রবেশ করতে চান ।

আপনার add_action()ক্লাসটির ভিতরে আপনার কলটি রাখুন এবং তারপরে কলব্যাকটি শনাক্ত করুন:

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

(দ্রষ্টব্য: আমি ধরে নিচ্ছি যে আপনার ক্লাসটি সঠিকভাবে নামগতির হয়; অন্যথায়, আপনার কলব্যাক ফাংশনগুলির নাম স্পেস করতে ভুলবেন না))


বর্তমান ক্লাসটি ইতিমধ্যে চালু না হলে কী হবে? আমি আসলে শুরু করার জন্য অ্যাড_অ্যাকশনটি ব্যবহার করার চেষ্টা করছিলাম, সুতরাং আমাকে $ var = নতুন মাই ক্লাস () যুক্ত করতে হবে না; আগে অন্য কোথাও।
ম্যাথু রুডি

আপনি কি নিজের ক্লাসে init(বা যেখানে আপনার প্রয়োজন সেখানে) ইনস্ট্যান্ট করার জন্য কেবল কলব্যাক লিখতে পারবেন না ?
চিপ বেনেট

0

তাত্ক্ষণিক বস্তুর পরিবর্তে শ্রেণীর নামটি পাস করে আপনার এটি করা উচিত:

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

(তত্ত্বগতভাবে, আপনার অন্যান্য সমাধানেরও কাজ করা উচিত

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

মাথার উপর থেকে নিশ্চিত না কেন এটি হয় না। আপনি যদি রেফারেন্স দিয়ে ফোন না করেন?)


প্রথম এক কাজ করে না। কেবল পৃষ্ঠাটি ফাঁকা করে দেয়। দ্বিতীয়টি কাজ করে, তবে কেবল ক্লাসটি প্রথম লাইনে শুরু করা হয়েছিল। এটি ক্রমটি ক্রিয়া যুক্ত করার উদ্দেশ্যকে পরাভূত করে, কারণ ক্লাসটি ইতিমধ্যে শুরু করা হয়েছে। তবে আমি যা করার চেষ্টা করছি তা তা করে না, যা ক্রিয়াকলাপটি ক্রিয়াকলাপের মাধ্যমে শুরু করা হয়েছে। আমি যে প্রকৃত কোডটিতে কাজ করছি তাতে ক্রিয়াটি 'অ্যাডমিন_ইনিট' নয় বরং অন্য শ্রেণীর মধ্যে একটি কাস্টম ক্রিয়া। আমি চাই না যে অন্য শ্রেণীর ক্রিয়া না থাকলে 'মাইক্লাস' ফাংশনটি শুরু করা হোক। দুঃখিত যদি আমি কিছু মিস করছি; আমি যেমন যাচ্ছি শিখছি
ম্যাথু রুডি

হ্যাঁ, আমি ভুল ছিলাম। এটি কেবলমাত্র যদি আপনি স্থিতিশীল initপদ্ধতিতে কল করেন তবেই কাজ করে । ওয়ার্ডপ্রেস.সটাকেক্সচেঞ্জ
বুন গর্জেস
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.