Этот урок набрал набрал достаточно большое количество
комментариев и дальнейшее его комментирование отключено.
Если вы хотели убедиться в правильности выполнения ДЗ или у вас возник вопрос по уроку,
посмотрите ранее добавленные комментарии, кликнув по кнопке ниже. Скорее всего вы найдете там то, что искали.
Если это не помогло - задайте вопрос в чате в телеграме - https://t.me/php_zone
Уважаемый автор, хоть бы исходники к урокам поставили ато код откуда то появляется и куда то исчезает, новичкам как я не понять. Куда делся код в конструкторе куда делся дланные передаваемые в вид у меня сыпится миллион ошибок в лгог пожалуйста покажи исходники к этому уроку.
С сожалением должен признать что уроки превратились в ctrl C => ctrl V. Очень много материала вываливается за один урок, и я уже перестал что-то понимать сам. Да и домашки опять нет.
Если что-то неудачно скопировал - ошибку найти практически не возможно с нашим уровнем :((
Попробуйте не бежать вперед как можно быстрее, а разбираться более глубоко в теме. Ученик, дошедший до данного урока уже сам должен разбираться в ошибках. Учитесь дебажить. Опыт других учеников показывает, что с уроками всё в порядке.
Переставайте делать ctrl+c=>ctrl+v. Пишите код от руки, так будете лучше и понимать что вы пишете и запоминать построение кода. Мне очень помогло еще на курсе php для начинающих. При этом я еще и конспект от руки веду, чтобы когда писал дополнительно в голове проговаривал и понимал/запоминал. :)
Материала действительно много, я бы советовал всем оставлять везде в коде комментарии.
Потом просто создадите свой проект по этому шаблону и все станет на свои места.
Тема мне кажется тут ошибка в коде :
в этой строке <p>Автор: <?= $article->getAuthor()->getNickname() ?></p>
Должно же быть getAuthorId() вместо getAuthor() ?????
<?php include DIR . '/../header.php'; ?>
<h1><?= $article->getName() ?></h1>
<p><?= $article->getText() ?></p>
<p>Автор: <?= $article->getAuthor()->getNickname() ?></p>
<?php include DIR . '/../footer.php'; ?>
Вроде как в коде понимаю, вижу что происходит, берет отсюда, идет там, потом обрабатываем и так далее, ошибки если что вроде разбираюсь где найти и что перезаписать, но, вот чтобы я сам такое сделал, чтобы взять и сказать: давайте так, нам нужно страничку, потом контроллер для нее чтобы работать с БД, потом наследоваться от ActiveRecord и многое такое, я по прежнему не могу сам писать((
Fatal error:
Uncaught TypeError:
Return value of MyProject\Models\ActiveRecordEntity::getById() must be an instance of MyProject\Models\ActiveRecordEntity or null, array returned in C:\OSPanel\domains\newproj.loc\src\MyProject\Models\ActiveRecordEntity.php:54 Stack trace: #0 C:\OSPanel\domains\newproj.loc\src\MyProject\Controllers\ArticlesController.php(20): MyProject\Models\ActiveRecordEntity::getById(2) #1 C:\OSPanel\domains\newproj.loc\www\index.php(30): MyProject\Controllers\ArticlesController->view(2) #2 {main} thrown in C:\OSPanel\domains\newproj.loc\src\MyProject\Models\ActiveRecordEntity.php on line 54
ivashkevich, спасибо за урок!
Всё доступно и понятно.
Подскажите, как расширить этот класс?
Например:
$article = Article::getById($articleId);
Как грамотно реализовать добавление дополнительных условий?
Например, вместо getById учитывать несколько условий: WHERE x = 'y' AND a = 'b' ORDER BY k DESC LIMIT n;
public function __set(string $name, $value)
{
$camelCaseName = $this->underscoreToCamelCase($name);
$this->$camelCaseName = $value;
}
private function underscoreToCamelCase(string $source): string
{
return lcfirst(str_replace('_', '', ucwords($source, '_')));
}
Эти два метода не работают в паттерне, из-за этого не могу вывести никнейм, в чем может быть проблема?Когда методы возвращаю в Article.php всё работает
А как можно реализовать findAllCount() по аналогии с findAll(), только запросом COUNT(*) ?
Собственно, получить количество записей таблицы, в рамках работы с ActiveRecord.
Ну, начать стоит с того, почему вы выбрали тип static::class в качестве результата запроса? Вам ведь нужно только число, для чего его в объект запихивать? Пробовали погуглить по этой теме? Я вот погуглил и нашел ответ на второй позиции поисковика - тут.
Я до того, как прочитал готовое решение в уроке, пробовал сам делать и сделал сразу в геттере получение и никнейма.
public function getAuthor (): string
{
return User::getById($this->authorId)->getNickname();
}
а в шаблоне уже выводил
<p>Автор:<?= $article->getAuthor()?></p>
Посему у меня возник вопрос : А есть ли разница?
2. Есть ли случаи, когда НУЖНО применять не позднее, а именно раннее связывание? Если да, то можно какие-то примеры?
3. В примере всего две таблицы в БД и данные в них перемежаются, поэтому использован всего один, общий шаблон(и для статей и для юзеров) между БД и "основной программой", хотя в итоге по факту наследования этот шаблон делится уже на два отдельных. А если бы свойства/методы не перемежались у статей и узеров, это были бы отдельные шаблоны? Т.е. фактически для связи основной программы с отдельной таблицей в БД - отдельный шаблон? Префикс ActiveRecord - обязательный в названии класса-шаблона?
Тогда название метода некорректно. Он возвращает не автора, а его никнейм.
В любом случае, когда не нужно позднее. Пример: когда вам нужно обращаться к имени класса, в котором код был НЕ ВЫЗВАН, а НАПИСАН, будет использоваться self, а не static.
CRUD-операции для всех сущностей почти всегда будут одинаковыми, поэтому код для работы с БД не требует каких-то особых изменений, в зависимости от конкретной сущности. ActiveRecord даёт нам явно понять какой именно паттерн используется для реализации ORM. Так просто понятнее и является правилом хорошего тона.
А не является ли тут нарушением MVC то, что шаблон по сути обращается к модели за автором? По идее это же работа контроллера. Вьюха не должна знать откуда брать данные, ее задача же просто отобразить уже готовые из контроллера.
Вы сказали получать свойство модели в шаблоне допустимо. А вообще передаваемые переменные в шаблоны надо в контроллере создавать, да?
Просто я подумал что если вы в шаблоне получаете свойства модели, то на то есть причина.
Спасибо за урок, очень интересный!
Хотел попросить, если имеется такая возможность, скинуть исходники предыдущего урока, чтобы можно было ещё раз построчно пробежаться по каждому изменению. До этого урока всё понимал быстро, а здесь почему-то мозг взрывается)
Поясните как быть если запрос в СУБД затрагивает несколько таблиц? То есть тогда каким образом указывать класс объектом которого орм должна дать ответ. И как сам тогда скл запрос вид должен иметь?
Хорошо, но как быть если у меня карточка хранится в отд таблице её поля, сами данные о человеке фио и комментарий в др таблице и есть ещё третья таблица список три текст поля для карточки специальные.
Кпрточка пользователя хранится вв иде полей а одной таблице потому что в этом проекте фамилии, имён, отчества могут быть более одного. Потом год, место рождения, наличие фотографий и примечания.
Примечания в отд таблице у меня т. К. Там текст и также может храниться текст вместоварчара как у оси полей карточки.
Таким образом у меня должен быть метод в модели состоящий из нескольких орм актив запросов и потом формироваться, собираться воедино или как!? Просто что описано в статье здорово все, но мне не понятно как получить из бд подобным образом сущность если она составная из нескольких таблиц?! Спасибо!
Ну к примеру, есть у тебя Пользователь и есть Социальные_Сети_Пользователя. Тогда в том месте, где нужно получить его социальные сети нужно сделать так:
Привет. Спасибо за ответ. Тогда получается согласно твоему ответу проецируя на мою проблему/вопрос получается следующее. Необходмо для получения составной сущности иметь в определенных моделях отражающих логику подсущностей методы возвращаемые необходимые значения. Эти методы уже должны быть основаны как приведеный тобой метод getByColumn с максимальной универсальностью/Унификацией?!
ТОгда в этом методе луше чтобы было return $entities ? $entities : null;
т.к. могут понадобиьтся все значения, которое может быть не одним единственным.
Если метод начинается с get, то подразумевается что он для получения одной сущности. Для получения нескольких лучше назвать метод find.
И тогда просто return $entities;
Потому что если ожидается массив сущностей, то если не нашлось ни одной, правильнее будет вернуть пустой массив, а не null (null подходит чтобы показать что одной сущности нет).
Пришлось попотеть я в файле Db.php написал require_once вместо require. И при запросе автора, файл подключения оказывался пустым. И главное ошибка такая специфическая, сообщала мне, что подключение к БД осуществляется без пароля, хотя в файле с настройками всё прописано) С помощью дебага только нашел)
Добрый день! Большое спасибо за урок!
Должен признать, действительно тяжеловато идет это ученье.
Возник вопрос по следующему предложению:
«Обратите внимание, свойства теперь становятся не private, а protected, чтобы к ним можно было достучаться из класса-родителя», - мы вроде бы должны стучаться из класса-наследника в класс-родителя…?
Артем, отличный урок, спасибо! Вопрос такой. Если одно из полей в таблице массив. Свойство класса, соответственно, тоже массив (ORM). Количество элементов в этом массиве всегда разное, от 3 до 10. Как хранить такой массив в БД? Одно из решений - сериализация и хранение под типом BLOB. Рабочий вариант или есть более современные подходы?
Ох опять это моё чувство дурацкое "не понимаю", столько мыслей в голове, вот даже коммент не могу нормально написать чтоб донести суть проблемы. Да проект работает, код пишу сам, читаю урок, пытаюсь понять откуда что приходит, куда передаётся и вроде бы понимаю, но по сути списываю с доски за учителем, единственное что радует, с ошибками возникающими в коде пока справляюсь сам.
И вот это очень беспокоит что без подглядываний не могу писать.
Артём плиз поддержи как более опытный в этом деле.
Ооочень насыщенный. Как бы все переварить.
Да, тема не самая простая. Изучай в несколько подходов.
Уважаемый автор, хоть бы исходники к урокам поставили ато код откуда то появляется и куда то исчезает, новичкам как я не понять. Куда делся код в конструкторе куда делся дланные передаваемые в вид у меня сыпится миллион ошибок в лгог пожалуйста покажи исходники к этому уроку.
Привет. Репа тут - https://gitlab.com/ivashkevitch/myproject
С сожалением должен признать что уроки превратились в ctrl C => ctrl V. Очень много материала вываливается за один урок, и я уже перестал что-то понимать сам. Да и домашки опять нет.
Если что-то неудачно скопировал - ошибку найти практически не возможно с нашим уровнем :((
Попробуйте не бежать вперед как можно быстрее, а разбираться более глубоко в теме. Ученик, дошедший до данного урока уже сам должен разбираться в ошибках. Учитесь дебажить. Опыт других учеников показывает, что с уроками всё в порядке.
Переставайте делать ctrl+c=>ctrl+v. Пишите код от руки, так будете лучше и понимать что вы пишете и запоминать построение кода. Мне очень помогло еще на курсе php для начинающих. При этом я еще и конспект от руки веду, чтобы когда писал дополнительно в голове проговаривал и понимал/запоминал. :)
Материала действительно много, я бы советовал всем оставлять везде в коде комментарии.
Потом просто создадите свой проект по этому шаблону и все станет на свои места.
Немного непонятки, почему при вардампе вот этого $article = Article::getById($articleId);
Он говорит что это обьект
А что там должно быть?
отличный урок!!
Тема мне кажется тут ошибка в коде :
в этой строке <p>Автор: <?= $article->getAuthor()->getNickname() ?></p>
Должно же быть getAuthorId() вместо getAuthor() ?????
<?php include DIR . '/../header.php'; ?>
<h1><?= $article->getName() ?></h1>
<p><?= $article->getText() ?></p>
<p>Автор: <?= $article->getAuthor()->getNickname() ?></p>
<?php include DIR . '/../footer.php'; ?>
Нет, всё правильно. Посмотри внимательно на метод getAuthor.
это я у себя тут что-то начудил, нашел ошибку)
Вроде как в коде понимаю, вижу что происходит, берет отсюда, идет там, потом обрабатываем и так далее, ошибки если что вроде разбираюсь где найти и что перезаписать, но, вот чтобы я сам такое сделал, чтобы взять и сказать: давайте так, нам нужно страничку, потом контроллер для нее чтобы работать с БД, потом наследоваться от ActiveRecord и многое такое, я по прежнему не могу сам писать((
Сможешь через несколько уроков, не бойся
Да дружище вот и у меня сейчас такое чувство. Хочу спросить, как сейчас успехи?
Привет, сейчас работаю php разработчиком. Курс сдесь хороший, есть чему поучится.
Вот это жееесть! Вроде осилил, но придется еще не раз это переосмыслить.
Изи, изи)
Предыдущие вопросы сами собой отпали, но чтоб все это переварить, ладно справимся)))
P.S.
Прям кайфанул от урока)))
Еее!
Что-то я пропустил
['articles' => $articles] вот этот момент зачем нам нужен?
Переменную в шаблон передаём таким образом. Этот массив потом попадает в функцию extract, перед подключением шаблона.
У меня после всех манипуляций на странице "http://newproj.loc/articles/2" вышла следующая ошибка:
Fatal error:
Uncaught TypeError:
Return value of MyProject\Models\ActiveRecordEntity::getById() must be an instance of MyProject\Models\ActiveRecordEntity or null, array returned in C:\OSPanel\domains\newproj.loc\src\MyProject\Models\ActiveRecordEntity.php:54 Stack trace: #0 C:\OSPanel\domains\newproj.loc\src\MyProject\Controllers\ArticlesController.php(20): MyProject\Models\ActiveRecordEntity::getById(2) #1 C:\OSPanel\domains\newproj.loc\www\index.php(30): MyProject\Controllers\ArticlesController->view(2) #2 {main} thrown in C:\OSPanel\domains\newproj.loc\src\MyProject\Models\ActiveRecordEntity.php on line 54
Вот и всё тут. И не могу найти где собака зарыта.
Ошибку не пробовал прочитать?
Вернутое значение getById должно быть экземпляром или нулем, массив получился в ActiveRecordEntity на 54 строке.
И про что это!? ))
Про то что или объект класса или нулл должны вернуться. А возвращается массив. Из-за этого ошибка. Разбирайся, почему там массив.
Потому что так в уроке было показано(!) :)
Дебаггер в руки и вперёд
Всё как всегда банально оказалось.
В подключении к дб осталась старая запись:
А должно было быть через классы:
Вот и ругалось на массивы, когда вызов должен был возвратить экземпляр.
Красава!
Та ваще капец, моск ломает нещадно... фуф...
Сам порешал, молодец. Учись читать ошибки, в них всё есть.
ivashkevich, спасибо за урок!
Всё доступно и понятно.
Подскажите, как расширить этот класс?
Например:
Как грамотно реализовать добавление дополнительных условий?
Например, вместо getById учитывать несколько условий: WHERE x = 'y' AND a = 'b' ORDER BY k DESC LIMIT n;
Судя по запросу вам требуется уже не способ достать по ID, а что-то другое. Просто добавляете в нужную сущность метод findByXAndA()
Эти два метода не работают в паттерне, из-за этого не могу вывести никнейм, в чем может быть проблема?Когда методы возвращаю в Article.php всё работает
Вы уверены, что понимаете, что такое паттерн?
Ошибся, буду дальше изучать
С вопросом-то разобрались?) Если нет - напишите лучше в телегу или ВК.
А как можно реализовать findAllCount() по аналогии с findAll(), только запросом COUNT(*) ?
Собственно, получить количество записей таблицы, в рамках работы с ActiveRecord.
А в чём проблема? Вы же сами написали ответ на свой вопрос - запросом COUNT(*)
Вопрос в самой реализации кода в ActiveRecordEntity.php
Например код:
Результат просто объект:
Вопрос в том, как грамотно выводить просто число сразу из ActiveRecord при использовании:
Ну, начать стоит с того, почему вы выбрали тип static::class в качестве результата запроса? Вам ведь нужно только число, для чего его в объект запихивать? Пробовали погуглить по этой теме? Я вот погуглил и нашел ответ на второй позиции поисковика - тут.
Спасибо большое за урок, получился очень интересным :)
И всё то, что я делал в комментариях к прошлому уроку оказалось в следующем уроке, правда удобнее и лаконичнее. Но зато класс User уже был готов)
На здоровье)
1.
Я до того, как прочитал готовое решение в уроке, пробовал сам делать и сделал сразу в геттере получение и никнейма.
а в шаблоне уже выводил
Посему у меня возник вопрос : А есть ли разница?
2. Есть ли случаи, когда НУЖНО применять не позднее, а именно раннее связывание? Если да, то можно какие-то примеры?
3. В примере всего две таблицы в БД и данные в них перемежаются, поэтому использован всего один, общий шаблон(и для статей и для юзеров) между БД и "основной программой", хотя в итоге по факту наследования этот шаблон делится уже на два отдельных. А если бы свойства/методы не перемежались у статей и узеров, это были бы отдельные шаблоны? Т.е. фактически для связи основной программы с отдельной таблицей в БД - отдельный шаблон? Префикс ActiveRecord - обязательный в названии класса-шаблона?
А не является ли тут нарушением MVC то, что шаблон по сути обращается к модели за автором? По идее это же работа контроллера. Вьюха не должна знать откуда брать данные, ее задача же просто отобразить уже готовые из контроллера.
Если хотите, можете сделать и так. Здесь шаблон использует только получение свойства модели, это допустимо.
Я для тега title передаю название статьи так:
Это норм так делать?
И насчет комментария Ember.
Вы сказали получать свойство модели в шаблоне допустимо. А вообще передаваемые переменные в шаблоны надо в контроллере создавать, да?
Просто я подумал что если вы в шаблоне получаете свойства модели, то на то есть причина.
Ну в целом да. Просто можно строку по умолчанию брать из какого-нибудь конфига.
Ну, если переменная передается из контроллера, то она там и определяется (создаётся, как вы сказали).
Спасибо за урок, очень интересный!
Хотел попросить, если имеется такая возможность, скинуть исходники предыдущего урока, чтобы можно было ещё раз построчно пробежаться по каждому изменению. До этого урока всё понимал быстро, а здесь почему-то мозг взрывается)
Сорян, не осталось исходников
Ничего страшного, с 8-го урока пробегусь ещё раз всё руками забью, даже лучше усвою программу.
Может быть, не "создание класса не нужно" , а "создание объектов этого класса не нужно"? Класс-то создается в итоге, а его объекты нет.
Конечно да) Спасибо, исправил
Хороший урок. Все работает. Логику и действия на отдельном этапе понимаю хорошо. Только сложно запомнить все взаимосвязи классов и методов.
Главное понимать как работает на данном этапе. Чуть позже сможете самостоятельно повторить. Еще чуть позже - улучшить.
Поясните как быть если запрос в СУБД затрагивает несколько таблиц? То есть тогда каким образом указывать класс объектом которого орм должна дать ответ. И как сам тогда скл запрос вид должен иметь?
Один класс отражает работу с одной таблицей. Соответственно в рамках паттерна ActiveRecord один запрос не должен затрагивать несколько таблиц.
Хорошо, но как быть если у меня карточка хранится в отд таблице её поля, сами данные о человеке фио и комментарий в др таблице и есть ещё третья таблица список три текст поля для карточки специальные.
Кпрточка пользователя хранится вв иде полей а одной таблице потому что в этом проекте фамилии, имён, отчества могут быть более одного. Потом год, место рождения, наличие фотографий и примечания.
Примечания в отд таблице у меня т. К. Там текст и также может храниться текст вместоварчара как у оси полей карточки.
Таким образом у меня должен быть метод в модели состоящий из нескольких орм актив запросов и потом формироваться, собираться воедино или как!? Просто что описано в статье здорово все, но мне не понятно как получить из бд подобным образом сущность если она составная из нескольких таблиц?! Спасибо!
Ну к примеру, есть у тебя Пользователь и есть Социальные_Сети_Пользователя. Тогда в том месте, где нужно получить его социальные сети нужно сделать так:
В классе User прописать этот метод:
Метод getByColumn может быть реализован как-то так:
Привет. Спасибо за ответ. Тогда получается согласно твоему ответу проецируя на мою проблему/вопрос получается следующее. Необходмо для получения составной сущности иметь в определенных моделях отражающих логику подсущностей методы возвращаемые необходимые значения. Эти методы уже должны быть основаны как приведеный тобой метод getByColumn с максимальной универсальностью/Унификацией?!
ТОгда в этом методе луше чтобы было return $entities ? $entities : null;
т.к. могут понадобиьтся все значения, которое может быть не одним единственным.
Если метод начинается с get, то подразумевается что он для получения одной сущности. Для получения нескольких лучше назвать метод find.
И тогда просто return $entities;
Потому что если ожидается массив сущностей, то если не нашлось ни одной, правильнее будет вернуть пустой массив, а не null (null подходит чтобы показать что одной сущности нет).
Примерный смысл то понятен, но я оконочательно запутался такое чувство.
Написал тебе в телеграме вопрос, т.к. в чате так никто и не ответил.
Пришлось попотеть я в файле Db.php написал require_once вместо require. И при запросе автора, файл подключения оказывался пустым. И главное ошибка такая специфическая, сообщала мне, что подключение к БД осуществляется без пароля, хотя в файле с настройками всё прописано) С помощью дебага только нашел)
Хех) Молоток, что дебаггером пользуешься
Добрый день! Большое спасибо за урок!
Должен признать, действительно тяжеловато идет это ученье.
Возник вопрос по следующему предложению:
«Обратите внимание, свойства теперь становятся не private, а protected, чтобы к ним можно было достучаться из класса-родителя», - мы вроде бы должны стучаться из класса-наследника в класс-родителя…?
Привет! Спасибо, исправил ошибку)
Это нормально для процесса обучения. Программирование - это не на саночках кататься) Главное не торопиться, понимать что делаешь.
Так зря исправил, мы же из класса родителя к ним тоже обращались из метода __set
Так, я уже сам запутался. С private тоже ведь работает?
Артем, отличный урок, спасибо! Вопрос такой. Если одно из полей в таблице массив. Свойство класса, соответственно, тоже массив (ORM). Количество элементов в этом массиве всегда разное, от 3 до 10. Как хранить такой массив в БД? Одно из решений - сериализация и хранение под типом BLOB. Рабочий вариант или есть более современные подходы?
Хранение в json это обычная практика
Ох опять это моё чувство дурацкое "не понимаю", столько мыслей в голове, вот даже коммент не могу нормально написать чтоб донести суть проблемы. Да проект работает, код пишу сам, читаю урок, пытаюсь понять откуда что приходит, куда передаётся и вроде бы понимаю, но по сути списываю с доски за учителем, единственное что радует, с ошибками возникающими в коде пока справляюсь сам.
И вот это очень беспокоит что без подглядываний не могу писать.
Артём плиз поддержи как более опытный в этом деле.
Привет. Но это же новая тема, это норм что ты не знаешь что писать)
Почему мы делаем protected свойства в классе Article, если мы используем свойства только внутри класса?
А все понял, мы можем переопределить общедоступные и защищённые свойства, но не закрытые