За последние 24 часа нас посетили 20848 программистов и 1010 роботов. Сейчас ищут 366 программистов ...

Является ли метод магическим

Тема в разделе "Прочие вопросы по PHP", создана пользователем qwert_ukg, 12 фев 2014.

  1. qwert_ukg

    qwert_ukg Активный пользователь

    С нами с:
    20 июл 2010
    Сообщения:
    387
    Симпатии:
    0
    Адрес:
    Алмата
    там покруче даже там __set() вызывает __call()
     
  2. iliavlad

    iliavlad Активный пользователь

    С нами с:
    24 янв 2009
    Сообщения:
    1.689
    Симпатии:
    4
    можете показать этот код?

    я понимаю, что переменную можно создать в классе, которая там не определена, но вот метод, по-моему, нельзя.
    Но вдруг можно.
    Код (Text):
    1. <?php
    2. class A {}
    3. $a = new A();
    4.  
    5. $a->b = 1;
    6. echo $a->b; // видим 1
    7.  
    8. $a->c = function() {echo 2;};
    9.  
    10. call_user_func_array(array($a, 'c'), array()); // call_user_func_array() expects parameter 1 to be a valid callback, class 'A' does not have a method 'c' in ... on line ...
    11.  
    12. $a->c(); // Call to undefined method A::c() in ... on line ...
    13.  
    14. exit();
     
  3. runcore

    runcore Старожил

    С нами с:
    12 окт 2012
    Сообщения:
    3.625
    Симпатии:
    158
    как описали изначально задачу, так мы её и поняли.
    а вот это поподробнее. как именно вы это сейчас делаете? опишите подробнее или код покажите.
     
  4. qwert_ukg

    qwert_ukg Активный пользователь

    С нами с:
    20 июл 2010
    Сообщения:
    387
    Симпатии:
    0
    Адрес:
    Алмата
    полный гугл примеров, вот один из них:

    Код (Text):
    1. class blank
    2. {
    3.     private $functions = array();
    4.     private $vars = array();
    5.  
    6.     function __set($name, $data)
    7.     {
    8.         if(is_callable($data)) $this->functions[$name] = $data;
    9.         else $this->vars[$name] = $data;
    10.     }
    11.  
    12.     function __get($name)
    13.     {
    14.         if(isset($this->vars[$name]))
    15.         {
    16.             return $this->vars[$name];
    17.         }
    18.     }
    19.  
    20.     function __call($method,$args)
    21.     {
    22.         if(isset($this->functions[$method]))
    23.         {
    24.             return call_user_func_array($this->functions[$method], $args);
    25.         }
    26.     }
    27. }
    Код (Text):
    1. $obj = new blank;
    2.  
    3. $obj->param = 'Новый параметр';
    4. $obj->method = function()
    5. {
    6.     return 'Новый метод';
    7. };
    8.  
    9. echo $obj->param;
    10. echo $obj->method();
    Добавлено спустя 1 минуту 16 секунд:
    и это не единственный вариант, можно через Reflection но я не пробовал

    Добавлено спустя 4 минуты 26 секунд:
    я про пример спросил, там вроде все понятно
     
  5. iliavlad

    iliavlad Активный пользователь

    С нами с:
    24 янв 2009
    Сообщения:
    1.689
    Симпатии:
    4
    гм. мягко скажем - это извращение. и лучше от этого сразу отказаться.

    но решение задачи в таком коде очевидно: если имя метода есть в массиве $functions, то это магический метод.
     
  6. qwert_ukg

    qwert_ukg Активный пользователь

    С нами с:
    20 июл 2010
    Сообщения:
    387
    Симпатии:
    0
    Адрес:
    Алмата
    странно, но это обычная реализация фабрики на пхп

    Добавлено спустя 11 минут 9 секунд:
    вообще не о том, причем здесь что я делаю??? вам всем хочется проверить мой уровень? или по тролить или что? я просто не могу понять какое отношение имеет задача которую я пытаюсь реализовать к моему вопросу?
    еще раз:

    в приложении необходимо проверить, описан ли вызываемый метод/свойство с помощью магии (__call() или __callStatic() или __set()), или он обычный

    пример:
    Код (Text):
    1.  
    2. class myClass {
    3.  
    4.    public function __call($method, $arguments)
    5.    {
    6.       return 'is magic';
    7.    }
    8.  
    9.    public function notMagic()
    10.    {
    11.       return 'not a magic';
    12.    }
    13.  
    14. }
    15.  
    16.  
    17. $reflection = new ReflectionMethod('myClass', 'magic');
    18.  
    19. if ($reflection->isMagic())
    20. {
    21.    /* do some shit if is magic */
    22. }
    в классе 2 метода
    Код (Text):
    1. $reflection->anyShit()
    и
    Код (Text):
    1. $reflection->notMagic()
    как из вне узнать какой из них как описан?

    если вам не интересно или не понятно, или вы считаете мой вопрос или меня глупым, или по любой другой причине, просто оставьте без внимания
     
  7. iliavlad

    iliavlad Активный пользователь

    С нами с:
    24 янв 2009
    Сообщения:
    1.689
    Симпатии:
    4
    я ж написал - добавьте в ваш класс метод isMagic(), где проверяете массив $functions.

    Использование Reflection - ещё большее извращение, чем магические методы)))

    Если вдруг вам интересно, то пара доводов - отладка и использование IDE. Могу завтра ещё добавить.

    и кстати, я думал, что фабрика - это что-то типа такого
    Код (Text):
    1. <?php
    2. class FormElementFactory
    3. {
    4.     public static function getFormElement($name, $args)
    5.     {
    6.         $class = 'FormElement' . $name;
    7.  
    8.         return new $class($args);
    9.     }
    10. }
    11.  
    12. $element = FormElementFactory::getFormElement('submit', array());
    ваш код, снова по-моему, это не фабрика, но на что похоже тоже поищу завтра.


    пс. извините, если обидел, просто хотел помочь.
     
  8. runcore

    runcore Старожил

    С нами с:
    12 окт 2012
    Сообщения:
    3.625
    Симпатии:
    158
    думаю что никак.
    обычные методы можно проверить через method_exist или рефлекшн.
    а то что описано внутри __call например, никак не узнать. если только не перечислить списк магических методов внутри отдельной переменной-списка. заводите новый метод, добавляйте в список. да вам об этом уже писали выше.
     
  9. igordata

    igordata Суперстар
    Команда форума Модератор

    С нами с:
    18 мар 2010
    Сообщения:
    32.410
    Симпатии:
    1.768
    я вообще не понял зачем это нужно
     
  10. qwert_ukg

    qwert_ukg Активный пользователь

    С нами с:
    20 июл 2010
    Сообщения:
    387
    Симпатии:
    0
    Адрес:
    Алмата
    да я сам не особо понимаю :)

    Добавлено спустя 3 минуты 7 секунд:
    мне нужно до того как положить его в этот массив проверить существует ли он в родителе (AR)

    а фабрика это когда толпой создаешь объкты, которыми также толпой и управляешь
     
  11. iliavlad

    iliavlad Активный пользователь

    С нами с:
    24 янв 2009
    Сообщения:
    1.689
    Симпатии:
    4
    Если хочется через рефлекшн, то есть ReflectionProperty, у ReflectionProperty есть getValue(). Можно получить значение твоего массива (хоть они и приватный) и уже работать с ним.


    Тут кстати ещё такая проблема. Всё-таки ты не методы класса создаёшь. Ты также добавляешь некую переменную, в которую кладёшь название функции. А вот у этой функции контекста объекта-то нет. Его туда явно надо передавать, что-то типа $obj->method = function($obj) {} и потом $obj->method($obj). В самой функции будет получение свойств как $obj->prop, а не $this->prop. Как-то так.
    Собственно поэтому не получается использовать обычный method_exist(), метод-то не добавляется, как бы ты не уговаривал :)
     
  12. [vs]

    [vs] Суперстар
    Команда форума Модератор

    С нами с:
    27 сен 2007
    Сообщения:
    10.553
    Симпатии:
    631
    Описанный метод является не магическим, а недоступным.
    ман:
    Следовательно, получить о нем какую-либо информацию, невозможно. Бектрейс проливает свет на кухню магии:
    Код (PHP):
    1. <?php
    2.  
    3. class a {
    4.  
    5.   public function __call($method, $arguments) {
    6.     if ($method == 'magic') {
    7.       var_dump(debug_backtrace());
    8.       echo __METHOD__ . "\r\n";
    9.       echo 'Is callable?';
    10.       var_dump(is_callable('a::magic'));
    11.       return 'is magic';
    12.     }
    13.   }
    14.  
    15. }
    16.  
    17. $a = new a;
    18. $a->magic();
    19. echo 'Is callable?';
    20. var_dump(is_callable('a::magic'));
    21.  
    итак, мы видим, что обращение к неопределенному методу magic ведет на __call, которому передается два аргумента: имя метода magic и ссылка на массив с аргументами magic. Константа __METHOD__ показывает, что в действительности выполняется метод __call. Но магия все же есть: метод magic действительно появляется во время выполнения __call, и исчезает сразу после выполнения. Очевидно, это способ избежать Fatal error.
    Магия или нет - наверняка можно определить из самого метода, а снаружи только косвенно, по is_callable = false.
     
  13. qwert_ukg

    qwert_ukg Активный пользователь

    С нами с:
    20 июл 2010
    Сообщения:
    387
    Симпатии:
    0
    Адрес:
    Алмата
    спасибо чувак! ты реально крут!
    я думаю можно немного поправить фреймворк
    еще раз спасибо!
     
  14. unrecovered

    unrecovered Новичок

    С нами с:
    24 янв 2014
    Сообщения:
    45
    Симпатии:
    0
    о моск мой моск...