Проверка данных в ArrayAccess

khrisanfov

Новичок
Добрый день! Прошу помощи, совсем запутался в проектировании класса.
Есть производный класс Company и базовый класс ArrayAccess.
Если я присваиваю данные какому либо полю таким образом $company["name"] = "Name"; то как получить информацию о том что всё прошло успешно (данные корректны и всё присвоилось успешно)? Ведь такая конструкция if($company["name"] = "Name") всегда вернёт TRUE. В C++ к примеру можно было бы перегрузить оператор "[]" и сделать возвращаемое значение каким я захочу. Тут же мне приходится дважды проверять данные, например так:
PHP:
if($company->checkName("Name")) $company["name"] = "Name";
Данные проверяются дважды, в методе checkName() и в "перегруженном []" так как объект должен следить за корректностью своих данных. Получаются какие-то излишки с двойной проверкой.
Как решить данную проблему? Может я слишком заморачиваюсь?
 

Духовность™

Продвинутый новичок
Если я присваиваю данные какому либо полю таким образом $company["name"] = "Name"; то как получить информацию о том что всё прошло успешно
Это бессмысленная проверка. Всегда присваивание через [] будет успешным. Если вы с С перешли на PHP, то не распространяйте свои знания по С на PHP, это другой язык.

как получить информацию о том что всё прошло успешно (данные корректны и всё присвоилось успешно)?
создать явно методы get/set, если нужно делать какие-то проверки. Или, если охота поизврощаться, вызывать несуществующие методы типа setName($name), через __call их отлавливать, определять, какой переменной-члену класса идет присваивание и на основе заранее созданной карты опций делать проверку.


Далее, насчет ArrayAccess. Это очень спорный по удобству использования объект. Если вы его используете, то должны четко понимать, зачем это делаете.
 

Adelf

Administrator
Команда форума
Если вы его используете, то должны четко понимать, зачем это делаете.
Кстати да. В данном случае похоже гораздо лучше подойдут __set и __get
 

Духовность™

Продвинутый новичок
Кстати да. В данном случае похоже гораздо лучше подойдут __set и __get
Не... ему нужно ещё и проверку делать.

Как показала лично моя практика, в PHP, в котором массив не является объектом, лучше не использовать синтаксис массивов для объектов, т.е. грубо говоря, массив - это массив, объект - это объекти . Иначе в неумелых руках это приведет к катастрофе.
 

флоппик

promotor fidei
Команда форума
Партнер клуба
Как показала лично моя практика, в PHP...
в неумелых руках это приведет к катастрофе.
гыгыгы.
Не... ему нужно ещё и проверку делать.
в __set и __get вполне можно проверки делать, в чем проблема-то?
 

Духовность™

Продвинутый новичок
Ну да, был проект - я ошибся и была катастрофа. Я не родился со знанием PHP.

в __set и __get вполне можно проверки делать, в чем проблема-то?
покажи мне, как ты собрался в __set и __get делать проверки входящих значений, при условии, что входящие значения - это разные типы данных с разными условиями приема.
 

флоппик

promotor fidei
Команда форума
Партнер клуба
Понимаешь, в твоих косяках инструмент не может быть виноват. Виноват только ты.
PHP:
public function __set($value)
{
  if ($value instanceof DataInterface)
  try {
    $this->checkData($value);
  } catch(DataException $e)
  {
    // error processing
  }
}
 

khrisanfov

Новичок
Понимаешь, в твоих косяках инструмент не может быть виноват. Виноват только ты.
PHP:
public function __set($value)
{
  if ($value instanceof DataInterface)
  try {
    $this->checkData($value);
  } catch(DataException $e)
  {
    // error processing
  }
}
Для встроенных типов такой вариант уже не подойдёт.
Пожалуй я избавлюсь от ArrayAccess. Всем спасибо за ответы.
 

флоппик

promotor fidei
Команда форума
Партнер клуба
Я накосячил. Там же $key, $value - надо сначала проверять по $key/
 

atv

Новичок
khrisanfov
Переопредели методы offsetSet offsetGet и т.д. в классе Company. При обращении $company["name"] = "Name"; будет вызываться соответствующий метод, в нём и вызывай проверку checkName("Name").
 

khrisanfov

Новичок
atv
Возможно вы немного не поняли. Я именно так и делаю. Но результат проверки в клиентском коде при таком подходе получить невозможно так как offsetSet всегда возвращает TRUE. Приходится повторно вызывать checkName("Name") в клиентском коде.
 

флоппик

promotor fidei
Команда форума
Партнер клуба
PHP:
public function __set($key, $value)
{
   try 
   {
      $method = 'check' . $key;
      $this->$method($value);
   } catch(Exception $e)
   {
     // error processing
   }
}
Вот примерно так надо.
 

Adelf

Administrator
Команда форума
Вы немного не поняли. Возможно не программили на С++, точнее не юзали переопределение операторов там. Читаем внимательно:
Если я присваиваю данные какому либо полю таким образом $company["name"] = "Name"; то как получить информацию о том что всё прошло успешно (данные корректны и всё присвоилось успешно)? Ведь такая конструкция if($company["name"] = "Name") всегда вернёт TRUE.
В PHP это невозможно. Максимум можно кидать Exception(почти вариант флоппика). Либо работать так, как делал ТС раньше.
 

Духовность™

Продвинутый новичок
Понимаешь, в твоих косяках инструмент не может быть виноват. Виноват только ты.
я не спорю, что я. Но ArrayAccess - не лучший инструмент, вот я о чем говорю. И польза от него в PHP не очевидна и сомнительна.

PHP:
public function __set($value)
{
  if ($value instanceof DataInterface)
  try {
    $this->checkData($value);
  } catch(DataException $e)
  {
    // error processing
  }
}
ОМГ. Что это? Попытка ответит на ответ? Тебе поспорить не о чем? =)

Твой код - какой у него смысл? Он проверяет всего один какой-то тип данных, а дальше что, если у нас в объекте нужно проверять множество значений? Плодить case конструкции для свитча? А если скаляр приходит?
 

Духовность™

Продвинутый новичок
Вот примерно так надо.
Так лучше. Но удобнее для читабельности использовать виртуальные методы:

PHP:
    /**
     * Получение и установка свойств объекта через вызов магического
     * метода вида:
     *
     * $model->(get|set)Propertyname($prop);
     *
     * @see __call
     */
    public function __call($method_name, $argument)
    {
        $args = preg_split('/(?<=\w)(?=[A-Z])/', $method_name);

        $action = array_shift($args);

        $property_name = strtolower(implode('_', $args));

        if (!isset(static::$model_attributes[$property_name]))
        {
        	throw new BadMethodCallException(
                'Вызов неизвестного метода ' . get_class($this) . '::' . $method_name
            );
        }

        switch ($action)
        {
            case 'get':
                return $this->$property_name;

            case 'set':
                $this->$property_name = $argument[0];

                $has_errors = isset($this->validate_errors[$property_name]);

                $explicit_method = '_'.$method_name;

                // Смотрим, имеется ли в классе явно объявленный set-метод (с префиксом "_") для
                // данного свойства и имеются ли ошибки валидации.
                // Если метод явно объявлен, а ошибок валидации нет, то применяем метод
                // для текущего состояния свойства.
                if (method_exists($this, $explicit_method) && !$has_errors)
                {
                   $this->data[$property_name] = $this->$explicit_method($this->$property_name);
                }

                return $this;
        }
    }
 

флоппик

promotor fidei
Команда форума
Партнер клуба
Для удобства и читаемости нужно использовать псевдокод, а не листинг на страницу.
 
Сверху