Комментарии 32
В принципе мне кажется, что выполнять проверку параметров стоит на этапе валидации, можно использовать метод find вместо getElementById (указать primary в классе таблицы), а в общем про создание моделей есть очень хорошая презентация www.slideshare.net/weierophinney/playdoh-modelling-your-objects-176600.
А данное расширение класса мало подойдет для крупного проекта
А данное расширение класса мало подойдет для крупного проекта
0
Допустим проект, где есть «Новости», «Статьи», «Товары», «Фирмы», «Города», «Статичные страницы», не считается большим, но данный подход позволил мне сэкономить прилично времени. Если брать разработку крупной CMS, то я пока не вижу причин, почему расширение не подойдёт для неё.
Ещё плюс данного подхода — не будут плодиться методы с одинаковым функционалом но с разными названиями. Например:
getNewsById(), deleteArticleById, addFirm(), updateCityById()
Ещё плюс данного подхода — не будут плодиться методы с одинаковым функционалом но с разными названиями. Например:
getNewsById(), deleteArticleById, addFirm(), updateCityById()
0
Абсолютно согласен по поводу того, что намного удобнее, когда методы имеют одно и тоже название при условии, что выполняют одинаковые функции. Но на этом можно и остановиться. Основная проблема всех методов, предложенных выше заключается в том, что модель = таблица, а это зачастую не так. Поэтому лучше создать интерфейс для модели, в котором описать все основные методы (при этом я подразумеваю, что одна модель работает сразу с несколькми таблицами), и работать с таблицами через защищённые свойства, например.
Приведу небольшой пример: есть процесс, параметры и связь процесса с параметрами. В этом случае логичнее создать одну модель процесса, которая будет работать с данными трёх таблиц и реализовать в ней методы, описанные в статье. Разница будет в том, что в этих методах будут использоваться зачастую уникальные конструкции (в этом и будет заключаться моделирование процесса).
Приведу небольшой пример: есть процесс, параметры и связь процесса с параметрами. В этом случае логичнее создать одну модель процесса, которая будет работать с данными трёх таблиц и реализовать в ней методы, описанные в статье. Разница будет в том, что в этих методах будут использоваться зачастую уникальные конструкции (в этом и будет заключаться моделирование процесса).
0
В данном случае модель как раз равна таблице, т.к. Zend_Db_Table это реализация паттерна «шлюз таблицы». В остальных случаях предпочтительно использовать модель сохраняемую в базу с помощью маппера, который в свою очередь может использовать шлюзы.
+3
Я это понимаю. Поэтому и говорю, что не имеет особого смысла расширять функциональность шлюза до логики модели.
0
То что описано в статье не является бизнес логикой, и если автору удобно что его шлюзы делают это так, то почему бы и нет? Ведь это и есть задача шлюза — взаимодействовать с таблицой в базе.
+1
Согласен, что это не бизнес логика. И всё же это некоторое ужесточение правил работы с таблицами, которые лучше закладывать в модель, на мой взгляд. Но вы правы в одном — если это делает кому-то работу с данными удобнее, то имеет право на жизнь. Мне же хватает доступных методов для работы с картой базы.
0
Я не заморачивался и поставил Doctrine, правда жрёт памяти прилично.
+1
А я не пользуюсь Db_Table, перенял опыт у Magento, у них гораздо удобнее все реализовано, да и нет явной привязки к 1 таблице.
+1
По-моему, автор просто открыл для себя «наследование», причем, используя его, он все равно продолжает программировать в процедурном стиле.
0
Дело не в «открыл для себя наследование». Я заметил, что есть люди, которые всё ещё не используют преимущества ООП или просто отказываются это делать их не видя в этом смысла. Статья описывает простой пример, без очень универсальных и навороченных методов именно для моделей таблицы базы данных.
0
Я заметил, что есть люди, которые всё ещё не используют преимущества ООП
Например, отдавая данные из слоя бд в виде массива, а не объекта вы тоже не используете эти преимущества. Представьте что вам понадобилось в модель товара добавить метод вычисления НДС исходя из стоимости, в нормальной ситуации это просто решалось наследованием от Zend_Db_Table_Row (с добавлением нужного метода getVat()) и указанием нового класса в поле protected $_rowClass в классе таблицы. Для всего кода, который уже работает с товаром ничего не изменилось бы, просто добавилась бы возможность использования нового метода. С вашим же подходом вы прилепили бы процедурный костыль и вместо использования $table->getItemById($id)->getVat() использовали бы $item = $table->getItemById($id); $table->getVatByPrice($item['price']);
Чувствуете разницу?
-1
Я же не говорю использовать это везде.
Пожалуйста, опишите эти методы здесь
class Model_DbTable_Test extends App_Db_Table
{
protected $_name = 'test';
}
Да и создайте модель, наследуясь от Zend_Db_Table_Row, и решите свою не совсем тривиальную задачу удобным для вас способом. Почему вы пытаетесь применить то, что я написал к тому, для чего это не предназначено?
Пожалуйста, опишите эти методы здесь
class Model_DbTable_Test extends App_Db_Table
{
protected $_name = 'test';
}
Да и создайте модель, наследуясь от Zend_Db_Table_Row, и решите свою не совсем тривиальную задачу удобным для вас способом. Почему вы пытаетесь применить то, что я написал к тому, для чего это не предназначено?
0
Методы работающие с наборами в случае если ничего не найдено должны возвращать пустой набор, но никак не бросать исключение. Если нормальная логика программы построена через try… catch, то это повод задуматься)
+1
А где на ваш взгляд грань между использованием исключений и возвращаемых значений? С наборами всё ясно, но в случае если входные данные указаны неправильно — логичнее использовать исключения, тогда результирующее значение получено всё равно не будет.
0
Логично использовать исключения в исключительных ситуациях.
Если значение не найдено и скрипт должен продолжать работать дальше с учетом этого обстоятельства, то это не исключительная ситуация. Если элемент не найден (например это была статья на которую мы попытались зайти), то это ошибка 404, а значит исключительная ситуация, которую, в случае с зендом, обработает плагин ошибок и перенаправит на ErrorController.
Если значение не найдено и скрипт должен продолжать работать дальше с учетом этого обстоятельства, то это не исключительная ситуация. Если элемент не найден (например это была статья на которую мы попытались зайти), то это ошибка 404, а значит исключительная ситуация, которую, в случае с зендом, обработает плагин ошибок и перенаправит на ErrorController.
0
> throw new Exception(«Необходимо указать id обновляемого элемента»);
Это будет лишнее?
>это ошибка 404, а значит исключительная ситуация
Тогда в этой ошибке можно будет указать только то, что статья не найдена — причина данного события останется скрытой.
Исключения при правильном использовании более информативны.
Это будет лишнее?
>это ошибка 404, а значит исключительная ситуация
Тогда в этой ошибке можно будет указать только то, что статья не найдена — причина данного события останется скрытой.
Исключения при правильном использовании более информативны.
+1
Да дело ведь не в информативности. Исключения используемые для управления логикой приложения подобны goto.
+1
А в чём будет разница между выходом из функции с null вместо результата или выброса исключения в этом месте? Человек который потом будет использовать эту функцию по тексту поймёт что пошло не так, а получив не то значение потратит ещё уйму времени на определение причины.
Согласен, что не стоит делать проверку if(count($result) > 0) { чтобы бросить исключение — здесь ясно, что ничего не найдено, но вот throw new Exception(«Необходимо указать id для выбора элемента»); что-то вроде этого намного правильнее, чем return null;.
Вы согласны?
Согласен, что не стоит делать проверку if(count($result) > 0) { чтобы бросить исключение — здесь ясно, что ничего не найдено, но вот throw new Exception(«Необходимо указать id для выбора элемента»); что-то вроде этого намного правильнее, чем return null;.
Вы согласны?
0
Нет). Тем о чем Вы написали занимается валидация, которая конечно может быть частью модели, но никак не частью метода удаляющего данные. А в данном случае метод должен вернуть 0, он ведь не затронул ни одну строку?
0
Черт я говорил про удаление), а в случае выборки метод опять же должен вернуть пустой набор, если он возвращает наборы, либо null, если он возвращает row.
А уже в контроллере можно делать так if ($row)
В выборках наличие непустого id контролируется, например, через роутинг -> news_id => '\d+'
А уже в контроллере можно делать так if ($row)
В выборках наличие непустого id контролируется, например, через роутинг -> news_id => '\d+'
0
С таким простым случаем я согласен — если условие задано таким, что ничего не возвращает, то метод должен продолжить своё выполнение и вернуть значение. Но если передан пустой идентификатор, то это тоже нарушает правила использования функции.
0
PHP язык с динамической типизацией, и во все функции всех библиотек можно передать пустое значение (не считаем интерфейсы и массивы). Представтье если они все начнут выкидывать исключения по этому поводу.
0
Это и минус. Особенно, когда функция, возвращающая целое внезапно вернула null. Аналогично и при передаче значений. Если метод ожидает целое, а ему приходит пусто, то, на мой взгляд, здесь более правильное поведение языков со статической типизацией и поэтому эксепшен повторяет их логику.
Если пришло пусто, значит где-то шагом или несколькими шагами раньше сформировалось это пустое значение как результат какой-то ошибки. Без использования исключений отловить её будет очень непросто.
Если пришло пусто, значит где-то шагом или несколькими шагами раньше сформировалось это пустое значение как результат какой-то ошибки. Без использования исключений отловить её будет очень непросто.
0
> А в данном случае метод должен вернуть 0, он ведь не затронул ни одну строку?
С этим согласен, но я другое имею в виду. Допустим есть функция с 2мя параметрами: id, typeId, sortKey. Я проверяю, что id > 0, typeId в array(1, 2). Если id < 0, то не будет записи и в принципе ничего страшного. В тоже время передавая typeId не в заданном диапазоне я не получу данных, но это не то, т.к. в этом случае функция в принципе неправильно используется.
С этим согласен, но я другое имею в виду. Допустим есть функция с 2мя параметрами: id, typeId, sortKey. Я проверяю, что id > 0, typeId в array(1, 2). Если id < 0, то не будет записи и в принципе ничего страшного. В тоже время передавая typeId не в заданном диапазоне я не получу данных, но это не то, т.к. в этом случае функция в принципе неправильно используется.
0
Вы предлагаете контролировать typeId внутри метода доступа к базе? А если я добавлю новый typeId? Кто мне напомнит что нужно залезть во все методы где стоит такая валидация и починить это?
Методы поиска занимаются только поиском, и если они что то не вернули то значит вы им не то передали. Если ошибка в том что метод не рабочий — правьте тесты.
Если мы говорим про вставку данных, то целостность базы должна поддерживаться на уровне базы и единственный способ сделать это, использовать внешние ключи. Без них любая база превратиться в помойку, даже при самых страшных проверках.
Методы поиска занимаются только поиском, и если они что то не вернули то значит вы им не то передали. Если ошибка в том что метод не рабочий — правьте тесты.
Если мы говорим про вставку данных, то целостность базы должна поддерживаться на уровне базы и единственный способ сделать это, использовать внешние ключи. Без них любая база превратиться в помойку, даже при самых страшных проверках.
0
Речь о поиске. Имеется в виду, что typeId в array(1,...,5), но тот метод работает только с 2мя из них (такая у него специфика, такое бывает).
Но как быть если данный метод используется в 10ти местах стразу и везде на входные данные наложены одни теже ограничения? Писать отдельный метод валидации для этого поиска тоже не выглядит очень логично.
Но как быть если данный метод используется в 10ти местах стразу и везде на входные данные наложены одни теже ограничения? Писать отдельный метод валидации для этого поиска тоже не выглядит очень логично.
0
Конечно нужно пропускать через валидаторы данные, которые будут отдаваться методу, но если делать простые проверки в самом методах класса — это сделает класс более независимым и даст возможность быстро понять, где была ошибка, особенно программистам с небольшим опытом.
0
А если часть скрипта не должна продолжать работу, то это тоже исключительная ситуация.
Простой пример — если запись в таблице не удалось добавить, или обновить, то и файл, который к ней относится будет удалён из временной директории.
Имхо проще эту логику описать в try{} как некое подобие «транзакции».
Простой пример — если запись в таблице не удалось добавить, или обновить, то и файл, который к ней относится будет удалён из временной директории.
Имхо проще эту логику описать в try{} как некое подобие «транзакции».
-1
Очень странное у Вас представление о транзакциях.
Все Ваши примеры решаются тем инструментом который для этого предназначен — это условные операторы.
Выдержка из книги «Совершенный код»:
8 ) Кодирование путём исключения
Этот антипаттерн представляет собой реализацию нормальной логики работы программы с помощью механизма исключений. Например, рекурсивный поиск по дереву может в качестве результата поиска кидать исключение. Такая реализация на первый взгляд может выглядеть заманчиво и удобно, но не более чем на первый взгляд.
Исключения должны использоваться с одной единственной целью — проинформировать систему об ошибке. Использование исключений как инструмента для управления логикой программы вносит неоднозначность. Глядя на конструкцию try-throw-catch / try-raise-except, программисту совершенно не очевидно, для чего именно эта конструкция используется. Кроме того, управление логикой через исключения и система оповещения об ошибках, построенная на исключениях, могут попросту мешать друг другу, поскольку они построены на одном механизме.
Для обработки ошибок используйте только исключения, а исключения — только для обработки ошибок.
Все Ваши примеры решаются тем инструментом который для этого предназначен — это условные операторы.
Выдержка из книги «Совершенный код»:
8 ) Кодирование путём исключения
Этот антипаттерн представляет собой реализацию нормальной логики работы программы с помощью механизма исключений. Например, рекурсивный поиск по дереву может в качестве результата поиска кидать исключение. Такая реализация на первый взгляд может выглядеть заманчиво и удобно, но не более чем на первый взгляд.
Исключения должны использоваться с одной единственной целью — проинформировать систему об ошибке. Использование исключений как инструмента для управления логикой программы вносит неоднозначность. Глядя на конструкцию try-throw-catch / try-raise-except, программисту совершенно не очевидно, для чего именно эта конструкция используется. Кроме того, управление логикой через исключения и система оповещения об ошибках, построенная на исключениях, могут попросту мешать друг другу, поскольку они построены на одном механизме.
Для обработки ошибок используйте только исключения, а исключения — только для обработки ошибок.
+1
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Ускоряем разработку ч.1 (Расиширяем Zend_Db_Table)