Тотальная проверка данных, передаваемых в функцию

123 4
php.developer
На сайте с 22.11.2010
Offline
94
#11

Добавляй && is_int($arr['key']) в условие, в таком случае.

kiowas
На сайте с 06.02.2010
Offline
61
#12

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

подпись
F9
На сайте с 13.04.2008
Offline
104
#13
kiowas:
К тому же если я создаю класс, то в конструкторе уже какие-то свойства класса проверяются и вроде бы этого должно быть достаточно, но нет же... Первый же вызов метода из конструктора и меня опять клонит в этом методе все переменные перепроверить.... А вдруг в конструкторе не проверилось?

Чтобы быть спокойным относительно переменных класса, их нужно делать private и задавать значения только через конструктор и только там делать валидацию. Если валидация не проходит, то конструктор должен бросать исключение. Для правильной валидации существуют такие библиотеки, как, например, Zend Validate - поначалу использование таких решений может выглядеть избыточно, но когда набивается достаточно шишек на собственных велосипедах, приходишь к выводу, что ничего особо лишнего на самом деле там нет.

C
На сайте с 04.02.2005
Offline
277
#14

Если php не является строготипизированным языком, то это не значит, что это нужно делать за него.

Проверять нужно все то, что пришло из вне.

валидация int - http://www.php.net/manual/ru/function.filter-var.php

IL
На сайте с 20.04.2007
Offline
435
#15
for93t:
и задавать значения только через конструктор

эм.. а если надо задать "по ходу".. не в конструкторе?

for93t:
то конструктор должен бросать исключение.

Вы реально так делаете? Можно кусок кода?

Валидатор он на то и валидатор, чтобы "проверять" (возвращать тру/не тру + получать список ошибок) , а не исключения кидать.

К тому же, в зависимости от ситуации (сценарии) значение может иметь различные ограничения (к примеру, оформление заказа в админке магазина и на сайте пользователем.. в первом случае email нет смысла делать обязательным полем)

