Обновление в БД через Active Record

Обновление с помощью Active Record

В этом уроке мы научимся обновлять данные в базе данных в стиле объектно-ориентированного подхода. Для этого, как вы уже наверное догадались, мы будем использовать всё те же сущности ActiveRecord.

Давайте представим, что у нас есть объект класса Article, который был прочитан из базы данных, и который мы хотим изменить.

Давайте для изменения статей сделаем отдельный роут (^articles/(\d+)/edit$):

src/routes.php

Код доступен только после покупки курса ООП в PHP.

Теперь добавим в контроллере новый экшн edit, в котором мы пока просто будем получать статью и выводить её с помощью var_dump();

src/MyProject/Controllers/ArticlesController.php

Код доступен только после покупки курса ООП в PHP.

Перейдём по новому URL и убедимся, что все работает - http://myproject.loc/articles/1/edit

Вывод статей для редактирования

Теперь, предположим, что мы решили изменить этот объект. Давайте изменим у этого объекта свойства name и text (не забудьте добавить сеттеры для этих полей в классе Article):

src/MyProject/Controllers/ArticlesController.php

Код доступен только после покупки курса ООП в PHP.

Посмотрим на результат.
Новые свойства объекта

Как видим, свойства у объекта успешно были изменены. Но это никак не повлияло на его состояние в базе данных.

Данные в БД не изменились

И это логично, ведь мы после этого не выполнили запросов на обновление записи в базе. Давайте реализуем этот механизм.

Давайте создадим метод save() в классе ActiveRecordEntity, который будет сохранять текущее состояние обоъекта в базе.

Для того, чтобы обновить запись в базе данных, нам нужно выполнить запрос в MySQL:

Код доступен только после покупки курса ООП в PHP.

где во все поля подставить текущие значения у объекта.

Но ведь у разных наследников класса ActiveRecordEntity разные свойства. Вопрос – как их получить, не привязываясь к конкретному классу. Да с помощью рефлексии, которую мы изучили на прошлом занятии!

Алгоритм у нас будет такой:

  1. Получаем имена свойств объекта с помощью рефлексии, например, authorId
  2. Преобразовываем это значение из camelCase в строку_с_подчеркушками, например, author_id – именно так называется поле в базе данных
  3. Составляем результирующий запрос на обновление записи в базе данных.

Итак, давайте теперь сделаем это!
Для начала давайте напишем метод, который будет преобразовывать строки типа authorId в authorid.
Это можно сделать с помощью регулярного выражения: перед каждой заглавной буквой мы добавляем символ подчеркушки «
», а затем приводим все буквы к нижнему регистру:

src/MyProject/Models/ActiveRecordEntity.php

Код доступен только после покупки курса ООП в PHP.

Отлично, теперь давайте напишем метод, который прочитает все свойства объекта и создаст массив вида:

Код доступен только после покупки курса ООП в PHP.

src/MyProject/Models/ActiveRecordEntity.php

Код доступен только после покупки курса ООП в PHP.

Здесь мы получили все свойства, и затем каждое имяСвойства привели к имя_свойства. После чего в массив $mappedProperties мы стали добавлять элементы с ключами «имя_свойства» и со значениями этих свойств.

Давайте посмотрим, что у нас получилось. Выведем массив, полученный с помощью этого метода в методе save().

Код доступен только после покупки курса ООП в PHP.

Теперь вызовем этот метод сущности в контроллере:

src/MyProject/Controllers/ArticlesController.php

Код доступен только после покупки курса ООП в PHP.

Посмотрим на то, что этот код выдаёт.
Массив с именами колонок в БД

Отлично! Мы имеем структуру, которая соответствует структуре в базе данных. Теперь на её основе можно построить запрос!

Но перед этим нам стоит обратить внимание, что метод save() может быть вызван как у объекта, который уже есть в базе данных, так и у нового (если мы создали его с помощью new Article и заполнили ему свойства). Для первого нам нужно будет выполнить UPDATE-запрос, а для второго - INSERT-запрос. Как понять, с каким типом объекта мы работаем? Да всё проще простого – у объекта, которому соответствует запись в базе, свойство id не равно null, а если мы только создали объект, у него свойства id ещё нет.

Поэтому нам нужно разделить логику метода save() для этих двух случаев. Вот что у нас должно получиться:

src/MyProject/Models/ActiveRecordEntity.php

Код доступен только после покупки курса ООП в PHP.

В этом уроке мы напишем реализацию только одного метода – update(). Синтаксис запроса выглядит следующим образом:

Код доступен только после покупки курса ООП в PHP.

После этого нам нужно подставить в запрос параметры:

Код доступен только после покупки курса ООП в PHP.

У нас есть массив column1 = value1, column2 = value2. Всё что нам нужно – разделить его на 2 массива:

  1. будет содержать строки: column1 = :param1
  2. будет содержать ключ => значение вида: [:param1 => value1]
    и собрать из этих частей готовый запрос!

Чтобы было проще понимать, что происходит, будем делать это поэтапно. Для начала напишем код, который будет создавать два этих массива:

Код доступен только после покупки курса ООП в PHP.

После этого мы получим следующий результат:
Почти готовый запрос на UPDATE

Теперь дело за малым – сформировать запрос:

Код доступен только после покупки курса ООП в PHP.

Результат:
Сформированный запрос

Остаётся только выполнить этот запрос и передать нужные параметры!

Код доступен только после покупки курса ООП в PHP.

Сейчас этот скрипт ничего не выведет, но если мы зайдём в базу данных, мы обнаружим, что запись, соответствующая нашей статье – изменилась!
Обновленные данные в БД

Давайте теперь попробуем посмотреть нашу обновленную статью, перейдя по адресу http://myproject.loc/articles/1

Обновленная статья

Итак, в этом уроке мы создали универсальный метод, который позволит обновлять записи в бд для любых объектов, являющимися наследниками класса ActiveRecordEntity.