【问题标题】:How to "modify" a closure如何“修改”闭包
【发布时间】:2017-07-07 20:34:38
【问题描述】:

我正在创建一个类以将元框添加到 Wordpress 扩展 Metabox.io 的功能。

现在您经常拥有具有相同属性的元框(例如对于相同的帖子类型)。我想对这些进行分组,这样您就不必重复这些属性。

我有一个函数add(),它只是添加了一个元框。

现在我希望group() 方法执行以下操作:

$manager->group([
    'post_types' =>'page',
], function() use ($manager) {

    $manager->add('metaboxfromgroup', [
        'title'      => __( 'Metabox added from group!', 'textdomain' ),
        'context'    => 'normal',
        'fields'     => [
            [
                'name'  => __( 'Here is a field', 'textdomain' ),
                'id'    => 'fname',
                'type'  => 'text',
            ],
        ]
    ]);

});

所以我的group() 方法接受一个属性数组,需要将其添加到闭包中每个add() 的属性数组中。

Laravel 用 Routes 很好地做到了这一点,看起来像这样:

Route::group(['middleware' => 'auth'], function () {
    Route::get('/', function ()    {
        // Uses Auth Middleware
    });

    Route::get('user/profile', function () {
        // Uses Auth Middleware
    });
}); 

实现这一目标的最佳方法是什么?

编辑:

这是我的 Metabox 管理器类

namespace Vendor\Lib;

use Vendor\App\Config as Config;

final class Metabox {

    /** @var string */
    protected $prefix;

    /** @var array */
    static private $metaboxes = [];

    public static function getInstance()
    {
        static $inst = null;
        if ($inst === null) {
            $inst = new Metabox();
        }
        return $inst;
    }

    /**
     * Metabox constructor.
     *
     * @param string $prefix
     */
    private function __construct() {
        $this->prefix = Config::get('metabox.prefix');
    }

    /**
     * Add a new metabox.
     *
     * @param string $id
     * @param array $attributes
     */
    public function add( $id, array $attributes ) {
        $attributes['id'] = $id;

        array_walk_recursive( $attributes, function ( &$value, $key ) {
            if (
                $key === 'id'
                && substr( $value, 0, strlen( $this->prefix ) ) !== $this->prefix
            ) {
                $value = $this->prefix . $value; // auto prefix
            }
        } );

        self::$metaboxes[] = $attributes;
    }

    public function group( $attributes, $function) {
        // here comes group method
    }

    /**
     * Register the metaboxes.
     */
    public function register() {
        add_filter( 'rwmb_meta_boxes', function () {
            return self::$metaboxes;
        } );
    }

}

【问题讨论】:

  • 我不明白。您是想在 Laravel 中实现某些目标,还是 Laravel 只是展示您想在 WordPress 中实现的目标或您正在玩的任何玩具?
  • Laravel 只是一个例子。我想创建类似的东西:在闭包中附加到 add 函数的第二个参数数组。
  • Manager 指的是单例类。所以目前无法扩展。
  • 我没有使用任何框架。我会在一秒钟内分享我的 Metabox 管理器的代码

标签: php wordpress laravel closures php-7


【解决方案1】:

这里有一个建议。在调用group 方法时,您可以将可共享信息存储在您的类中,然后在您的add 方法中使用它。

final class Metabox {
    private $group = [];
    ...
}

public function group( $attributes, $function) {
    $this->group = $attributes;
    $function(); // Invoke the closure, I don't remember if this is the right way.
    $this->group = [];  // Clean up the group.
}

现在,对于add 方法。

/**
 * Add a new metabox.
 *
 * @param string $id
 * @param array $attributes
 */
public function add( $id, array $attributes ) {
    if(!empty($this->group))
       $attributes = array_merge($group, $attributes);

    $attributes['id'] = $id;

    array_walk_recursive( $attributes, function ( &$value, $key ) {
        if (
            $key === 'id'
            && substr( $value, 0, strlen( $this->prefix ) ) !== $this->prefix
        ) {
            $value = $this->prefix . $value; // auto prefix
        }
    } );

    self::$metaboxes[] = $attributes;
}

旁注:使用 $attributes 作为第二个参数调用 array_merge 允许您覆盖仅特定添加的组值。

【讨论】:

  • 啊啊该死的太聪明了。我怎么没想到,让我试试这个,我会告诉你的!
  • 有效!谢谢你的帮助。做了一些小的改动:因为你做了 $this->group = $attributes 你设置了 group 变量,所以没有必要再把它设为空(使用 $this->group = [];)。再次感谢!
  • @MelvinKoopmans 如果你调用group方法,稍后只调用add(不分组),如果你不清理它会自动分组。
  • 您知道如何在调用 group 方法时消除指定 use ($manager) 的需要吗?我可以以某种方式将一个实例注入到 group 方法中的闭包中吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-10-28
  • 1970-01-01
  • 2011-09-29
  • 2015-07-28
  • 2018-08-22
  • 2016-11-12
相关资源
最近更新 更多