Comments 87
Use ORM, Luke.
+11
Иногда оно того не стоит
+3
Кстати я эту коллекцию использую в паре с ActiveRecord отличнейшая штука получается.
0
github.com/limb-php-framework/limb/tree/master/active_record/src
для общего развития посмотрите, как тут коллекции реализованы.
для общего развития посмотрите, как тут коллекции реализованы.
0
Не поверите, это один в один то что я сделал.
Для общего развития посмотрите как работает ArrayObject, и почему я использовал именно его. Да и вообще на SPL посмотрите чтоб глупостей не говорить
Для общего развития посмотрите как работает ArrayObject, и почему я использовал именно его. Да и вообще на SPL посмотрите чтоб глупостей не говорить
0
С чего это вы взяли, что я не знаю, как работает ArrayObject? :) Я вам дал ссылку на готовое, давно существующее решение, которое, возможно, избавило бы вас от велосипедостроения.
0
<?php echo $user->id; ?>
в тегах бардак.
в тегах бардак.
-2
парсер гад.
0
$stmt->fetch(PDO::FETCH_CLASS|PDO::FETCH_PROPS_LATE, 'ClassName');
+7
Warning: PDOStatement::fetch() expects parameter 2 to be long, string given
Можно поподробней?
Можно поподробней?
0
UFO just landed and posted this here
Ладно, на самом деле не важно, Вы скажите это избавит от того что я описал:
1. Поля отдаются только через геттер
2. Конструктор вызывается только после отдачи всех полей
1. Поля отдаются только через геттер
2. Конструктор вызывается только после отдачи всех полей
0
UFO just landed and posted this here
> 2. Конструктор вызывается только после отдачи всех полей
Это и изменяется.
Вообще, Вызывать конструктор после установки значения свойств — это просто ппц, и любого нормального программиста это должно было натолкнуть на поиски как изменить данное поведение. Найти инфу про PDO::FETCH_PROPS_LATE — две минуты поисков по мануалу.
> 1. Поля отдаются только через геттер
Поля отдаются так, как хочется. Но ниже вы написали более подробно «Чтоб как-то контролировать эти анные без геттера и сеттера не обойтись» — вот на это можно подробнее и ответить. Классы, представляющие из себя строки в базе должны быть простыми максимально. Запихивать логику в конструктор таких классов — говнокод. Поэтому, да, нормальным будет создавать геттеры и сеттеры.
Это и изменяется.
Вообще, Вызывать конструктор после установки значения свойств — это просто ппц, и любого нормального программиста это должно было натолкнуть на поиски как изменить данное поведение. Найти инфу про PDO::FETCH_PROPS_LATE — две минуты поисков по мануалу.
> 1. Поля отдаются только через геттер
Поля отдаются так, как хочется. Но ниже вы написали более подробно «Чтоб как-то контролировать эти анные без геттера и сеттера не обойтись» — вот на это можно подробнее и ответить. Классы, представляющие из себя строки в базе должны быть простыми максимально. Запихивать логику в конструктор таких классов — говнокод. Поэтому, да, нормальным будет создавать геттеры и сеттеры.
0
Ну как вариант можно было всего лишь getAll() переписать так:
static public function getAll(){
$res = $this->db->fetchAll();
return array_map(function ($x){return (object)$x;},$res);
}
+2
Тогда уж
return array_map(function ($x){return new User($x);},$res);
+1
Я специально хочу избавиться от массива, у него, в отличии от обьтекта, нет свойств и методов.
0
тогда
return new ArrayObject(array_map(function ($x){return new User($x);},$res));
:)+1
Внутри массив конечно мелькает, и даже два, но их обход реализован на C, а не на PHP
+1
А я не то же самое по сути сделал?
0
Не совсем. У вас объект User создаётся при каждом обращении к одному индексу, у нас возвращаются ссылки на один и тот же объект
Что напишет наша getAll, а что ваша? Какое поведение вы считаете логичным?
$users = Users::getAll();
if ($users[0] === $users[0]) {
echo 'Trivial';
}
else {
echo 'WTF?!'
}
Что напишет наша getAll, а что ваша? Какое поведение вы считаете логичным?
0
Так лучше?
habrahabr.ru/blogs/php/125665/#comment_4140504
public function offsetGet( $index )
{
$this->$_cashe[$index] = new User( parent::offsetGet[$index] );
return &$this->$_cashe[$index];
}
habrahabr.ru/blogs/php/125665/#comment_4140504
0
Бред какой-то написали.
+2
Тогда уж так:
public function offsetGet( $index )
{
if (!isset($this->$_cache[$index])) {
$this->$_cache[$index] = new User( parent::offsetGet[$index] );
}
return &$this->$_cache[$index];
}
+2
Нет :) Результат тот же самый, только памяти больше жрёт.
Тогда уж так
Тогда уж так
public function offsetGet( $index )
{
if (!isset($this->_cache[$index]) {
$this->_cashe[$index] = new User( parent::offsetGet[$index] );
}
return $this->_cashe[$index];
}
+2
Либо PDO::FETCH_CLASS, либо ORM типа Doctrine полностью решит ваши проблемы. И без всякого велосипедостроительства.
0
Как бы при чем тут PDO, если в php можно выбрать объект произвольного классам через любое api работы с базами данных.
www.php.net/manual/en/function.mysql-fetch-object.php
www.php.net/manual/en/function.mysql-fetch-object.php
0
Вы наверно совершенно не читали что я писал.
+1
> Первая мысль — PDO! Да у него ведь есть волшебный метод fetchObj.
Да ведь не только у него!
Да ведь не только у него!
0
Ничего что функции mysql_* будут убирать?
0
Ничего, потому что «объект произвольного класса можно выбрать через любое api работы с базами данных».
0
Что плохого что я хочу управлять тем как обьект получает данные?
0
Почему вы вдруг решили задать мне этот вопрос, никак не относящийся к нашему диалогу?
0
Смотрите, у вас в статье есть фраза:
> Первая мысль — PDO! Да у него ведь есть волшебный метод fetchObj.
Она не верна. Правильная фраза:
> Первая мысль — любой api доступа к данным! Да у них у всех есть волшебный метод fetchObj.
Все. При чем тут управление получением данных?
> Первая мысль — PDO! Да у него ведь есть волшебный метод fetchObj.
Она не верна. Правильная фраза:
> Первая мысль — любой api доступа к данным! Да у них у всех есть волшебный метод fetchObj.
Все. При чем тут управление получением данных?
0
Как интересный прием — да, имеет место, но по производительности все это печально выглядит. Все равно храниться будет ассоциативный массив, а конструкторы будут вызываться при обращении к свойствам, при чем, при повторном обращении — опять будут вызываться, а объекты будут дохнуть. Подумайте, что Вам важнее, просто заменить <?php echo $user['login']; ?> на <?php echo $user->login; ?> из-за нежной привязанности к ООП или в 2-3 выиграть в производительности кода? Попробуйте все приведенные в статье варианты прогнать 100000 раз и засеките microtime().
Гораздо лучше вариант с PDO или mysql_fetch_object, как бы костылей не видно при этом, но поверьте, PHP не сделан от природы объектным, и хранение свойств объекта в памяти у него все одно сделано через ту же структуру, что и ассоциативных массивов. Тут лучше использовать тот вараинт, который работает быстрее и позволяет написать код короче.
P.S. Меня вот, например (после Delphi и C#) раздражала сперва эта стрелочка -> в PHP и коробило страшно от нее (дайте мою любимую точку «Object.Property»), но это все личные предпочтения, от них можно и нужно абстрагироваться.
Гораздо лучше вариант с PDO или mysql_fetch_object, как бы костылей не видно при этом, но поверьте, PHP не сделан от природы объектным, и хранение свойств объекта в памяти у него все одно сделано через ту же структуру, что и ассоциативных массивов. Тут лучше использовать тот вараинт, который работает быстрее и позволяет написать код короче.
P.S. Меня вот, например (после Delphi и C#) раздражала сперва эта стрелочка -> в PHP и коробило страшно от нее (дайте мою любимую точку «Object.Property»), но это все личные предпочтения, от них можно и нужно абстрагироваться.
+3
Нечаянно комментарий не к статье привязал, сори. Это все Автору
+1
Зачем дохнуть? Ссылки никто не отменял.
0
Оїект живет только одну итерацию форича. Разве этот массив вообще создается для одноразового использования? Если для многоразового, то лучше массив объектов, а если для одноразового, то лучше ассоциативный.
0
Сколько он живет — зависит от того где Вы его будете применять. Это лишь пример. Зачем вообще использовать фреймверки, ведь скрипт завершается при показе результата. Есть некие рамки удобства, и как бы не хочется писать на голом пхп все что можно сделать немного удобней, хоть и будет некий ущерб скорости. Это все не так сильно тормозит как кажется. Массив обьетктов от обьекта обтектов отличается на столько несущественно, так как основные рессурсы будут поедать именно содержимое, а не контейнер.
0
Если эстетическое удовольствие от вида -> вместо [] повышает у Вас производительность труда, то я согласен с таким решением )))
0
Вообще ArrayUtils::filter($MyArray), но в большинстве случаев это задача «where» в SQL-запросе, кроме тех случаев, когда чтение не из РСУБД.
0
И по каким полям Вы будете фильтровать? Там обьекты. Коллекция прекрасно знает что в ней находится и может просто орудовать данными внутри себя, это оболочка лишь для удобства. ArrayObject нативный класс, на скорость это сильно не повлияет
0
Коллекция ничего не знает о бизнес-логике, Вы все указываете:
$collection->filter( array( 'id' => '>5' ) );
и в чем разница:
ArrayUtils::filter($MyArray, array( 'id' => '>5' ));
или
ArrayUtils::filter($MyArray, 'id', '>5');
$collection->filter( array( 'id' => '>5' ) );
и в чем разница:
ArrayUtils::filter($MyArray, array( 'id' => '>5' ));
или
ArrayUtils::filter($MyArray, 'id', '>5');
0
Разницы нет совершенно, разве что другой обьект работает с моим. Не Вы немного выше говорили что обьекты — ущерб производительности и даете мне обьект?
0
Я всетаки ошибся, не через любое, но через большинство популярных api можно. Нельзя, например в mssql.
+1
Никогда не понимал зачем делать объект вместо массива, если отличаться будет только синтаксис:
$user->id вместо $user['id']
Ради эстетики?
Мне массивы нравятся, ассоциативные особенно. Использовать синтаксис $user['id'] удобнее, потому что я могу сделать $user[]. У объектов $user->$field_name выглядит странно, а использовать выражение вместо $field_name вообще нельзя.
Еще часто объекты используют для уникальности имен переменных, делая их свойствами объекта, прячут в класс. Особенно этим грешат всяческие фреймворки. Но на самом деле это задача namespace`ов.
По-моему, основное назначение и свойство объектов — инкапсуляция. (Да, наследование тоже важно и удобно, но не так как инкапсуляция. А полиморфизм в PHP я вообще не встречал :))
Если у вас в объекте нет методов для работы с его данными (простейшие геттеры, сеттеры не в счет), то вам нужен либо namaspace, либо ассоциативный массив.
$user->id вместо $user['id']
Ради эстетики?
Мне массивы нравятся, ассоциативные особенно. Использовать синтаксис $user['id'] удобнее, потому что я могу сделать $user[]. У объектов $user->$field_name выглядит странно, а использовать выражение вместо $field_name вообще нельзя.
Еще часто объекты используют для уникальности имен переменных, делая их свойствами объекта, прячут в класс. Особенно этим грешат всяческие фреймворки. Но на самом деле это задача namespace`ов.
По-моему, основное назначение и свойство объектов — инкапсуляция. (Да, наследование тоже важно и удобно, но не так как инкапсуляция. А полиморфизм в PHP я вообще не встречал :))
Если у вас в объекте нет методов для работы с его данными (простейшие геттеры, сеттеры не в счет), то вам нужен либо namaspace, либо ассоциативный массив.
+4
> а использовать выражение вместо $field_name вообще нельзя.
Богат синтаксисом php:
Богат синтаксисом php:
for ($i =0; $i < 3; $i++) {
echo $user->{'field_number'.$i}
}
+4
Например для:
$collection->filter( array( 'id' => '>5' ) )
или
$collection->escape();
или
$collection->append()
итд, все заканчивается только Вашей фантазией. Так как это обьект, а не массив, то и добавить методов не составит труда.
Мне абсолютно не важен синтаксис, мне не нравятся массивы не потому что там скобочки и нравятся обьекты потому что стрелочки, а потому что работа с массивами сложней чем с обьектами. Нужно изменить работу обьекта? Проще простого, наследование + переопределение = новое действие.
полиморфизм Вы встречаете ежедневно при работе с PDO, с интерфейсами, с фабриками. На то он и полиморфизм чтоб его не замечать явно.
$collection->filter( array( 'id' => '>5' ) )
или
$collection->escape();
или
$collection->append()
итд, все заканчивается только Вашей фантазией. Так как это обьект, а не массив, то и добавить методов не составит труда.
Мне абсолютно не важен синтаксис, мне не нравятся массивы не потому что там скобочки и нравятся обьекты потому что стрелочки, а потому что работа с массивами сложней чем с обьектами. Нужно изменить работу обьекта? Проще простого, наследование + переопределение = новое действие.
полиморфизм Вы встречаете ежедневно при работе с PDO, с интерфейсами, с фабриками. На то он и полиморфизм чтоб его не замечать явно.
0
А полиморфизм в PHP я вообще не встречал :))
Пример полиморфизма в PHP
class A {
public function printSmth() {
echo 'foo';
}
}
class B extends A {
public function printSmth() {
echo 'baz';
}
}
Или вы перегрузку имели в виду?
0
Никогда не понимал зачем делать объект вместо массива, если отличаться будет только синтаксис:
$user->id вместо $user['id']
Например чтоб можно было вместо
$user['firstName'] . ' ' . $user['lastName']
написать $user->getFullName();
Если такое только в одном месте, то да, для эстетики, а если в двух, то уже DRY;А вообще вы конечно правы — если у объекта нет поведения, а только данные, то это какой-то неполноценный объект. Но, с другой стороны, если у нас 10 схожих по назначению сущностей, но у половины есть поведение, а у половины нет, то следуя принципу «не умножай сущности сверх необходимого» не следует вторую половину делать ассоциативным массивом, даже если полиморфизм не используется:
echo $man->name;
echo $cat->name;
по-моему поддерживаемее, чемecho $man->name;
echo $cat['name'];
+1
Это дело вкуса, но я вот не люблю смешивать в объекте служебные функции, шаблоны вывода, данные, бизнес-логику. Например $user->load('username') или $user->restorePassword() или $user->getFullName я бы реализовывал примерно так: $user = db::load('user','username') и security::restorePassword($user) и template::($user, 'fullName'). Но это дело вкуса.
0
А чем бизнес-логика без данных будет оперировать? :)
Насчёт примеров:
— $user->load('username') я как-то даже не понял, что должна делать, то ли вернуть новый экземпляр, то ли свои свойства на новые поменять. User::load('username') ещё куда ни шло, но тоже не люблю с некоторых пор (хотя большой шаг вперёд по сравнению с mysql_fetch_array() ), предпочитаю что-то вроде $user = UserRepository->getOneByUsername('username').
— security::restorePassword($user) — тут согласен, наверное, как-то не так выглядит, не пойму
— template::($user, 'fullName') — вот тут спорно, если полное имя нужно только в выводе, то да, наверное. Но если бизнес-логика на него завязана, то рендерить в доменной модели шаблоны как-то неправильно по-моему
Насчёт примеров:
— $user->load('username') я как-то даже не понял, что должна делать, то ли вернуть новый экземпляр, то ли свои свойства на новые поменять. User::load('username') ещё куда ни шло, но тоже не люблю с некоторых пор (хотя большой шаг вперёд по сравнению с mysql_fetch_array() ), предпочитаю что-то вроде $user = UserRepository->getOneByUsername('username').
— security::restorePassword($user) — тут согласен, наверное, как-то не так выглядит, не пойму
— template::($user, 'fullName') — вот тут спорно, если полное имя нужно только в выводе, то да, наверное. Но если бизнес-логика на него завязана, то рендерить в доменной модели шаблоны как-то неправильно по-моему
0
Имею в виду, что load/save — методы загрузки и сохранения, и к предметной области не относятся, это лучше выделить в репозиторий, как Вы и сказали. Всякие методы типа restorePassword, signIn, checkPermission — это методы не объекта user, а системы безопасности, потом есть задачи шаблонизации и getFullName я отношу к ним. А вот если нужно сделать склонение фамилии, то это лучше реализовать в библиотеке, можно с статическом классе NameUtils. Что касается бизнес-логики, отвечающей за поведение именно этого объекта, это единственное, что в нем я оставляю. Например, методы buyProduct или applyToPosition.
0
Глянул в код, понял почему не так выглядит. У меня два метода — security::generatePasswordResetToken($user) и security::resetPassword($user, $token) :)
А getFullname я отношу всё же к вычисляемым свойствам, как, например, getTotal в объекте, представляющем строку заказа, а не к представлению. А вот какое представление есть у меня почти в каждом объекте модели предметной области, так это __toString()
А getFullname я отношу всё же к вычисляемым свойствам, как, например, getTotal в объекте, представляющем строку заказа, а не к представлению. А вот какое представление есть у меня почти в каждом объекте модели предметной области, так это __toString()
0
Но не даром оно __*, это же по сути метод абстрактного класса (такого себе BusinessObject) и достаточно служебный.
0
Но вот если это действительно метод пользователя, то он должун быть у пользователя: $user->buy($product);
0
Только мне одному непонятно, зачем для языка, использующегося в основном для веб, нужны лишние слои абстракции? И лишние затраты памяти под это дело… Все хорошо в меру =).
+3
Класс нативный, работать будет быстро.
-2
Чтобы уменьшить затраты времени разработчика, не?
0
Не поверите, хороший разработчик стоит ~200$ в месяц а хороший сервак, которому плевать на любые мои абстракции ~200$ в месяц… Как думаете что более рационально, использовать удобный код с абстракциями или мега оптимизированный который неизвестно как просто будет поддердивать?
0
UFO just landed and posted this here
Почему-то вспомнилась вторая стадия программизма:
«_Я разработчик. Да, именно так, я разработчик программного обеспечения, а не программист. Мое задание – разработать продукт, который будет стабильно работать и состоять из правильного кода. Код, который я пишу, должен работать сначала правильно, а потом уже быстро. Код должен быть структурированным и откомментированным – возможно его будут поддерживать другие разработчики. ООП – мой главный инструмент, я умею анализировать предметную область и выделять в ней иерархии классов. Все, что можно описать шаблонами или дженериками описывается шаблонами или дженериками. Я применяю декларативное прораммирование везде, где это возможно, ведь этот инструмент делает код максимально читабельным и понятным. Я использую кодогенерацию ведь это экономит мое время на написание кода. Я использую только новые технологии. Я провожу много времени в спорах с коллегами, какой паттерн или технология лучше подходят для решения поставленной задачи и правильно ли использовать здесь тот или иной подход..._»
Это описание. Данные анамнеза легко найдете сами habrahabr.ru/blogs/development/91665/
«_Я разработчик. Да, именно так, я разработчик программного обеспечения, а не программист. Мое задание – разработать продукт, который будет стабильно работать и состоять из правильного кода. Код, который я пишу, должен работать сначала правильно, а потом уже быстро. Код должен быть структурированным и откомментированным – возможно его будут поддерживать другие разработчики. ООП – мой главный инструмент, я умею анализировать предметную область и выделять в ней иерархии классов. Все, что можно описать шаблонами или дженериками описывается шаблонами или дженериками. Я применяю декларативное прораммирование везде, где это возможно, ведь этот инструмент делает код максимально читабельным и понятным. Я использую кодогенерацию ведь это экономит мое время на написание кода. Я использую только новые технологии. Я провожу много времени в спорах с коллегами, какой паттерн или технология лучше подходят для решения поставленной задачи и правильно ли использовать здесь тот или иной подход..._»
Это описание. Данные анамнеза легко найдете сами habrahabr.ru/blogs/development/91665/
+2
Учитывая что там всего три стадии, это выглядит больше чем комплимент =)
0
Вот и «больним» так кажется :) пока просветление не наступит
0
Sign up to leave a comment.
Массивы или Объекты? Хочу коллекции в пхп!