Pull to refresh

Comments 39

Мне подобный прием кажется грязным. Не очевидно(потому что там где у вас регулярки должен быть тип), легко может быть затерто программистом, встроенные валидаторы IDE для регулярок не работают.

PS: Очень много всего на отражениях завязано в phpUnit, но там в большинстве своем используются custom аттрибуты (@dataProvider например), не пересекающиеся со стандартным функционалом doc-блоков.
Я решил использовать аннотации, т.к. обычно для контроллеров вообще не пишу никаких комментариев, да и вызываются эти функции в основном автоматически, т.е. подсветка и подсказки из IDE особо не нужны и мешать они не будут. И наоборот плюсы есть от близости проверок к месту использования, не надо лезть в дальний файл с роутингом, чтобы проверить $num может быть [a-z0-9] или только [0-9].

В любом случае, PHPdoc описание для этих переменных выглядит так:
/**
 * Тестовое действие
 * @a /^[0-9]+$/i
 * @b /^[0-9a-z]+$/i
 * @var a int
 * @var b string
 */

Т.е. как раз использование «не пересекающиеся со стандартным функционалом doc-блоков»

Вероятность любого кода быть затертым кем-то левым существует всегда, но от этого не застраховано вообще ничего :) Мне опасность кажется несколько надуманной, в той же Symfony2 они не побоялись.
Опасность не самое верное слово.
Но мне кажется, что подобный подход имеет смысл в phpUnit, который не часть программы, не обитает на production сервере и с его зависимостями/аттрибутами и правда пришлось бы париться без doc-блоков. Но для организации валидации аргументов экшна контроллера я бы не стал его использовать.
По-поводу того, что чем ближе — здесь мне нравится концепция маршрутов в yii. На оснвое аргументов можно перенаправить действие к другому экшну другого контроллера и вся эта логика хранится в конфигурации UrlManager.
Ниже правильно отписались — магии должно быть как можно меньше и одно дело магические методы, а совсем другое вынос логики в комментарии.
Интересно, но это магия, а магии в проекте должно быть как можно меньше для улучшения читаемости кода.
На мой взгляд читаемость наоборот возрастает — сразу видно, какие переменные используются, какие проверки на них наложены.
Читаемость определенно возрастает, я когда начинал с Симфони 2, я воспринял эту особенность в штыки и честно говоря почти передумал ее использовать из-за этого, но сейчас, после пару месяцев работы — я аннотации ни за что не променяю, крайне удобная вещь, конфигурация рутов теперь просто сказка.

Я считаю пока человек не попробует их использовать хоть какое-то время, смысла спорить тут нет.

P.S. Работаю в PhpStorm, проблем не было ни разу.
$method->getDocComment();

Обана. Теперь комментарии являются частью кода программы?

/**
* @a /^[0-9]+$/i
*/
function do($fileName) {

file_put_contents($fileName, 'somthing');

}

Написав этот комментарий я уверен, что выполнить ФС-инъекцию невозможно?
А потом кто-то со спокойной совестью проходится обфускатором или ещё лучше энкодером. И тот кто удалит все комментарии будет прав, потому что комментарии не могут никак влиять на ход выполнения программы и тем более не могут влиять на её безопасность.
Я знаю тот факт, что русские не читают инструкцию по применению до тех пор, как что-то сломалось или не работает. Но об этой особенности системы таки следует написать и предупредить, что комментарии являются неотъемлемой частью, а кто не понял, тот ССЗБ

Ну а в особо важных местах, где потенциально есть опасность, можно не использовать комментарий, а по старинке воткнуть прямую проверку.
UFO just landed and posted this here
Имхо, это выглядит эффектно, и кажется удобным, но не более того. Магия вредна, особенно в коллективной и долгосрочной разработке. Если нужны валидаторы — оформлять соответствующие функции, классы с методами или конфиги с валидаторами. Если нравится макропрограммирование — делать компиляторы макрокода в обычный стандартный код. Недостатки описанного подхода очевидны: нарушение принципов программирования (логика находится в… комментариях к коду!), невозможность обработки кода (обфускации например). С архитектурной точкизрения, эти трюки ничем не лучше логики, основанной на файловой системе.
Но косательно обфускации — вопрос спорный. Да, без подготовки — нельзя, посредствам отрожения лишь получается информация о параметрах, которые можно отдельно закешировать. А потом уже проводить абфускацию.

Я очень надеюсь что аннотации будут включены в сам язык. Мне они еще при работе с ASP понравились. Удобно.
обфускацию*… Праздники…
Чем удобно? Тем, что можно описать в комментариях ожидаемые значения переменных и результата, а потом получать их по код ассисту — бесспорно, удобно. Но только, если это не влияет на ход выполнения. Комментарий должен оставаться комментарием. А для проверки значений явно вызывать валидатор в первой строчке метода.
По сути аннотации через комментарий это костыль, я очень жду когда их (аннотации) включат в сам язык.
В Yii используют ReflectionAPI для аргументов экшенов, но немногу по другому — он подставляет параметры по имени переменной, а в роутах прописываются именованные параметры.