... :) Облачные серверы от RegRu - промокод 3F85-3D10-806D-7224 ( http://levik.info/regru )
F9
На сайте с 13.04.2008
Offline
104
#16
ivan-lev:
эм.. а если надо задать "по ходу".. не в конструкторе?

Тогда нужно сделать public setter-метод, запрограммировать в нем валидацию и использовать его в конструкторе для установки значения переменной класса.

ivan-lev:
Вы реально так делаете? Можно кусок кода?

Если значение переменной класса критично для функционирования всего класса, то да, я реально так делаю. Пример кода:


class Core_Dns_Mx_Route
{
/**
* Hostname
*
* @access private
* @var string
*/
private $_host;

/**
* Class constructor
*
* @access public
*
* @param string $host
* @param int $priority
* @param int $port
*
* @throws Core_Dns_Exception
* @return Core_Dns_Mx_Route
*/
public function __construct($host, $priority = 10, $port = 25)
{
if (!Zend_Validate::is($host, 'Hostname', array('allow' => Zend_Validate_Hostname::ALLOW_DNS + Zend_Validate_Hostname::ALLOW_IP + Zend_Validate_Hostname::ALLOW_LOCAL))) {
throw new Core_Dns_Exception(
escsprintf(_("MX hostname '%s' is invalid. It should be either valid DNS hostname or valid IP address"), $host)
);
}
ivan-lev:
Валидатор он на то и валидатор, чтобы "проверять" (возвращать тру/не тру + получать список ошибок) , а не исключения кидать.

А что вы предлагаете дальше делать с тру/не тру?

IL
На сайте с 20.04.2007
Offline
435
#17
for93t:
А что вы предлагаете дальше делать с тру/не тру?

Пользователю в "цивильном" виде сообщать..

С отображением ему формы ввода.. с теми же данными, которые он ввёл на предыдущем шаге.. и подсветкой ошибки по соседству с полем, в котором ошибка.

for93t:
Тогда нужно сделать public setter-метод, запрограммировать в нем валидацию

А чего ж сразу про сеттер не написать?

ИМХО, гиблый подход.. смешивать конструктор/сеттеры и валидацию.

Думаю, корректнее выносить валидацию в отдельный метод, в котором (в зависимости от задачи либо проверять все поля сразу, либо до первой ошибки) а вызывать явно в контроллере или неявно из методов модели. /Хотя, вполне возможно, иногда такой подход может быть оправданным.../

F9
На сайте с 13.04.2008
Offline
104
#18
ivan-lev:
Пользователю в "цивильном" виде сообщать..

С отображением ему формы ввода.. с теми же данными, которые он ввёл на предыдущем шаге.. и подсветкой ошибки по соседству с полем, в котором ошибка.

Цивильное отображение - это уровень View, а валидация - уровень модели. Вьюхе, грубо говоря, все равно, как происходит проверка данных, ей важно получить список сообщений об ошибках и инструкции, куда их вставлять. А как был сформирован этот список - через исключения, возвращение false или прямым инжектом в какой-нибудь инстанс-коллектор сообщений - View может, точнее должен, не знать.

ivan-lev:
А чего ж сразу про сеттер не написать?

ИМХО, гиблый подход.. смешивать конструктор/сеттеры и валидацию.

Думаю, корректнее выносить валидацию в отдельный метод, в котором (в зависимости от задачи либо проверять все поля сразу, либо до первой ошибки) а вызывать явно в контроллере или неявно из методов модели. /Хотя, вполне возможно, иногда такой подход может быть оправданным.../

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

Валидация данных в модели крайне желательна, поскольку с одной и той же моделью может работать несколько контроллеров и в каждом потребуется делать валидацию, если этого не будет делать модель, а это дублирование кода со всеми вытекающими.

---------- Добавлено 07.06.2013 в 00:49 ----------

ivan-lev:
ИМХО, гиблый подход.. смешивать конструктор/сеттеры и валидацию

Вот тут вы ошибаетесь. Если public-сеттер работает с private переменной, он содержит логику валидации значений для этой переменной и существует соглашение о том, что извне задать значение переменной класса можно только с помощью этого метода, то получается единая точка ввода, которая гарантирует, что данная переменная всегда будет иметь корректное значение (или не иметь его вовсе, т.е. быть null). Такой подход очень распространен в серьезных приложениях/фреймворках. Если вы посмотрите в исходный код ZF, Symfony, Yii и т.п., то обязательно увидите примеры таких сеттеров. Самый упрощенный пример - это сеттер с type hint'ом для аргумента, где type hint как раз служит валидатором. Думаю, таких примеров можно найти предостаточно в любом "неговнокоде" на PHP.

kiowas
На сайте с 06.02.2010
Offline
61
#19

Если появляется идея каким-то образом написать функцию или переопределить какую-то другую, так чтобы она была видна из любого куска скрипта и проверяла переменную на целое число положительно, в этом случае как лучше поступить? Как переопределить или создать свою функцию?

F9
На сайте с 13.04.2008
Offline
104
#20
kiowas:
Если появляется идея каким-то образом написать функцию или переопределить какую-то другую, так чтобы она была видна из любого куска скрипта и проверяла переменную на целое число положительно, в этом случае как лучше поступить? Как переопределить или создать свою функцию?

Простая глобальная функция (function isId($input) { ... }) будет видна из любой точки скрипта, если будет несколько таких функций, можно сделать их статическими методами какого-либо класса:


class Validator {
static final public function isId($input) { ... }
static final public function isEmail($input) { ... }
...
}

, но это не панацея, потому что вместо кучи проверок типа is_numeric(), !empty() и т.п. вы будете писать кучу проверок типа Validator::isId(). Это немного сократит код, но не устранит проблему. Нужно изолировать данные и делать доступ к ним контролируемым, для этого (в т.ч.) и была придумана инкапсуляция.

123 4

Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий