Этот урок набрал набрал достаточно большое количество
комментариев и дальнейшее его комментирование отключено.
Если вы хотели убедиться в правильности выполнения ДЗ или у вас возник вопрос по уроку,
посмотрите ранее добавленные комментарии, кликнув по кнопке ниже. Скорее всего вы найдете там то, что искали.
Если это не помогло - задайте вопрос в чате в телеграме - https://t.me/php_zone
Я прочел, попробовал, работает. Нужно в файле Mvc\Services\Db добавить пару строк в конструкторе класса, где создаем подключение к БД. Установить два атрибута PDO.
$this->pdo = new \PDO(...);
$this->pdo->exec('SET NAMES UTF8');
$this->pdo->setAttribute(\PDO::ATTR_EMULATE_PREPARES, false); // раз
$this->pdo->setAttribute(\PDO::ATTR_STRINGIFY_FETCHES, false); // два
Теперь, INT(TINYINT) будет приходить из БД как INT, VARCHAR как STRING
src/MyProject/Models/ActiveRecordEntity.php
Примерно понимал как сделать, но добиться нужного результата не получилось, поэтому подсмотрел в готовые решения :(
1. В методах insert и update по сути бОльшая часть методов содержит один и тот же код(преобразование одного массива в два), за исключением очистки массива свойств, строки запроса, ну и заключительной части в методе insert из этого урока. Можно ли как-то унифицировать эти медоды, чтобы не было повторяющегося кода в разных методах?
2.
Например, в поле createdAt должна появиться строка с датой.
Для чего нужно получать эту информацию кроме id, где и как ее использовать? Не учитывая наработку практических навыков конечно.
3. Сложность решения задачи - в первую очередь из-за не знания моря(!) встроенных функций. Сам принцип получения этой информации(решения задачи) понятен, а вот реализация - посредством чего можно сделать - по аналогии с английским языком - вроде и конструкция предложения понятна/знакома, а нужные слова не знаешь.
)) Английский - это просто аналогия. А вопорс в том, что в языке очень много встроенных функций, которыми не приходилось пользоваться и даже неизвестно о их существовании. Например, дойдя уже до этого урока многие вещи просто не опробованы(из тех же операций со строками, массивами. как раз пример из этого урока: array_filter), поэтому многие вопросы решаются посредством костылей и полотнами кода. При этом, тоже не будеьтупо подряд по списку изучать все функции из документации. На это пол жизни уйдет, и не успеешь на работу устроиться))
Если я правильно понял вопрос, то потому что foreach позволяет пройти по тем свойствам объекта (как по элементам массива), которые являются видимыми и доступными. Если копнуть глубже, то с помощью интерфейса Traversable, который определяет является ли класс обходимым с использованием foreach. Я правда очень смутно это понимаю (пока что).
1.
Почему в этом уроке название таблицы и названия столбцов в обратных апострофах, а в прошлом -нет?
2.
Почему в одном уроке запрос в БД с синтаксическим сахаром, в другом - нет? Должно же быть однообразно во всем проекте? И вообще, приемлемо ли его использование в контексте стандартов и чистого кода в PHP?
3.
В примере решения вопроса из домашки использовано получение значения через метод getValue()
Можно и так и так. Это просто моё настроение, не более того)
К единообразию следует стремиться. Но всё равно не получится, особенно если на проекте более одного человека. У меня вот, как видите, и в одиночку не получается, просто прошла неделя между выпуском уроков. А про какой именно сахар речь?
Да, так тоже можно. У меня была логика именно в единообразии, раз начал через неё работать, значит и заканчивать через неё)
Пробегаем по свойствам объекта, смотрим какие из них не установлены, делаем заброс в бд по нужному свойству и, если получаем ответ, записываем в свойство объекта полученное значение.
Решение рабочее, но слишком сложное. Очень много лишних запросов. Можно обойтись одним SELECT-ом. Если не получится, посмотрите другие решения в комментариях.
Некорректное использование null-coalesce оператора. Он используется для возврата значений в правой части в левую часть выражения. У вас же он применяется для побочного вызова кода в случае выполнения или невыполнения условия. Используйте в таких случаях if-else.
Как можно решить проблему, если я через сеттер в модели задаю значение = 0
У меня тогда ActiveRecordEntity просто не учитывает это в insert запросе(просто пропускает поле, значение которого = 0).
Хотя если значение 1, 2, 3 или любое текстовое - то всё ок.
Проблема возникает в ActiveRecordEntity, в строке:
$filteredProperties = array_filter($mappedProperties);
у метода insert, то есть функция array_filter удаляет элементы входящего массива, если у него значение = 0.
Проблему решил так(при этом null, false, пустая строка будут так же удаляться из массива):
Не знаю вроде верно вывел всю информацию после добавления. Но что-то сильно просто, другие в комментариях создавали функции, я же просто вызвал view передав значение id статьи. Такое решение верное?
public function add(): void
{
$author = User::getById(1);
$article = new Article();
$article->setAuthor($author);
$article->setName('Новое название статьи');
$article->setText('Новый текст статьи');
$article->save();
$article = Article::getById($article->getId());
}
Артём еще сделал такую штуку, где получаю свойства есть createdAt и id которые неопределенны и если я в чистом виде буду к ним обращаться мне пишет ошибка $createdAt must not be accessed before initialization
С id тоже самое.
Решил эту проблему добавив заполнение null для этих свойств, которые не определены $this->$propertyName ?? null;
insert2 то что пытался делать в прошлом 21ом уроке в домашнем задании.
insert то что смог собрать из урока и комментариев.
Понимание естьно не полное еще пока, что.
Особенно зачем вызывать в конце insert и как работает refresh метод?!
Чем отличаются методы insert и add между собой?
Спасибо!
Метод insert это метод модели должен быть, а не контроллера. В контроллере метод add, наполняющий модель данными и вызывающий у нее метод save. Если у модели id, нет, то у нее должен вызваться метод insert
Привет всем, не могу понять ДЗ. Вопрос звучит так: Доработайте метод insert() таким образом, чтобы поля объекта обновлялись значениями из БД. Я правильно понимаю, что нужно вывести уже добавленные данные из БД? Так как с помощью array_filter убираются ненужные поля, а дата воспроизводится автоматически в БД и она в данный момент не видна.
Пример решения домашки:
чет сложна)
дебаггер в помощь)
Можно плиз краткое объяснение, как работает refresh()? :) потому что "чет сложна)" реально ахаха
Он берет версию объекта из базы, получает все его свойства.
Затем бежит в цикле по этим свойствам и:
Можно ли объекту $article присвоить данные полученные по id, который вернула функция getLastInsertId?
$article = Article::getById($article->getId());
Можно. Но зачем?
Немного не пойму, почему он числовые значения передаёт как строковые после добавления refresh();
Потому что из базы так возвращаются.
Понял, спасибо!
https://stackoverflow.com/questions/20079320/php-pdo-mysql-how-do-i-return-integer-and-numeric-columns-from-mysql-as-int
Но это можно поправить.
О спасибо! Обязательно прочту
Я прочел, попробовал, работает. Нужно в файле Mvc\Services\Db добавить пару строк в конструкторе класса, где создаем подключение к БД. Установить два атрибута PDO.
Теперь, INT(TINYINT) будет приходить из БД как INT, VARCHAR как STRING
Отлично что разбираетесь самостоятельно. Так держать!
Тяжеловато вошло....
А так можно делать??
Отлично
src/MyProject/Models/ActiveRecordEntity.php
Примерно понимал как сделать, но добиться нужного результата не получилось, поэтому подсмотрел в готовые решения :(
Главное чтобы в итоге это решение было вам понятно и вы его запомнили, точнее, могли реализовать в дальнейшем.
Спасибо за урок!
Можно ли так упростить функцию refresh? Или могут быть случаи, когда перебор задаст неправильные значения?
В базе имена столбцов именуются с подчеркиваниями. В коде - camelCase. Так что нет, нельзя.
Но разве в ActiveRecord прописанный магический метод __set, не занимается переименовыванием свойств в надлежащий вид?
А, сорян. Да, можно
1. В методах insert и update по сути бОльшая часть методов содержит один и тот же код(преобразование одного массива в два), за исключением очистки массива свойств, строки запроса, ну и заключительной части в методе insert из этого урока. Можно ли как-то унифицировать эти медоды, чтобы не было повторяющегося кода в разных методах?
2.
Для чего нужно получать эту информацию кроме id, где и как ее использовать? Не учитывая наработку практических навыков конечно.
3. Сложность решения задачи - в первую очередь из-за не знания моря(!) встроенных функций. Сам принцип получения этой информации(решения задачи) понятен, а вот реализация - посредством чего можно сделать - по аналогии с английским языком - вроде и конструкция предложения понятна/знакома, а нужные слова не знаешь.
)) Английский - это просто аналогия. А вопорс в том, что в языке очень много встроенных функций, которыми не приходилось пользоваться и даже неизвестно о их существовании. Например, дойдя уже до этого урока многие вещи просто не опробованы(из тех же операций со строками, массивами. как раз пример из этого урока: array_filter), поэтому многие вопросы решаются посредством костылей и полотнами кода. При этом, тоже не будеьтупо подряд по списку изучать все функции из документации. На это пол жизни уйдет, и не успеешь на работу устроиться))
Не переживайте. Если вы вместо array_filter напишите foreach, хуже не станет.
Домашка
Отлично!
Почему-то два раза отправилось одно и то же - удалил.
Article
ActiveRecordEntity
Решение должно быть гибким и касаться всех полей, а не только createdAt, приведенного в качестве примера.
Общий объект ActiveRecordEntity ничего не должен знать о статьях!
Файл ActiveRecordEntity.php:
И в Article.php добавить геттер getCreatedAt().
Решение должно быть гибким и касаться всех полей, а не только createdAt, приведенного в качестве примера.
Идея была обновить все поля, но компактного решения не нашел, поэтому вот так (наверное самое оптимальное):
Ок, а благодаря чему стало возможным вот так итерировать объект?
Если я правильно понял вопрос, то потому что foreach позволяет пройти по тем свойствам объекта (как по элементам массива), которые являются видимыми и доступными. Если копнуть глубже, то с помощью интерфейса Traversable, который определяет является ли класс обходимым с использованием foreach. Я правда очень смутно это понимаю (пока что).
Отлично. Этот интерфейс позволяет... да что я вам буду рассказывать, вы можете прочитать о нем в документации. Там же есть примеры.
Отлично
?
Отлично!
1.
Почему в этом уроке название таблицы и названия столбцов в обратных апострофах, а в прошлом -нет?
2.
Почему в одном уроке запрос в БД с синтаксическим сахаром, в другом - нет? Должно же быть однообразно во всем проекте? И вообще, приемлемо ли его использование в контексте стандартов и чистого кода в PHP?
3.
В примере решения вопроса из домашки использовано получение значения через метод getValue()
Но ведь можно напрямую обратиться к свойству объекта без встроенного геттера:
В чем разница между такими способами получения значения?
vs
Ок, спасибо за ответ
refrech - опечатка в слове
В остальном ОК!
Спасибо, исправил на refresh
Пробегаем по свойствам объекта, смотрим какие из них не установлены, делаем заброс в бд по нужному свойству и, если получаем ответ, записываем в свойство объекта полученное значение.
Решение рабочее, но слишком сложное. Очень много лишних запросов. Можно обойтись одним SELECT-ом. Если не получится, посмотрите другие решения в комментариях.
Переделал в один запрос. Так лучше?
Только непонятно, для чего это. У вас же уже есть метод для получения объекта из базы.
Мда, что-то я ударился в изобретание велосипеда. Думал, что тащить всю запись из БД не стоит. Теперь несколько строк всего получается)
И можно ли вместо
писать
Некорректное использование null-coalesce оператора. Он используется для возврата значений в правой части в левую часть выражения. У вас же он применяется для побочного вызова кода в случае выполнения или невыполнения условия. Используйте в таких случаях if-else.
ActiveRecordEntity.php
Отлично!
Как можно решить проблему, если я через сеттер в модели задаю значение = 0
У меня тогда ActiveRecordEntity просто не учитывает это в insert запросе(просто пропускает поле, значение которого = 0).
Хотя если значение 1, 2, 3 или любое текстовое - то всё ок.
Видимо значение отфильтровывается в array_filter. Вы дебажить пробовали?
Проблема возникает в ActiveRecordEntity, в строке:
$filteredProperties = array_filter($mappedProperties);
у метода insert, то есть функция array_filter удаляет элементы входящего массива, если у него значение = 0.
Проблему решил так(при этом null, false, пустая строка будут так же удаляться из массива):
Возможно кому-то пригодится.
Я ожидал что вы всё-таки свой коллбэк напишите и будете сравнивать с null. Потому что в вашем варианте будут и пустые строки отфильтровываться.
Чтобы не отфильтровывались пустые строки и нули необходимо
?
Супер!
Не знаю вроде верно вывел всю информацию после добавления. Но что-то сильно просто, другие в комментариях создавали функции, я же просто вызвал view передав значение id статьи. Такое решение верное?
Артём еще сделал такую штуку, где получаю свойства есть createdAt и id которые неопределенны и если я в чистом виде буду к ним обращаться мне пишет ошибка $createdAt must not be accessed before initialization
С id тоже самое.
Решил эту проблему добавив заполнение null для этих свойств, которые не определены $this->$propertyName ?? null;
Добавил редирект на главную страницу, спасибо:)
Думал почему ошибка выходит, а это я автора с id 1 удалил
ArticlesController.php
Article.php
```....................
....................
.............
private function insert2(array $mappedProperties): void
{
.............
Метод insert это метод модели должен быть, а не контроллера. В контроллере метод add, наполняющий модель данными и вызывающий у нее метод save. Если у модели id, нет, то у нее должен вызваться метод insert
Вроде понял. Пцтаница возникла, что в уроке где в домашнем задании предлагалось попробовать написать insert самомстоятельно не сразу понял.
Сейчас, что листинг кода предоставил это нормально?
Да, с кодом дела отлично
Почитав коментарии понял, что лучше вывести в отдельную функцию
В таком случае.
Ага, норм
Привет всем, не могу понять ДЗ. Вопрос звучит так: Доработайте метод insert() таким образом, чтобы поля объекта обновлялись значениями из БД. Я правильно понимаю, что нужно вывести уже добавленные данные из БД? Так как с помощью array_filter убираются ненужные поля, а дата воспроизводится автоматически в БД и она в данный момент не видна.
Да, всё так