Этот урок набрал набрал достаточно большое количество
комментариев и дальнейшее его комментирование отключено.
Если вы хотели убедиться в правильности выполнения ДЗ или у вас возник вопрос по уроку,
посмотрите ранее добавленные комментарии, кликнув по кнопке ниже. Скорее всего вы найдете там то, что искали.
Если это не помогло - задайте вопрос в чате в телеграме - https://t.me/php_zone
Скажите, я правильно понял, если мы хотим изменить существующую позицию в БД, мы делаем $article = Article::getById($articleId) в контроллере и работаем с этим объектом, а если мы создаем новую сущность, то $article1 = new Article() ?
И как избежать использование foreach два раза, криво вроде как-то выглядит? :)
public function create() {
$article = new Article;
$article->setName('Название новой статьи');
$article->setText('Текст новой статьи');
$article->setAuthor(1);
$article->save();
}
нельзя значение, пришедшее извне помещать в запрос без какой-либо фильтрации - всегда используйте параметризованные значения. В самом запросе только подстановки вида :param1, :param2. Сами значения - в параметрах, с которыми нужно выполнить запрос;
исправление предыдущего пункта приведет к отсутствию необходимости в приведении значений к строкам/не строкам
[A-Z] - берём большие буквы
(?<!^) - а это означает, что при этом самую первую букву в начале строки мы не берем, даже если она большая
_$0 - это знак подчеркивания, за которым следует нулевое совпадение в регулярке (нулевое - это вся строка, попавшая под регулярку. В нашем случае - это одна большая буква). Таким образом, с помощью preg_replace, мы заменяем все большие буквы A - Z на _A - _Z. А затем с помощью strtolower приводим всю строку к нижнему регистру.
Напишите самостоятельно метод insert(), который будет добавлять в базу новую запись. Не торопитесь, разбейте задачу на несколько компонентов и решите, какую последовательность действий нужно сделать.
Можно на уровне объектов оперировать с DateTime. А при сохранении и чтении из БД уже преобразовывать к строковому представлению. Как определять, что это поле с датой? Можно сделать специальные аннотации PhpDoc-ом к этому свойству в объекте, и определять с помощью рефлексии.
Где-то подсмотрел, но думаю, что понимание темы - это успех)
Article Controller
public function create(): void
{
$article2 = new Article();
$article2->setName('Новая статья 2');
$article2->setText('Новый текст 2');
$article2->setAuthorId(1);
$article2->save();
}
Где-то подсматривал, потому что пока не всё так легко, как хотелось бы)
ArticleController.php
public function create()
{
$article = new Article;
$article -> setName('Название новой статьи');
$article -> setText('Текст новой статьи');
$article -> setAuthorId(1);
$article -> save();
}
var_dump в рабочем коде быть не должно - удаляйте перед отправкой на проверку. При обращении к свойствам и методам объектов с помощью стрелочки, её не нужно окружать пробелами.
Добрый день! Домашнее задание разобрал не полностью сам, смотрел подсказки в комментариях, но главное с трудом дошло откуда всё берется, вроде разобрался))
Небольшой вопрос: откуда создание статьи получать логичнее, на отсутствующей со статьёй вот так : '~^articles/(\d+)/create$~', или всё таки '~^articles/create$~'?
Вместо $propertyName (видим $ - значит это переменная) подставляется значение этой переменной. Если там строка "title", то произойдет обращение к $this->title; (уже без $)
<?php
namespace MyProject\Models\Articles;
use MyProject\Models\ActiveRecordEntity;
use MyProject\Models\Users\User;
class Article extends ActiveRecordEntity
{
protected $name;
protected $text;
protected $authorId;
protected $createdAt;
public function setAuthorId(int $num)
{
$this->authorId = $num;
}
public function setName(string $name)
{
$this->name = $name;
}
public function setText(string $text)
{
$this->text = $text;
}
public function setCreatedAt(string $date)
{
$this->createdAt = $date;
}
public function getName() : string
{
return $this->name;
}
public function getText() : string
{
return $this->text;
}
public function getAuthor() : User
{
return User::getById($this->authorId);
}
protected static function getTableName() : string
{
return 'articles';
}
}
ArticlesController.php
....
public function create()
{
$article = new Article;
$article->setAuthorId(1);
$article->setName('Created note.');
$article->setText('Created many text for created note.');
$article->setCreatedAt(date('Y-m-d H:i:s'));
$article->save();
}
нашел, забыл скобки поставить в запросе и кроме того не отфильтровал этой строкой $filteredProperties = array_filter($mappedProperties); с пустыми параметрами почему то не работало , наверное потому что нуло давало и нулл не принимает база с настройками NOT NULL...
public function create():void
{
$article = new Article();
$article->setName('Новая статья');
$article->setText('Новый текст');
$article->setAuthorId(2);
$article->save();
}
public function create(): void
{
$article = new Article();
$article->setAuthorId(1);
$article->setName('Заголовок добавленной статьи в БД');
$article->setText('Текст добавленной статьи в БД .. ');
$article->save();
}
А если я хочу все это дело повесить на кнопку не уходя на страницу edit, наподобие form action , чтобы по кнопке обновлялись данные в БД, а после редиректа обновлялись на странице, то мне вызов метода на нее только повесить?
Приветствую всех.у меня такой вопрос. insert() запускаться лишь тогда когда нет свойства id экземпляра класса Article, а данного свойства не будет если не будет создан объект данного класса, который создается после запроса в БД по id который мы получаем из url, и так как edit() получает результат static::getById(), который на отсутствующий в БД id вернет лишь null, то будет загружен шаблон с ошибкой 404 о том что страница не найдена.следовательно insert ни когда не выполнится, так save() не будет запушен, верно?заранее спасибо за ответ)
Там же return написан после рендеринга 404 шаблона. Разумеется, ничего ниже в этом методе не выполнится. Рекомендую повторить урок про функции из курса PHP для начинающих.
public function create(): void
{
$article = new Article();
$article->setName('Новая статья');
$article->setText('Текст новой статьи');
$article->setAuthorId(1);
$article->save();
}
src/MyProject/Models/ActiveRecordEntity.php
Код в foreach переделал (надеюсь это не страшно).
От null избавился с помощью if, потом увидел, что многие используют array_filter, но решил оставить уже так.
Напишите самостоятельно метод insert(), который будет добавлять в базу новую запись. Не торопитесь, разбейте задачу на несколько компонентов и решите, какую последовательность действий нужно сделать.
Моя последовательность была следующая:
1) Прежде всего создается новый объект. Для этого я создал новый метод create:
public function create(): void
{
$article = new Article();
$article->setName('Заголовок новой статьи');
$article->setText('Текст новой статьи');
$article->setAuthorId(1);
$article->save();
}
2)В методе insert первым делом я отфильтровал переданный массив от null-значений id и createdAt, т.к. с ними запрос не выполнится:
private function insert(array $mappedProperties): void
{
$filterProperties = array_filter($mappedProperties);
3)Т.к. я решил составлять sql-запрос с использованием псевдопеременных (вроде как это хорошая практика), то создал 3 массива(для названия столбцов, для псевдопеременных и для значений этих псевдопеременных) и переменную $index для последующего перебора:
$columns = [];
$values = [];
$params = [];
4)Перебором из входного массива составляю три необходимых для составления запроса:
Первая домашка которую не сделал сходу, пришлось взять паузу от интенсивного прохождения курса, после чего перечитал весь курс по ООП сначала и быстро сделал домашку!
Теперь ок. Способ был извращенным не только потому что не знали про array_filter. Правильнее было бы отсекать null-значения, потому что у каждой сущности будут свои нумерованные ключи, полагаться на них не стоит.
Пришлось попотеть, час делал. Зато все полностью сам) И такой еще не было, с функцией array_keys.
ArticlesController.php
public function add(): void
{
$article = new Article();
$article->setName('Новая добавленная статья');
$article->setText('Новый текст статьи');
$article->setAuthorId(2);
$article->setCreatedAt(date("Y-m-d H:i:s"));
$article->save();
}
Использовал объект DateTime при работе с датой в сеттере и геттере. Но со временем в БД какая-то лажа. то точно отображает время создания, то немного раньше, то намного раньше. Непонятно почему.
А по работе с датой через рефлексию - не понял. Пересмотрел методы в разделе рефлексий, не понял каким образом через рефлексию работать с датой. Можно поподробнее про выделенное?:
Можно на уровне объектов оперировать с DateTime. А при сохранении и чтении из БД уже преобразовывать к строковому представлению. Как определять, что это поле с датой? Можно сделать специальные аннотации PhpDoc-ом к этому свойству в объекте, и определять с помощью рефлексии.
Приемлемо ли одновременное использование и Doc-блоков и комментариев внутри методов/классов?
В методе из урока не использована объявленная переменная в этой строке:
Спасибо, исправил
Использовал объект DateTime при работе с датой в сеттере и геттере.
Перед сохранением в базу приводите DateTime к UTC
А по работе с датой через рефлексию - не понял.
Почитайте про Doctrine Annotations. Речь о том, чтобы при сохранении в базу у свойства считывались PhpDoc-комментарии, и там будет написано @type DateTime, например. И наш маппер преобразует это значение в нужный формат, основываясь на комментариях к каждому свойству.
Приемлемо ли одновременное использование и Doc-блоков и комментариев внутри методов/классов?
В Doc блоке можно описать общие комментарии ко всему классу,методу в целом, а если нужны детальные комментарии по отдельной строчке или блоку кода внутри? Ну вот например отдельный метод из урока, в котором есть и Doc блок и, допустим, если нужны - более подробные комментарии внутри:
/**
* Returns array containing two separate ones with params and values.
* Prepared data for filling DB up.
*
* @return array
*/
public function preparePropertiesToDbFormat(): array
{
/*
* Object properties' names format preparing
* for using in SQL queries
* */
$reflector = new \ReflectionObject($this);
$properties = $reflector->getProperties();
$mappedProperties = [];
foreach ($properties as $property) {
$propertyName = $property->getName();
$mappedProperties[$this->CamelCaseToUnderscore($propertyName)] = $this->$propertyName;
}
$mappedProperties = array_filter($mappedProperties); // removing null-values from array
/*
* Dividing common array $mappedProperties = [param => value]
* into separate ones:
* $params = [param = :param]
* $values = [:param => value]
* */
$params = [];
$values = [];
foreach ($mappedProperties as $column => $value) {
$params[] = $column.' = :'.$column;
$values[':'.$column] = $value;
}
return $mappedProperties = ['params' => $params, 'values' => $values];
}
Однострочный комментарий конечно избыточен. И так понятно, что делает функция. Это в качестве примера, что используются разные комментарии одновременно - и однострочные и поблоково -многострочные, кроме этого метод имеет обобщающий, но без подробностей Doc блок
Скопировал похоже как-то криво. В коде с форматированием, сейчас смотрю, нормально все. Да и почти все форматирование шторм на себя берет, редко его поправлять приходится.
...
public function create(): void
{
$newArticle = new Article();
$newArticle->setName('Имя моей новой статьи');
$newArticle->setText('Текст моей новой статьи');
$newArticle->setAuthorId('1');
$newArticle->save();
}
Так в update мы как раз через именованные параметры делали.
Результирующий запрос будет:
UPDATE articles SET name = :param1, text = :param2, author_id = :param3, created_at = :param4, id = :param5 WHERE id = 1
И потом уже в query() будут переданы нужные значения.
А у вас данные присутствуют в самом запросе.
INSERT INTO articles (`name`, `text`, `author_id`, `created_at`, `id`) VALUES ('Статья о том, как я погулял', 'AZAZA', '1', '2020-06-21 12:06:32', '1')
Артем, я не могу понять почему не работает. Я смотрю дебагером, все четко, запрос формируется какой нужно, если я запрос вручную вставляю в пхпмайадмин - все отрабатывает.
Но при запуске этого экшна в браузере - в бд не создается новая строка.
public function create()
{
$article = new Article();
$article->setName('Новое название статьи 2');
$article->setText('Новый текст статьи 2');
$article->setAuthorId(2);
$article->save();
}
Написав функцию insert самостоятельно, и уже думая её отправлять, посмотрел комментарии и понял, что не учёл все моменты.
Добавил сортировку array_filter, изменил названия переменных и переписал код, после чего у меня появилась ошибка, что в функцию implode аргументы заявлены неправильно. Очень долго ломал голову в чём же проблема. Пользуясь отладчиком понял, что аргумент params, объявлен как string. И в итоге оказалось, что я просто приравнивая
$params = ':param' . $index;
забыл поставить квадратные скобки...
Из плюсов: Научился более уверенно пользоваться отладчиком
Из минусов: Убитое время и самобичевание по поводу такой мелкой оплошности)
...
public function create( ): void
{
$article = new Article();
$article->setAuthorId(1);
$article->setName('Заголовок добавленной статьи в БД');
$article->setText('Текст добавленной статьи в БД .. ');
$article->save();
}
...
$article = new Article();
$article->setName('Реализую метод insert');
$article->setText('Если ты это видишь то похоже что у меня получилось');
$article->setAuthorId(1);
$article->save();
Сейчас прохожу следующий урок и понимаю что тупанул xD.
Оказывается надо было просто убрать элементы с null так как они сами подставятся в таблице из за значения по умолчанию.
Ничего не получилось.
Прочитал много раз уроки 21 и 22.
Повторил все из них код.
Работает только обновление.
Инесерт не получилось, никак. Даже копирование готовых решений из коментариев ничего не дало.
Какой url должен быть и что он должен в итоге вывести?!
public function create(): void
{
$article = new Article();
$article->setAuthorId(2);
$article->setName('Статья про ежей');
$article->setText('Еж бежал по дорожке, на спине нес...');
$article->setCreatedAt(date("Y-m-d H:i:s"));
$article->save();
}
В модели Article.php добавил нужные сеттеры и геттеры
В роуте добавил
public function insert(): void
{
$article = Article::getById(1);
$article->id = null;
if ($article === null) {
$this->view->renderHtml('errors/404.php', [], 404);
return;
}
$article->setName('Добавлени статья : название статьи');
$article->setText('Новый текст добавленной статьи');
$article->setcreatedAt(date("Y-m-d m:s"));
$article->setauthorId(1);
$article->save();
}
Article.php
public function setName($name): string
{
return $this->name=$name;
}
public function setText($text): string
{
return $this->text=$text;
}
public function setcreatedAt($date): string
{
return $this->createdAt=$date;
}
public function setauthorId($Id): string
{
return $this->authorId=$Id;
}
}
Привет, Артём!
Курс я проходил до курса ооп пхп.
Снова перещел по ссылке и не нашел что-то по инсерту ничего.
Обратился в поисковик.
Подсмотрел некоторые решения домашнего задания других оучающихся.
В итоге, у меня появился осознанный, успешно проверенный метод insert.
Сеттеры в модель я добавил еще в прошлый раз, Но обнаружил ошибку с функцией дата у меня в контроллере при вызове.
Понадеялся на память. В результатате тестирвоания успешно исправил.
ArticlesController.php
public function insert(): void
{
$article = Article::getById(1);
$article->id = null;
if ($article === null) {
$this->view->renderHtml('errors/404.php', [], 404);
return;
}
$article->setName('Добавлени статья : название статьи');
$article->setText('Новый текст добавленной статьи');
$article->setcreatedAt(date("Y-m-d H:i:s"));
$article->setauthorId(1);
$article->save();
}
доброго времени суток, надеюсь, еще отвечаете здесь в комментариях (все-таки несколько лет прошло с момента создания курса).
вопрос следующий, вы посоветовали array_filter() для отсеивания пустых свойств, чтобы субд могла принять запрос и добавить новые данные. однако, изучая мануал (https://www.php.net/manual/ru/function.array-filter.php), я заметил в примере #2, что если не указать фильтрующую функцию, то помимо значения null, так же будут удалять значения: false, '0', 0. а ведь они вполне могут понадобиться в нашей бд.
есть ли другой, наиболее правильный способ или все-таки нужно сделать функцию по отсеиванию исключительно значений null?
в 18 уроке, мы поменяли свойства моделей с private, на protected (ссылка на урок https://php.zone/oop-v-php-prodvinutyj-kurs/pattern-active-record-v-php). все было ок, работало, пока в комментариях здесь не прочитал, что вы просите сделать свойства private. если их сделать private, тогда в методе mapPropertiesToDbFormat() в строке: $mappedProperties[$propertyNameAsUnderscore] = $this->$propertyName; будет ошибка, потому что невозможно получить доступ к приватному свойству. если свойства protected, тогда все работает.
я уже всю голову сломал, как правильно?
public function create(): void
{
$article = new Article;
$article->setAuthorId(1);
$article->setName('Новое название статьи');
$article->setText('Новый текст статьи');
$article->save();
}
ArticleController:
ActiveRecordEntity
Скажите, я правильно понял, если мы хотим изменить существующую позицию в БД, мы делаем $article = Article::getById($articleId) в контроллере и работаем с этим объектом, а если мы создаем новую сущность, то $article1 = new Article() ?
И как избежать использование foreach два раза, криво вроде как-то выглядит? :)
Привет, сначала ответ на твой первый вопрос - да, всё правильно.
По поводу кода и второго вопроса:
В целом - всё хорошо, есть небольшая путаница в контроллере, но это ничего страшного, со временем всё будет ;)
..
ArticlesController:
ActiveRecordEntity:
Привет, нужно исправить:
А если маски :name, :text использовать, такое допускается? Когда 10-12 :paramN можно и запутаться.
Да, конечно можно
Спасибо, всё принял к сведению, ну и подробное описание обнаружил в последующем уроке)
красава)
"Преобразовываем это значение из camelCase в строку_с_подчеркушками, например, author_id – именно так называется поле в базе данных"
Можно ли в БД имена столбцов писать сразу в camelCase или так не принято?
Так не принято. Нужно именовать все маленькими буквами, разделяя слова подчеркушками.
Где можно почитать про
'/(?<!^)[A-Z]/', '_$0'
В частности, что такое < ! и _$0
Напишите самостоятельно метод insert(), который будет добавлять в базу новую запись. Не торопитесь, разбейте задачу на несколько компонентов и решите, какую последовательность действий нужно сделать.
Отлично! Очень рад твоей скорости)
ArticlesController
ActiveRecordEntity
Чувствую что-то тут не так)
В каком именно месте ты это чувствуешь?)
Стоит ли cteatedAt так задавать? Или есть возможность это автоматизировать?
Можно на уровне объектов оперировать с DateTime. А при сохранении и чтении из БД уже преобразовывать к строковому представлению. Как определять, что это поле с датой? Можно сделать специальные аннотации PhpDoc-ом к этому свойству в объекте, и определять с помощью рефлексии.
В date(c) кавычки забыл, php будет искать константу c.
Где-то подсмотрел, но думаю, что понимание темы - это успех)
Article Controller
ActiveRecord
Отлично!
Где-то подсматривал, потому что пока не всё так легко, как хотелось бы)
ArticleController.php
ActiveRecordEntity.php
Правильно ли я использую роут?
Routes.php
Всё хорошо, при обращении к свойствам и методам объектов не нужно ставить пробелы:
Всё понял) Спасибо
var_dump в рабочем коде быть не должно - удаляйте перед отправкой на проверку. При обращении к свойствам и методам объектов с помощью стрелочки, её не нужно окружать пробелами.
Добрый день! Домашнее задание разобрал не полностью сам, смотрел подсказки в комментариях, но главное с трудом дошло откуда всё берется, вроде разобрался))
ActiveRecordEntity.php
ArticlesController.php
Роут
Небольшой вопрос: откуда создание статьи получать логичнее, на отсутствующей со статьёй вот так : '~^articles/(\d+)/create$~', или всё таки '~^articles/create$~'?
Ок. А откуда возьмёте id ещё не созданной статьи?
Точно, недодумал )))
разве в результате мы не получаем массив типа 'author_id'=>string 'authorId'
А запускать пробовал?)
да я же не об этом)я просто логику не понимаю,как оно работает.
Вместо $propertyName (видим $ - значит это переменная) подставляется значение этой переменной. Если там строка "title", то произойдет обращение к $this->title; (уже без $)
Article.php
ArticlesController.php
ActiveRecordEntity.php
Отлично! А почему поля protected?
Не помню)) не менял поля. Нужно сделать private.
Нужно)
если установить private на свойства, тогда при вызове метода mapPropertiesToDbFormat() выбрасывает ошибку при попытке работы с приватным свойством.
Верно)
в роде как по логике правильно, но так и не смог добиться , чтоб оно в базу писало....
Дебажить пробовал?
с помощью var_dump , а как посмотреть тот момент где НЕ происходит запись в БД так и не понял
Проверь, правильно ли формируется запрос. Попробуй скопировать его и выполнить в phpmyadmin
нашел, забыл скобки поставить в запросе и кроме того не отфильтровал этой строкой $filteredProperties = array_filter($mappedProperties); с пустыми параметрами почему то не работало , наверное потому что нуло давало и нулл не принимает база с настройками NOT NULL...
Отлично. Молодец!
Супер!
Добавил роут:
Добавил метод create в ArticlesController
Метод insert в ActiveRecordEntity
Подсмотрел функцию array_filter в комментах :)
Супер!
Поглядел некоторую часть с роутом и фильтром в комментариях
ActiveRecordEntity.php
ArticleController.php
routes.php
Отлично
А если я хочу все это дело повесить на кнопку не уходя на страницу edit, наподобие form action , чтобы по кнопке обновлялись данные в БД, а после редиректа обновлялись на странице, то мне вызов метода на нее только повесить?
После какого редиректа? Ты точно знаешь, что это такое?
Я ответил на свой вопрос в статье "Редактируем статьи в блоге на PHP" )
Я как-то нить потерял,откуда к нам значения в $articleId приходят.
В каком месте? Отладчиком пробовал пользоваться?
Приветствую всех.у меня такой вопрос. insert() запускаться лишь тогда когда нет свойства id экземпляра класса Article, а данного свойства не будет если не будет создан объект данного класса, который создается после запроса в БД по id который мы получаем из url, и так как edit() получает результат static::getById(), который на отсутствующий в БД id вернет лишь null, то будет загружен шаблон с ошибкой 404 о том что страница не найдена.следовательно insert ни когда не выполнится, так save() не будет запушен, верно?заранее спасибо за ответ)
Там же return написан после рендеринга 404 шаблона. Разумеется, ничего ниже в этом методе не выполнится. Рекомендую повторить урок про функции из курса PHP для начинающих.
src/routes.php
src/MyProject/Controllers/ArticlesController.php
src/MyProject/Models/ActiveRecordEntity.php
Это что такое? Для блоков if-else ВСЕГДА используйте фигурные скобки.
В остальном отлично
Моя последовательность была следующая:
1) Прежде всего создается новый объект. Для этого я создал новый метод create:
и прописал для него новый роут:
2)В методе insert первым делом я отфильтровал переданный массив от null-значений id и createdAt, т.к. с ними запрос не выполнится:
3)Т.к. я решил составлять sql-запрос с использованием псевдопеременных (вроде как это хорошая практика), то создал 3 массива(для названия столбцов, для псевдопеременных и для значений этих псевдопеременных) и переменную $index для последующего перебора:
4)Перебором из входного массива составляю три необходимых для составления запроса:
5)Формирую запрос, создаю подключение к бд и выполняю запрос:
Спасибо за урок!
Неправильно. Либо они обязательные в базе и всегда должны заполняться при выполнении INSERT, либо сделайте их необязательными в БД.
Для чего переменная $index?
Но ведь id и created_at необязательные, т.к. у id тип AUTO_INCREMENT, а у created_at есть значение по умолчанию.
Переменная index ни к чему) Исправил
К сожалению, пришлось подсмотреть, но суть понял.
Отлично
Файл routes.php:
Файл ArticleController.php:
Файл ActiveRecordEntity.php:
В Article.php добавлен сеттер setAuthorId($authorId)
Отлично
Отлично
src/routes.php
src/MyProject/Controllers/ArticlesController.php
src/MyProject/Models/ActiveRecordEntity.php
Первая домашка которую не сделал сходу, пришлось взять паузу от интенсивного прохождения курса, после чего перечитал весь курс по ООП сначала и быстро сделал домашку!
Для чего здесь значения сначала присваиваются переменным, а только потом идут в модель?
По методу insert - ОК!
Только для того чтобы сделать строки с сеттерами короче (на самом деле незнаю для чего=)
Кидайте сразу в сеттер.
В принципе работает. :/
Это что такое?
Почему привязка по каким-то непонятным числам?
Обновил+
Недавно узнал о функции array_filter, вот и пришлось таким извращенным способом удалять ключи из массива :/
Теперь ок. Способ был извращенным не только потому что не знали про array_filter. Правильнее было бы отсекать null-значения, потому что у каждой сущности будут свои нумерованные ключи, полагаться на них не стоит.
Хорошо, понял. Спасибо)
Пришлось попотеть, час делал. Зато все полностью сам) И такой еще не было, с функцией array_keys.
ArticlesController.php
ActiveRecordEntity.php
Отлично!
В методе из урока не использована объявленная переменная в этой строке:
Полагаю, должно быть так:
По заданию к уроку:
Немного переделал метод подготовки данных для заполнения БД из урока:
ActiveRecordEntity.php:
Метод INSERT:
ArticlesController.php:
routes.php:
Использовал объект DateTime при работе с датой в сеттере и геттере. Но со временем в БД какая-то лажа. то точно отображает время создания, то немного раньше, то намного раньше. Непонятно почему.
А по работе с датой через рефлексию - не понял. Пересмотрел методы в разделе рефлексий, не понял каким образом через рефлексию работать с датой. Можно поподробнее про выделенное?:
Приемлемо ли одновременное использование и Doc-блоков и комментариев внутри методов/классов?
Спасибо, исправил
Перед сохранением в базу приводите DateTime к UTC
Почитайте про Doctrine Annotations. Речь о том, чтобы при сохранении в базу у свойства считывались PhpDoc-комментарии, и там будет написано @type DateTime, например. И наш маппер преобразует это значение в нужный формат, основываясь на комментариях к каждому свойству.
Вот этот вопрос не понял
В целом домашка на отлично
В Doc блоке можно описать общие комментарии ко всему классу,методу в целом, а если нужны детальные комментарии по отдельной строчке или блоку кода внутри? Ну вот например отдельный метод из урока, в котором есть и Doc блок и, допустим, если нужны - более подробные комментарии внутри:
Однострочный комментарий конечно избыточен. И так понятно, что делает функция. Это в качестве примера, что используются разные комментарии одновременно - и однострочные и поблоково -многострочные, кроме этого метод имеет обобщающий, но без подробностей Doc блок
Можно совместно использовать. Просто строку с аннотацией можно начинать со специального символа. Например - @
Добавил
src\routes.php:
src\MyProject\Models\Articles\Article.php:
src\MyProject\Controllers\ArticlesController.php
src\MyProject\Models\ActiveRecordEntity.php:
Отлично!
Всегда используйте фигурные скобки для блоков if-else
И проблема с форматированием. Делайте отступы как в уроках. Для этого в шторме можно нажать Ctrl+Alt+L
В остальном отлично
Скопировал похоже как-то криво. В коде с форматированием, сейчас смотрю, нормально все. Да и почти все форматирование шторм на себя берет, редко его поправлять приходится.
ActivityRecordEntity.php
Имеет ли смысл третьим аргументом передавать класс?
Я думаю нет, там будет пустой массив.
Отлично
Нет, INSERT не вернет добавленную запись.
routes.php
ArticlesController.php
ActiveRecordEntity.php
Так не годится, нужно использовать параметризованные запросы, иначе есть риск нарваться на SQL injection
Артем, мы тоже самое сделали в апдейте, там тоже есть шанс нарваться на иньекции бд?
Так в update мы как раз через именованные параметры делали.
Результирующий запрос будет:
И потом уже в query() будут переданы нужные значения.
А у вас данные присутствуют в самом запросе.
Я только сейчас понял для чего эти "param" нужны.
Артем, я не могу понять почему не работает. Я смотрю дебагером, все четко, запрос формируется какой нужно, если я запрос вручную вставляю в пхпмайадмин - все отрабатывает.
Но при запуске этого экшна в браузере - в бд не создается новая строка.
В VALUES() передаются значения вида title = :param1, хотя должны быть просто :param1
Спасибо за подсказку
Огонь)
ArticlesController
ActiveRecordEntity
Отлично!
Написав функцию insert самостоятельно, и уже думая её отправлять, посмотрел комментарии и понял, что не учёл все моменты.
Добавил сортировку array_filter, изменил названия переменных и переписал код, после чего у меня появилась ошибка, что в функцию implode аргументы заявлены неправильно. Очень долго ломал голову в чём же проблема. Пользуясь отладчиком понял, что аргумент params, объявлен как string. И в итоге оказалось, что я просто приравнивая
забыл поставить квадратные скобки...
Из плюсов: Научился более уверенно пользоваться отладчиком
Из минусов: Убитое время и самобичевание по поводу такой мелкой оплошности)
Сам код:
routes.php
ArticleController.php
ActiveRecordEntity.php
Отлично
Работает, но в контроллере я делал так
Сейчас прохожу следующий урок и понимаю что тупанул xD.
Оказывается надо было просто убрать элементы с null так как они сами подставятся в таблице из за значения по умолчанию.
Ага)
Ничего не получилось.
Прочитал много раз уроки 21 и 22.
Повторил все из них код.
Работает только обновление.
Инесерт не получилось, никак. Даже копирование готовых решений из коментариев ничего не дало.
Какой url должен быть и что он должен в итоге вывести?!
Привет. А при чем тут урл?
ActiveRecordEntity.php
ArticlesController.php
В модели Article.php добавил нужные сеттеры и геттеры
В роуте добавил
Вот смотрю на код и чувствую, что намудрил чего-то, такое чувство, что можно легче сделать
Если id не будет, то тут будет ошибка.
Не получается домашняя работа по инсерту.
Что не так?!
src/MyProject/Models/ActiveRecordEntity.php
ArticlesController.php
Article.php
routes.php
Не понимаю в чем ошибка, Получаю вардампом такой ответ:
array (size=4)
0 => string 'name = :param1' (length=14)
1 => string 'text = :param2' (length=14)
2 => string 'author_id = :param3' (length=19)
3 => string 'created_at = :param4' (length=20)
array (size=4)
':param1' => string ''Добавлени статья : название статьи'' (length=65)
':param2' => string ''Новый текст добавленной статьи'' (length=60)
':param3' => string ''1'' (length=3)
':param4' => string ''2021-01-11 01:38'' (length=18)
string 'INSERT INTO articles (name = :param1, text = :param2, author_id = :param3, created_at = :param4) VALUES ('Добавлени статья : название статьи', 'Новый текст добавленной статьи', '1', '2021-01-11 01:38');' (length=259)
array (size=4)
':param1' => string ''Добавлени статья : название статьи'' (length=65)
':param2' => string ''Новый текст добавленной статьи'' (length=60)
':param3' => string ''1'' (length=3)
':param4' => string ''2021-01-11 01:38'' (length=18)
А это разве корректный SQL-запрос? (Нет. Пройдите курс MySQL для начинающих)
Привет, Артём!
Курс я проходил до курса ооп пхп.
Снова перещел по ссылке и не нашел что-то по инсерту ничего.
Обратился в поисковик.
Подсмотрел некоторые решения домашнего задания других оучающихся.
В итоге, у меня появился осознанный, успешно проверенный метод insert.
ActiveRecordEntity.php
Сеттеры в модель я добавил еще в прошлый раз, Но обнаружил ошибку с функцией дата у меня в контроллере при вызове.
Понадеялся на память. В результатате тестирвоания успешно исправил.
ArticlesController.php
INSERT-ы в курсе рассматриваются здесь
для чего это всё?
Всегда используйте фигурные скобки для блоков if-else.
Комментарии с вардампами из домашки тоже следует убирать
Возникла путаница где должен быть insert, а где add метод.
Начинаю потихоньку разбираться/продвигаться Вашим ответам и других обучающихся в чате.
доброго времени суток, надеюсь, еще отвечаете здесь в комментариях (все-таки несколько лет прошло с момента создания курса).
вопрос следующий, вы посоветовали array_filter() для отсеивания пустых свойств, чтобы субд могла принять запрос и добавить новые данные. однако, изучая мануал (https://www.php.net/manual/ru/function.array-filter.php), я заметил в примере #2, что если не указать фильтрующую функцию, то помимо значения null, так же будут удалять значения: false, '0', 0. а ведь они вполне могут понадобиться в нашей бд.
есть ли другой, наиболее правильный способ или все-таки нужно сделать функцию по отсеиванию исключительно значений null?
Да, вы правы, надо передавать туда коллбэк, который будет отсеивать только null
ActiveRecordEnity
ArticlesController
Супер!
в 18 уроке, мы поменяли свойства моделей с private, на protected (ссылка на урок https://php.zone/oop-v-php-prodvinutyj-kurs/pattern-active-record-v-php). все было ок, работало, пока в комментариях здесь не прочитал, что вы просите сделать свойства private. если их сделать private, тогда в методе mapPropertiesToDbFormat() в строке:
$mappedProperties[$propertyNameAsUnderscore] = $this->$propertyName;
будет ошибка, потому что невозможно получить доступ к приватному свойству. если свойства protected, тогда все работает.я уже всю голову сломал, как правильно?
Правильно protected. Про private я пошутил.
ArticlesController.php
ActiveRecordEntity.php
Супер!