ООП динамическое добавление методов

Тема в разделе "PHP Pro", создана пользователем CrashX, 22 мар 2011.

Статус темы:
Закрыта.
  1. CrashX

    CrashX В прошлом XSiteCMS

    Регистр.:
    6 июн 2008
    Сообщения:
    682
    Симпатии:
    112
    ООП динамическое добавление методов
    может кто делал ранее
    нужно скажем есть свойство
    keyword и нужно его сделать методом и назначить набор свойст вида
    get,set,generate,clear
    щас имею вид
    Код:
    $engine->document->keySet();
    $engine->document->keyGet();
    $engine->document->keyGen();
    а хочу
    внутри должно быть
    Код:
    private $value=array();
    $engine->document->key->generate();
    $engine->document->key->get();
    $engine->document->key->set();
    набор действий стандартных одинковый это вернуть ключ, добавить ключ, создать, очистить.

    как нибудь можно скажем имея шаблон расширять нужные свойства до объектов

    зачем это нужно ? да тупо для удобства
    тк мне удобнее обращаться к некоторому свойству не трогая его само что бы голова не болела что могу его испортить

    такую фигню хочу добавить массово многим объектам
     
  2. chang

    chang

    Регистр.:
    20 ноя 2009
    Сообщения:
    364
    Симпатии:
    117
    ну так сделайте внутреннюю переменную key каким-то классом (на подобии паттерна Registry ) внутри которого будут реализованы все эти методы get,set,generate,clear

    или я чего-то не то понял?
     
  3. saen

    saen

    Регистр.:
    6 авг 2006
    Сообщения:
    756
    Симпатии:
    129
    То что ТС хочет реализовать, называется метапрограммирование, которое в PHP отсутствует. Можно попробывать сделать эмуляцию метапрограммирования через создание анонимных лямбда-функций либо попробовать поиграть с дополнением php runkit.
     
  4. CrashX

    CrashX В прошлом XSiteCMS

    Регистр.:
    6 июн 2008
    Сообщения:
    682
    Симпатии:
    112
    в общем как хотел не смог сделал проще
    сделал для каждого метода, который нужно расширить и расширил в конструкторе.
    благо еще раз подумал и сделал там где действительно нужно скрыть
    например

    PHP:
    <?php


    /**
     * Класс документа
     */
    class Document {

      var 
    $version 0.01;
      public 
    $title null;
      public 
    $description null;
      public 
    $keyword null;
      public 
    $style null;
      public 
    $script null;
      public 
    $header null;

      public function 
    __construct() {
        
    $this->keyword = new Keyword();
        
    $this->description = new Description();
        
    $this->title = new Title();
      }

      
    /**
       * @global Engine $engine
       */
      
    function headers() {
        global 
    $engine;
        
    header("Content-Type: text/html; charset=" $engine->language->get('CHARSET'));
        
    header("Cache-Control: no-store, no-cache, must-revalidate");
        
    header("Cache-Control: post-check=0, pre-check=0"false);
        
    header("Pragma: no-cache");
        
    header("Expires: " gmdate("D, d M Y H:i:s"0) . " GMT");
        
    header("Last-Modified: " gmdate("D, d M Y H:i:s") . " GMT");
        
    header("X-Powered-By: XSiteCMS ");
      }

      
    /**
       * @global Engine $engine
       * @return <type>
       */
      
    function meta() {
        global 
    $engine;
        return 
    '<meta charset=' $engine->language->get('CHARSET') . ' />
      <meta http-equiv="content-type" content="text/html; charset=' 
    $engine->language->get('CHARSET') . '" />
      <meta name="title" content="' 
    $this->title->get() . '" />
      <meta name="keywords" content="' 
    $this->keyword->get() . '" />
      <meta name="description" content="' 
    $this->description->get() . '" />
      <meta name="abstract" content="' 
    $this->description->get() . '" />
      <meta name="generator" content="' 
    GENERATOR '" />'
        
    . (GOOGLE "\n" '  <meta name="verify-v1" content="' GOOGLE '" />' '')
        . (
    YANDEX "\n" '  <meta name="yandex-verification" content="' YANDEX '" />' '')
        . (
    WEBMONEY "\n" '  <meta name="webmoney.attestation.label" content="' WEBMONEY '" />' '')
        . 
    "\n" '  <link rel="alternate" href="feed.rss" type="application/rss+xml">
      <link rel="icon" href="favicon.ico" type="image/x-icon">
      <link rel="shortcut icon" href="favicon.ico" type="image/x-icon">'
    ;
      }
    }

    /**
     * Класс ключевых влов
     */
    class Keyword {

      var 
    $version 0.01;
      public 
    $config = array('words' => 15'min' => 5'max' => 25);
      private 
    $keywords = array();
      private 
    $endings = array("ые""ое""ие""ий""ая""ый""ой""ми""ых""ее""ую""их""ым");
      private 
    $exceptions = array("able""about""даже""дал""далее""далеко"
      
    );

      
    /**
       *
       * @global Engine $engine
       */
      
    public function __construct() {
        global 
    $engine;
        
    $this->keywords preg_split("/[\s,]+/s"$engine->string->trim($engine->config['keywords']));
      }

      
    /**
       *
       * @global Engine $engine
       */
      
    function get() {
        global 
    $engine;
        return (string) 
    implode(", "$this->keywords);
      }

      
    /**
       *
       * @global Engine $engine
       * @param <type> $key
       */
      
    function set($key) {
        global 
    $engine;
        if (
    in_array($key$this->keywords)):
          return 
    false;
        else:
          
    $this->keywords[] = $key;
        endif;
      }

      
    /**
       *
       * @global Engine $engine
       */
      
    function clear() {
        global 
    $engine;
        
    $this->keywords = array();
      }

      
    /**
       *
       * @global Engine $engine
       * @param string $text
       * @return mixed
       */
      
    function generate($text=null) {
        global 
    $engine;
        
    $text $engine->string->lower($text);
        
    // вырезаем теги, символы и лишние пробелы
        
    $text $engine->string->clean($text);
        
    // создаем массив слов
        
    $words preg_split("/[\s]+/s"$text);
        ...
        return 
    $words;

      }

    }

    /**
     * Класс составления описания страницы
     */
    class Description {

      var 
    $version 0.01;
      public 
    $config = array('length' => 300);
      private 
    $description = array();
      private 
    $synonyms = array('searche' => 'replace');

      
    /**
       *
       * @global Engine $engine
       */
      
    public function __construct() {
        global 
    $engine;
        
    $this->description $engine->config['description'];
      }

      
    /**
       *
       * @global Engine $engine
       * @param <type> $key
       */
      
    function get() {
        global 
    $engine;
        return 
    $this->description;
      }

      
    /**
       *
       * @global Engine $engine
       * @param <type> $key
       */
      
    function set($string) {
        global 
    $engine;
        
    $this->description .= $string;
      }

      
    /**
       *
       * @global Engine $engine
       */
      
    function clear() {
        global 
    $engine;
        
    $this->description null;
      }

      
    /**
       *
       * @global Engine $engine
       * @param string $text
       * @return mixed
       */
      
    function generate($text=null) {
        global 
    $engine;
      }

    }

    /**
     * Класс заголовка страницы
     */
    class Title {

      var 
    $version 0.01;
      public 
    $config = array('length' => 300'separator' => ' - ');
      private 
    $title = array();
      private 
    $synonyms = array('searche' => 'replace');

      
    /**
       *
       * @global Engine $engine
       */
      
    public function __construct() {
        global 
    $engine;
        
    $this->title[] = $engine->config['title'];
      }

      
    /**
       *
       * @global Engine $engine
       * @param <type> $key
       */
      
    function get() {
        global 
    $engine;
        return (string) 
    implode($this->config['separator'], $this->title);
      }

      
    /**
       *
       * @global Engine $engine
       * @param <type> $key
       */
      
    function set($string) {
        global 
    $engine;
        
    $this->title[] = $string;
      }

      
    /**
       *
       * @global Engine $engine
       */
      
    function clear() {
        global 
    $engine;
        
    $this->title null;
      }

      
    /**
       *
       * @global Engine $engine
       * @param string $text
       * @return mixed
       */
      
    function generate($text=null) {
        global 
    $engine;
      }

    }

    //
    ?>
     
    dandandan нравится это.
  5. LEE_ROY

    LEE_ROY

    Регистр.:
    26 янв 2007
    Сообщения:
    205
    Симпатии:
    20
    не совсем вник в задачу, но кейворд можно сделать отдельным классом с методом __toString который позволит обращаться к кейворду как к обьекту так и к строке где нужно.
     
  6. CrashX

    CrashX В прошлом XSiteCMS

    Регистр.:
    6 июн 2008
    Сообщения:
    682
    Симпатии:
    112
    магические методы в этом случае ненужны, ими пользоватся умею...
    увы то что хочется нельзя делать в пхп, да и нужна как то отпала...
    нужно было расширение нужных свойст до методов со стандартным набором действий, и защищенным хранилищем внутри.
     
  7. saen

    saen

    Регистр.:
    6 авг 2006
    Сообщения:
    756
    Симпатии:
    129
    Пару замечаний по твоему коду:
    1)
    PHP:
    return (string) implode(", "$this->keywords); 
    зачем приводить к типу "string", если ф-я implode итак возвращает строку?

    2) Есть такой паттерн проектирования как регистр(registry), который представляет из себя единое глобальное хранилище. На твоем месте я бы отказался от использования глобальных переменных в ф-ии в пользу регистра.

    И еще по поводу твоей задачи: с выходом новой ветки php(5.4 или 6) появится поддержка traits(для непрошаренных это значит множественное наследование). Да и про импорт-оператор "use" ты наверняка не слышал...
     
  8. CrashX

    CrashX В прошлом XSiteCMS

    Регистр.:
    6 июн 2008
    Сообщения:
    682
    Симпатии:
    112
    у меня и так подобие но только без __clone
    у меня однократная инициализация, вот иногда нужно перезагружать класс с другим расширением но пока не придумал как,
    поэтому у меня большая зависимость между классами, 50% мелких классов самодостаточна но более крпные прямолинейно зависят от мелких...
    хранилищем у меня выступает корневой класс Engine в который загружаются новый классы при обращении к несуществющему свойству, методу и тп...

    про (string) да приведение, поидее нужно делать именно так но у нас мало кто так делает, да и там не полный набор показан, часть просто вырезана.
     
  9. saen

    saen

    Регистр.:
    6 авг 2006
    Сообщения:
    756
    Симпатии:
    129
    так почему надо делать приведение к типу "string", если ф-я implode итак возвращает строку?
     
  10. CrashX

    CrashX В прошлом XSiteCMS

    Регистр.:
    6 июн 2008
    Сообщения:
    682
    Симпатии:
    112
    у меня часть кода вырезана... там вызов еще некоторых ключей)
    (int)(string) по большей части, привычка писать...
    просто где то читал что типа так нужно... да и сам не читаю что они возвращают, а то есть и mixed) а так поменяю чего и все будет все равно норм)
     
Статус темы:
Закрыта.