Введение в Redbean
Когда дело доходит до RAD и прототипирования, существует множество инструментов, помогающих быстро запускать проекты. От быстрого запуска до микро-фреймворков, от инструментов сборки, таких как Composer, до установщиков в один клик и, конечно же, ORM — есть все способы ускорить время разработки. Я собираюсь взглянуть на Redbean , ORM с разницей, которая идеально подходит для прототипирования.
Введите Redbean
Redbean — это ORM (Object Relational Mapper), но он делает больше, чем просто — он создает и изменяет базовую схему на лету. Традиционно вы использовали бы ORM в качестве оболочки для заранее запланированной, уже существующей схемы базы данных. Это хорошо для большинства проектов, но когда вы создаете прототипы — или придумываете их по ходу дела! — сделать это для вас за кулисами может ускорить процесс еще больше.
Когда вы создаете объект с помощью Redbean — или bean-компонента, чтобы использовать определенную терминологию — как только вы сохраняете его в базе данных, схема адаптируется к размеру. Это применимо, даже если вы пытаетесь сохранить объект без соответствующей таблицы!
Установка
Самый простой способ установить Redbean — это загрузить пакет «все в одном» . Затем вам просто требуется один файл, rb.php
.
Вы также можете установить его через Composer; однако автор библиотеки не рекомендует такой подход — подробности см. на странице установки .
Дозирование
Первый шаг при использовании Redbean — «распределить» боб, который в основном является объектом. Обратите внимание, что я буду использовать термин «bean» и взаимозаменяемо использовать объект до конца статьи.
Дозирование осуществляется с помощью статического метода всеобъемлющего класса Redbean « R
», который принимает тип в качестве аргумента.
Например:
$user = R::dispense('user');
Это создаст пустой объект для пользователя, которому вы можете назначить свойства. Вы также можете дозировать несколько одновременно, добавив желаемое число в качестве второго параметра:
$users = R::dispense('user', 10);
На данном этапе не имеет значения, есть ли в базе данных таблица для ее хранения; как только мы попытаемся это сохранить, Redbean позаботится об этом.
Давайте попробуем это — обратите внимание на использование статического метода store
, который используется для записи в базу данных:
$user->name = 'Joe Bloggs'; $user->email = '[email protected]'; $id = R::store($user); print $id;
В большинстве ORM можно ожидать, что это не удастся, если вы еще не создали таблицу для пользователей. Однако, используя Redbean это успешно, потому что он создает таблицу для вас. Если вы посмотрите на свою базу данных на этом этапе, вы должны увидеть следующую таблицу:
user ---- id int(11) UN PK AI name varchar(255) email varchar(255)
По необходимости соглашение об именах довольно строгое; это единственное строчное представление указанного вами типа.
Теперь давайте посмотрим, как меняется схема во время итерации. Для записи пользователя, скорее всего, понадобится поле пароля, но мы забыли его создать.
Если вы делаете это:
$user->password = 'secret'; R::store($user);
На этот раз Redbean знает, как сохранить пользователя, но есть новое поле, которое таблица базы данных не может вместить. Неважно — он просто добавляет один, и ваша таблица теперь будет выглядеть так:
user ---- id int(11) UN PK AI name varchar(255) email varchar(255) password varchar(255)
Типы данных поля
Redbean пытается угадать тип данных поля на основе информации, которую вы предоставляете. Так что, если вы сделали это:
$user->age = 30; R::store($user);
Вы обнаружите, что поле возраста было создано в виде крошечного целого числа.
Если тип поля окажется недостаточным позже, Redbean просто изменяет его на лету. Если вы попытаетесь присвоить возрасту 3000, столбец изменится на обычное целое число. Если вы произнесете имя как «тридцать», оно будет изменено на varchar. Задайте для поля varchar значение, превышающее 255 символов, и оно станет полем TEXT и т. Д.
В поисках бобов
Вы можете загрузить определенный объект по первичному ключу, используя load
:
$user = R::load('user', 1);
Вы можете загрузить несколько объектов одновременно (по первичному ключу), используя batch
метод:
$users = R::batch('user', array(1, 2, 3));
Это возвращает массив бинов.
Вы также можете найти бины с помощью SQL. Второй аргумент метода find
— это, по сути, SQL, начиная с WHERE
, за исключением самого ключевого слова WHERE
. Например, чтобы найти пользователей, которым еще нет двадцати:
$users = R::find('user', 'age < ?', array(20) );
Обратите внимание, что мы связываем параметры, поэтому массив является третьим аргументом. Это возвращает массив бинов, используя их идентификаторы в качестве ключей.
Вы можете добавить больше предложений к вашему SQL, например:
$users = R::find('user', 'age < ? ORDER BY age ASC', array(20) );
Counting
Вы можете узнать количество записей, используя метод подсчета:
$number_of_users = R::count('user');
Удаление
Чтобы удалить один компонент, используйте trash
:
R::trash($user);
Чтобы удалить больше определенного типа, используйте trashAll
:
R::trashAll('user');
Чтобы удалить все компоненты определенного типа, используйте wipe
:
R::wipe('user');
Или, чтобы уничтожить все — что может быть полезно при nuke
прототипа — вы nuke
его на вооружение:
R::nuke();
связи
Как и в любом ORM, отношения между объектами поддерживаются.
Отношения «один ко многим» относятся к использованию концепции «владения» связанными объектами. Например, если заказы имеют одного пользователя, говорят, что этот пользователь «владеет» этими заказами. Используя определенное имя переменной, мы можем построить эту связь следующим образом:
$orders = R::dispense('order', 2); $orders[0]->order_id = '000001'; R::store($orders[0]); $orders[1]->order_id = '000002'; R::store($orders[0]); $user->ownOrders = $orders; R::store($user);
Ключевым элементом здесь является свойство ownOrders
. Если вы сейчас осмотрите свою базу данных, то обнаружите, что Redbean добавил поле user_id
в таблицу заказов вместе с соответствующим внешним ключом.
Пользователь, которому «принадлежит» заказ, может быть просто доступен как свойство, например:
$user = $order->user; print 'This order belongs to ' . $user->name;
Чтобы продемонстрировать отношения «многие ко многим», давайте создадим несколько ролей:
$roles = R::dispense('role', 3); $roles[0]->name = 'member'; R::store($roles[0]); $roles[1]->name = 'admin'; R::store($roles[1]); $roles[2]->name = 'super_admin'; R::store($roles[2]);
Роли принадлежат не только отдельным пользователям; они являются общими. Таким образом, чтобы назначить первые две роли пользователю и при этом построить отношения в базе данных, мы можем сделать это:
$roles = R::batch('user', array(1,2)); $user->sharedRole = $roles; R::store($user);
На этот раз вы должны найти новую таблицу под названием role_user
, которая определяет это отношение как «многие ко многим».
Вы можете получить роли, принадлежащие пользователю, прочитав свойство:
$roles = $user->sharedRole;
Это лениво загружает роли при первом обращении к ним.
В отношениях есть еще много чего, в том числе возможность добавлять свойства в отношение с помощью ссылки, фильтрация по ссылке, активная загрузка и т. Д. — см. Подробную информацию в документации .
модели
Вы можете создавать модели, соответствующие типам бинов, просто следуя определенным соглашениям. Затем модели подключаются к bean-компонентам с помощью FUSE; например, следуя соответствующему соглашению об именах, они объединяются.
Соглашение простое; разделите «Модель» и тип с подчеркиванием, например, Model_Type
. Так, например, чтобы создать модель для пользователей, вы просто делаете это:
class Model_User extends RedBean_SimpleModel { }
После того, как вы определили модель, вы можете реализовать несколько методов, которые будут вызываться в разные моменты жизненного цикла компонента. Это показано в таблице ниже, которая отображает операции CRUD на «ловушки», которые вы можете реализовать:
R::store $model->update() R::store $model->after_update() R::load $model->open() R::trash $model->delete() R::trash $model->after_delete() R::dispense $model->dispense()
Так, например, вы можете добавить проверку, реализовав update()
:
class Model_User extends RedBean_SimpleModel { public function update() { if (strlen($this->password) < 8) { throw new Exception('Password must be at least 8 characters long'); } } }
Конечно, вы также можете создавать свои собственные методы, а также пользовательские GETters.
Запрос к базе данных
Вы можете выполнить необработанный запрос SQL следующим образом:
R::exec('UPDATE user SET status = 1');
Вы можете вернуть многомерный массив строк следующим образом:
R::getAll('SELECT * FROM user');
Кроме того, вы можете использовать привязку параметров:
R::getAll('SELECT * FROM user WHERE status = :status', array(':status' => 1) );
Вы можете получить один столбец следующим образом:
R::getCol('SELECT email FROM user');
Вы также можете получить ассоциативный массив, используя два столбца таблицы следующим образом:
R::$adapter->getAssoc('SELECT id, email FROM user');
Развертывание вашего приложения
Хотя он, возможно, лучше всего подходит для создания прототипов — или, по крайней мере, для разработки — нет никаких причин, по которым вы не можете продолжать использовать Redbean в производстве, если выполняете определенные шаги.
Механизм Redbean для обновления схемы на лету называется «жидким режимом»; однако это не подходит для производства и имеет довольно существенное снижение производительности. Однако вы можете отключить его, «заморозив»:
R::freeze( true );
Приступая к производству, вы захотите выполнить еще несколько шагов:
- просмотреть типы данных столбца
- рассмотреть внешние ключи и отношения
- проверить индексы — Redbean создает несколько — и изменить соответствующим образом
Резюме
В этой статье я представил Redbean как удобный способ начать процесс разработки, позволяя вам поэкспериментировать с моделями доменов, не беспокоясь о создании базовой схемы. Будет ли он жизнеспособным для производства, еще неизвестно — но для прототипирования и быстрых итераций это отличный маленький инструмент. Я многое еще не рассказал, поэтому обязательно ознакомьтесь с документацией .