WordPress-подобная модель для просмотра системы событий API (MVC) - PullRequest
1 голос
/ 18 января 2010

Wordpress имеет хорошую систему API. Я изо всех сил пытаюсь создать такой же гибкий, используя более традиционную интерпретацию MVC. Типичный класс представления может быть таким:

class View
{
    public function set($name, $value)
    {
         $this->data[$name] = $value
    }

    public function __get($name) ... you know how it works
}

Вариант использования: контроллер, добавляющий заказ, содержащий строки заказа:

$view->add('order', $orderModel);

Тогда файл шаблона может иметь что-то вроде

foreach ($this->order->getOrderLines() as $orderLine)
{
    ?><div><?php echo $orderLine->getItemName(); ?><div><?php
}

По крайней мере, это то, что обычно встречается во многих средах PHP MVC. Я открыт для альтернативных реализаций, которые решают вопрос:

Как добавить систему событий, как в WordPress? Например, фильтр OrderLineItemName.

1 Ответ

2 голосов
/ 21 января 2010

Хорошо,

Я не на 100% точно, что вы хотите сделать, но у меня есть идея.

Может быть, вы имеете в виду что-то вроде этого:

class View {
    public $hooks = array('getsomeVar');
    public $hooks_functions = array();
    public $attributes = array();
    public function __set($k,$v) {
        $this->attributes[$k] = $v;
    }
    public function __get($k) {
        if (isset($this->attributes[$k])){
            $hooks = $this->get_functions_by_hook('get' . $k);
            if (!empty($hooks)){
                foreach ($hooks as $klass=>$methods) {
                    if (class_exists($klass)){
                        $class = new $klass();
                        foreach ($methods as $method) {
                            if (method_exists($class,$method)){
                                $this->attributes[$k] = $class->$method($this->attributes[$k]);
                            } 
                        }
                    }
                }
            }
            return $this->attributes[$k];
        } else {
            throw new Exception($k . " is not a view variable");
        }
    }

    public function register_filter($name,$class,$method) {
        if (in_array($name,$this->hooks)){
            $this->hooks_functions[$name][$class][] = $method;
        } else {
            throw new Exception($name . ' is not a valid hook');
        }
    }

    public function get_functions_by_hook($name) {
        if (array_key_exists($name,$this->hooks_functions)){
            return $this->hooks_functions[$name];
        }
        return array();
    }
}
class MyPlugin {
    public function fix_string($str) {
        return str_replace("ruby",'php',$str);
    }
}

$v = new View();
$v->someVar = 'ruby is great';
$v->register_filter('getsomeVar','MyPlugin','fix_string');
echo $v->someVar;

или вы можете использовать этот метод, который больше похож на событие. Снова пример кода, но вы должны быть в состоянии отобрать его.

class EventDispatcher {
    public static $listeners = array();
    public static function registerListener(&$instance) {
        if (!in_array($isntance,self::$listeners)){
            array_push(self::$listeners,$instance);
        }
    }
    public static function dispatchEvent($name,&$value) {
        foreach (self::$listeners as $listener) {
            if (method_exists($listener,'interests')){
                $funcs = $listener->interests();
                if (array_key_exists($name,$funcs)){
                    foreach ($funcs as $f) {
                        $value = $listener->$f($value);
                    }
                }
            }
        }
    }
}
class Plugin {
    public static function registerPlugin($class_name) {
        if (class_exists($class_name)){
            EventDispatcher::registerListener(new $class_name());
        }
    }
}
class Model {
    public function __construct() {
        EventDispatcher::registerListener($this);
    }
    public function special($value) {
        echo "I got called too!\n\n";
        return $value;
    }
    public function interests() {
        return array(
            "getsomeVar" => "special",
        );
    }
}
class View {
    public $attributes = array();
    public function __set($k,$v) {
        $this->attributes[$k] = $v;
    }
    public function __get($k) {
        if (isset($this->attributes[$k])){
            EventDispatcher::dispatchEvent('get' . $k,$this->attributes[$k]);
            return $this->attributes[$k];
        } else {
            throw new Exception($k . " is not a view variable");
        }
    }
}
class MyPlugin {
    public function fix_string($str) {
        return str_replace("ruby",'php',$str);
    }
    public function interests() {
        return array(
            "getsomeVar" => "fix_string",
        );
    }
}
Plugin::registerPlugin('MyPlugin');
$model = new Model();
$v = new View();
$v->someVar = 'ruby is great';
echo $v->someVar;

Это просто пример кода, я вообще так не делаю, но, похоже, это то, о чем вы говорите.

Cheers, Jason

Приложение:

Большая часть этого материала посвящена базе кодов WP.

WP обращается к переменным, установленным в глобальной области видимости, которые изменены следующим образом:

function add_filter($tag, $function_to_add, $priority = 10, $accepted_args = 1) {
    global $wp_filter, $merged_filters;

    $idx = _wp_filter_build_unique_id($tag, $function_to_add, $priority);
    $wp_filter[$tag][$priority][$idx] = array('function' => $function_to_add, 'accepted_args' => $accepted_args);
    unset( $merged_filters[ $tag ] );
    return true;
}

У него есть некоторые другие функции, такие как has_filter и т. Д. *

function apply_filters($tag, $value) {
    global $wp_filter, $merged_filters, $wp_current_filter;

    $args = array();
    $wp_current_filter[] = $tag;

    // Do 'all' actions first
    if ( isset($wp_filter['all']) ) {
        $args = func_get_args();
        _wp_call_all_hook($args);
    }

    if ( !isset($wp_filter[$tag]) ) {
        array_pop($wp_current_filter);
        return $value;
    }

    // Sort
    if ( !isset( $merged_filters[ $tag ] ) ) {
        ksort($wp_filter[$tag]);
        $merged_filters[ $tag ] = true;
    }

    reset( $wp_filter[ $tag ] );

    if ( empty($args) )
        $args = func_get_args();

    do {
        foreach( (array) current($wp_filter[$tag]) as $the_ )
            if ( !is_null($the_['function']) ){
                $args[1] = $value;
                $value = call_user_func_array($the_['function'], array_slice($args, 1, (int) $the_['accepted_args']));
            }

    } while ( next($wp_filter[$tag]) !== false );

    array_pop( $wp_current_filter );

    return $value;
}

Это не система, управляемая событиями, это таблица поиска методов, которая представляет собой просто гигантский хеш, который ищет определенные пользователем функции для вызова.

apply_filters, и все плагиноподобные функции вызываются процедурно при визуализации кода, вот пример

    if ( $prefixed ) {
        $value = apply_filters("pre_$field", $value);
        $value = apply_filters("${field_no_prefix}_save_pre", $value);
    } else {
        $value = apply_filters("pre_post_$field", $value);
        $value = apply_filters("${field}_pre", $value);
    }

Или для действий в реальном представлении шаблона, например, так:

<p class="submit"><input type="submit" class="button" name="submit" value="<?php esc_attr_e('Add Category'); ?>" /></p>
<?php do_action('edit_link_category_form', $category); ?>
</form>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...