К тому же на phpDoc полагаться 100% нельзя, поскольку опкод кешеры могут его вырезать (в APC багтрекере точно был баг на эту тему).
А вы не знаете как обстоят дела с этим багом сейчас? Мне тогда он сильно жизнь подпортил.
Нет, не следил. Просто не так давно подымалось в листе рассылки разработчиков PHP. Гугл вам в помощь в данном случае :)
В Yii еще используется ReflectionAPI для SOAP-сервера. И вот там он смотрит на комментарии.
Извините, пожалуйста, но это — жуть! :)
Почему нельзя было сделать так:
addMethodVariable('Controller', 'testAction', 'a', '/^[0-9]+$/i');
addMethodVariable('Controller', 'testAction', 'b', '/^[0-9a-z]+$/i');
Если уж есть в этом необходимость?
А почему нельзя прочитать название статьи. Внимательно
Потом прочитать дисклеймер.
Потом прочитать постскриптум
И удержаться от комментариев не в тему.
Я высказал своё личное мнение, т.к. я считаю, что такой подход в корне не верен и противоречит многим «законам» программирования. PHPDoc для того и PHPDoc, чтобы хранить в себе документацию (приходится быть К.О). :)
Это можно использовать в непосредственно разработке, а в продакшене просто один раз закешировать все роуты и все, все счастливы, хоть заобфусцируйся :)

Но мне лично это не удобно, так как чтобы подправить роут придется лезть в контроллер этого роута, а это лишнее действие, для меня все же проще конфиг отдельный :)
Мне намного больше нравится как в Kohana 3 сделано. В экшенах вообще нет аргументов, зато все параметры роутинга есть в объекте Request. Т.е. делаем в экшене $a = $this->request->param('a'); и все.
Reflection это очень-очень медленно и использовать его в интенсивных (даже ещё не нагруженных) проектах — есть зло и напрасная утилизация процессорного времени. И кстати, это может поломаться в любой момент при использовании кешеров опкода.
Да ладно. Чегой-та я накапитанил.
Хм… ну оверхед-то от такого подхода какой? Приходилось видеть упоминание о том, что с Reflection код работал в 3 раза медленее, чем без него. И это на каждом вызове. Поэтому использование Reflection как основной архитектурный подход может неслабо затормозить движок. Так что… есть ли от указанного подхода профиты?
Я не предлагаю использовать этот подход везде и вся. Я вообще не предлагаю его где либо использовать. Я всячески выделил и обратил внимание, что мне было интересно посмотреть и понять как работает Reflection, тем более это используется в крупных фреймворках на определенном примере, который первым пришел в голову.

Тем не менее, не устающие минусовать хабравоины отстаивают догмы истинной веры.

Представьте, что это не контроллер, а тест. Не продакшн, а девелопмент. И вообще все комментарии будут скомпилированы во что-то прекрасное и кошерное идеологически верное.
UFO just landed and posted this here
А какие еще варианты для динамического вызова контроллера?
вот такой:

function index($a){return $a;}
$a = 'some interesting string';
$ololo='index';
echo $ololo($a);
Такой вызов может быть только если заранее известно число аргументов в вызываемом контроллере.
В примере это не так, так что этот способ не подходит.
т.е.? а в таком вызове call_user_func_array( 'index', array( $a )) значит заранее не надо знать кол-во аргументов?

можно написать call_user_func_array( 'index', array( $a,$b,$c,$d,$ololo ) )?
Вы невнимательно читали статью :)

$arr = CheckURLValid('Controller', 'testAction', $_GET);
call_user_func_array(array('Controller', 'testAction'), $arr);

Предложите как сделать этот вызов с помощью $ololo(...) не зная количество аргументов для функции.
что-то я не догоняю. в call_user_func_array(array('Controller', 'testAction'), $arr) неизвестно кол-во аргументов? т.е. в Controller->testAction можно пихнуть их любое кол-во?
Да, иначе и не было бы смысла городить всё это :)
В контроллере указывается любое количество нужных параметров, затем в приведенной реализации CheckURLValid() проверяются и подставляются все параметры в соответствии с настройками.
Таки решил проверить. Простейший скрипт:
    $time = microtime(true);
    function index ( $a ) { return $a; }

    $a = 'some interesting string';

    //Версия №1
    echo index( $a );

    //Версия №2
    echo call_user_func_array( 'index', array( $a ) );

    echo number_format( (microtime(true) - $time), 10, '.', '' );


На моей девелоперской машине вариант №1 отрабатывает за ~0.000012 секунды, вариант №2 за ~0.000025
Т.е. формально да, очень медленно, аж в два раза. Но это уже ближе к оптимизации на print и echo.
Sign up to leave a comment.

Articles