💻 آخرین فرصت یادگیری برنامه‌نویسی با آفر ویژه قبل از افزایش قیمت در ۵ آذر ماه (🎁 به همراه یک هدیه ارزشمند )
۰ ثانیه
۰ دقیقه
۰ ساعت
۱ اسماعیل آبابائی
حل تمرین : ریفکتور setting API در شی گرایی
محسن موحد حل شده توسط محسن موحد

تغییرات بیس کلاس:

ابتدا اومدیم  یک پراپرتی آرایه‌ای با نام field_properties تعریف کردیم تا تمام دیتاهای ورودی یک فیلد را داخلش بریزیم.قرار است مقادیر هر فیلد داخل یک آرایه ریخته بشه و اون آرایه توی آرایه field_properties قرار بگیرد و در نهایت ما یک آرایه دو بعدی داشته باشیم)

در مرحله بعد زمانی که خواستیم تابع add_setting_field مقدار دهی کنیم با زدن یک حلقه روی آرایه field_properties‌مقادیر را از آرایه گرفتیم و توی تابع قرار دادیم. 

<?php
// Base class providing a structure for settings
abstract class BaseSetting
{
    protected string $option_group, $section_ID, $section_title, $field_section;
    protected array $args = [], $option_names = [], $section_args = [], $field_args = [], $field_properties = [['field_ID', 'field_title', 'field_callback']];
    // Constructor to set up actions on admin_init
    public function __construct()
    {
        add_action('admin_init', [$this, 'register_init_setting']);
    }
    // Method to register settings, sections, and fields
    public function register_init_setting()
    {
        // Register each option name
        foreach ($this->option_names as $option_name) {
            register_setting(
                $this->option_group,
                $option_name,
                $this->args
            );
        }
        // Add a settings section with its callback
        add_settings_section(
            $this->section_ID,
            $this->section_title,
            [$this, 'section_callback_title'],
            $this->option_group,
            $this->section_args
        );
        // Add fields for each property in field_properties array
        foreach ($this->field_properties as $item) {
            add_settings_field(
                $item['field_ID'],
                $item['field_title'],
                [$this, $item['field_callback']],
                $this->option_group,
                $this->field_section,
                $this->field_args
            );
        }
    }
    // Abstract method for section callback title
    abstract public function section_callback_title();
}

 

تغییرات کلاس extend‌شده:

به ازای هر فیلدی که میخواهیم داشته باشیم مقادیر وروردی تابع را( field_ID ، field_title و field_callback) در قالب یک آرایه در  field_properties قرار دادیم . 

به ازای هر فیلد یه callback function با نامی که در آرایه تعریف کردیم ایجاد می‌کنیم. 

<?php
include_once 'BaseSetting.php';
// Child class extending the base setting class
class Setting_ExampleGatePay extends BaseSetting
{
    // Constructor to set up specific settings
    public function __construct()
    {
        $this->option_group = 'general';
        $this->option_names = ['_merchant_ID', '_gate_pay_name'];
        $this->args = [
            'type' => 'string',
            'sanitize_callback' => 'sanitize_text_field',
            'default' => null
        ];
        $this->section_ID = 'merchant_ID_section';
        $this->section_title = '';
        $this->field_properties = [
                //properties were defined for merchant field
            [
                'field_ID' => 'merchant_ID_field',
                'field_title' => 'کلید مرچنت آی‌دی',
                'field_callback' => 'layout_merchant'
            ],
            [
                //properties were defined for gate pay field
                'field_ID' => 'gate_pay_name',
                'field_title' => 'نام درگاه پرداخت',
                'field_callback' => 'layout_gate_pay'
            ]
        ];
        $this->field_section = $this->section_ID;
        parent::__construct();
    }
    // Implementation of the abstract section callback title method
    public function section_callback_title()
    {
        // TODO: Implement section_callback_title() method.
    }
    // Layout function for merchant field
    public function layout_merchant()
    {
        $merchant_ID = get_option('_merchant_ID');
        ?>
        <input type="text" name="_merchant_ID" value="<?php echo isset($merchant_ID) ? esc_attr($merchant_ID) : '' ?>">
        <?php
    }
    // Layout function for gate pay field
    public function layout_gate_pay()
    {
        $gate_pay_name = get_option('_gate_pay_name');
        ?>
        <input type="text" name="_gate_pay_name"
               value="<?php echo isset($gate_pay_name) ? esc_attr($gate_pay_name) : '' ?>">
        <?php
    }
}

 

به این شکل می‌توانیم به صورت داینامیک هر تعداد فیلد که میخواهیم ایجاد بکنیم.

 

نکته:

من نتوانستیم کال‌بک فانکشن هر فیلد را به صورت داینامیک و abstract تعریف کنیم و در قالب یه public function تعریف کردم.

آیا راه حلی وجود دارد که به صورت داینامیک abstract function را در کلاس base نام گذاریم و تعریف کنیم ؟

سلام،

یک راه پیاده سازی استفاده از توابع callable یا متد __call هست، این متدو داخل کلاس والد تعریف میکنید:

public function __call($name, $arguments)
{
    if (in_array($name, array_column($this->field_properties, 'field_callback'))) {
        // Executing the callback function
    }
}

 

روش دیگه اینکه از دیزاین پترن استراتژی استفاده کنید و برای هر فیلد یک کلاس تعریف کنید که یک اینترفیس رو پیاده سازی میکند:

interface FieldCallbackStrategy {
    public function executeCallback();
}
class MerchantFieldCallback implements FieldCallbackStrategy {
    public function executeCallback() {
        // Display the merchant field
    }
}
class GatePayFieldCallback implements FieldCallbackStrategy {
    public function executeCallback() {
        // Display the gate pay field
    }
}

و در نهایت میتونید آبجکت‌های مورد نظرو تزریق کنید:

class Setting_ExampleGatePay extends BaseSetting {
    public function __construct(MerchantFieldCallback $merchant, GatePayFieldCallback $gatepay) {
    }
}
بهترین پاسخ
محسن موحد ۲۹ آذر ۱۴۰۲، ۱۹:۲۰