RedBeanPHP был создан для значительного облегчения жизни программистов в процессе работы с базами данных. RedBeanPHP требует версию PHP >= 5.3.4. Под капотом используется драйвер PDO, поэтому защита от SQL- инъекций при правильном применении гарантированна. К поддерживаемым СУБД RedBeanPHP относятся MySQL, MariaDB, PostgreSQL, SQLite, CUBRID.
ORM это способ задания связи объектов и РСУБД. Всего есть 2 модели ORM-систем: Data Mapper и Active Record. Так вот RedBeanPHP это Data Mapper и каждый объект записи здесь называется бином. Эти бины можно воспринимать как самые обычные объекты, свойства которых представляют собой записи в Ваших таблицах. То есть одна запись это один бин, а его свойства это поля Вашей записи. Работать с бином можно точно также как с обычным массивом.
Скачать библиотеку RedBeanPHP можно на официальном сайте.
Подключить библиотеку можно через функцию require:
require 'libs/rb.php';
Для подключения к базе данных в RedBeanPHP есть статичный метод setup, который принимает 4 опциональных аргумента. Опциональными они являются, потому что Вы можете никакой аргумент не задать и тогда RedBeanPHP создаст временную базу данных в формате SQLite в Вашей временной директории. Вызывается метод setup для MySQL следующим образом:
R::setup( 'mysql:host=127.0.0.1;dbname=redbean','login', 'password' ); if ( !R::testConnection() ) { exit ('Нет соединения с базой данных'); }
Метод testConnection проверяет есть ли у нас фактическое подключение к базе.
Подробнее о подключении к базам данных можно прочесть в разделе Connection.
Закрыть соединение с базой данных Вы можете при помощи метода close. Вызывается он вот так:
R::close();
Какой в RedBeanPHP есть аналог функции mysqli_query? Этим аналогом является метод exec. У него всего 2 аргумента: sql и bindings. Бинды (bindings) – это специальная техника подготовленных запросов, при помощи которых можно обезопасить себя от SQL-инъекций. Также бинды увеличивают производительность при частых запросах. Вызывается метод exec следующим образом:
Пример #1
Вторым элементом мы передаем массив с данными, которые будут подставлены вместо знака ? (плэйсхолдер). В данном случае это id.
$id = $_POST['id']; R::exec('DELETE FROM `users` WHERE `id` = ?', array( $id ));
Пример #2
Плэйсхолдеров может быть много. В этом случае в качестве первого знака ? будет вставлена первая ячейка массива, то есть цифра 32. В качества второго ? слева на право будет вставлена цифра 51. В качестве последнего ? будет вставлена цифра 73.
R::exec('DELETE FROM `users` WHERE `id` = ? OR `id` = ? OR `id` = ?', array( 32, 51, 73 ));
Пример #3
Если Вы уже работали с PDO, то возможно будет привычней использовать следующий подход:
$id = $_POST['id']; R::exec('DELETE FROM `users` WHERE `id` = :id', array( ':id' => $id ));
Пример #4
R::exec( 'UPDATE `page` SET `title`="test" WHERE `id` = 1' );
Метод dispense принимает всего 1 аргумент – название таблицы. RedBeanPHP умеет создавать таблицы налету. Достаточно вызвать dispense и указать какие поля будут у таблицы. После этого мы вызываем метод store и передаем в него бин user.
Пример #1
$user = R::dispense('users'); //передаем название таблицы users //поле id можно не создавать, так как RedBeanPHP автоматически его создает с автоинкрементом $user->login = $data['login']; $user->email = $data['email']; R::store($user); // сохраняем объект $user в таблице
Пример #2
$user = R::dispense('users'); $user->name = 'Alex'; $user->age = 35; R::store($user);
Для чтения данных есть множество методов, например, метод load. Первым параметром мы передаем имя таблицы, из которой мы хотим прочесть данные. Второй параметр – id записи, которую мы хотим получить. С полученными данными мы можем работать, как с объектом или массивом.
$cat = R::load('category', 2); echo $cat->title; // работаем с данными, как с объектом echo $cat['title']; // работаем с данными, как с массивом
Чтобы изменить запись в БД её нужно:
1 - получить в виде объекта;
2 – написать новое значение;
3 – сохранить через метод store.
$cat = R::load('category', 2); $cat->title = "Новое значение"; R::store($cat); echo $cat->title; // выводим наше новое значение
Чтобы удалить запись из БД мы её должны:
1 - получить в виде объекта;
2 – использовать метод trash, который удалит одну запись. Есть ещё метод trashAll, который может удалить сразу несколько объектов.
$cat = R::load('category', 2); R::trash($cat); //удаляем запись с id=2 из таблицы category
R::wipe('category'); // удаляем все записи из таблицы category
Режим заморозки в RedBeanPHP нужен для того, чтобы включить или выключить поведение автоматического создания и изменения таблиц в БД. Сервер сильно нагружается, поэтому, когда Вы разрабатываете сайт, то режим заморозки можно выключить (false). Тогда автоматическое создание таблиц будет работать. Когда Вы зальете готовый сайт на хостинг, то нужно поставить режим заморозки в значение true.
R::setup(); // тут подключение к БД R::freeze( true ); // тут выключение режима заморозки
Статья была написана на основе видеоуроков Хауди Хо, который Вы можете посмотреть ниже.
2:00 Проверяем/Меняем версию PHP
6:10 Качаем/Подключаем RedBeanPHP
8:40 Подключаемся к базе данных R::setup()
9:50 В чём разница между utf8_general_ci и utf8mb4_general_ci
11:45 Почему нужно прописывать IP в качестве хоста базы данных
14:45 Закрытие соединения с базой данных R::close()
15:10 Проверяем соединение с базой данных R::testConnection()
16:00 Выполняем произвольный SQL код R::exec()
20:20 Что такое CRUD
21:00 Создание записей R::dispense()
27:50 О режиме заморозки R::freeze()
30:45 Конвенция именования таблиц
32:20 Пишем обход конвенций именования таблиц R::ext()
34:00 Конвенция именования свойств бина
34:40 Конвенция автосоздания индексов
37:20 Загружаем записи R::load()
41:00 Загружаем сразу несколько записей R::loadAll()
42:30 Поиск записей R::find()
44:20 Генерируем бинд слоты R::genSlots()
46:40 Ищем только одну запись R::findOne()
47:25 Загружаем все записи сразу R::findAll()
48:10 Итерация по всем записям R::findCollection()
49:40 Ищем записи по значениям R::findLike()
51:30 Загружаем запись если есть, создаем и загружаем если нет R::findOrCreate()
53:15 Считаем количество записей R::count()
54:35 Обновляем данные в записях
59:00 Удаляем записи из таблиц
1:00:18 Вайпаем данные таблиц (очищаем таблицы) R::wipe()
1:33 Почему нельзя копировать вообще весь код из урока
2:45 Метод R::getAll()
6:09 Метод R::getRow()
10:45 Метод R::getCol()
15:00 Методы R::convertToBean() и R::convertToBeans(), перекидываем массивы в бины
16:44 Метод R::getInsertID()
19:42 Что такое отношения вообще?
23:45 Отношения One-to-Many (1:M)
40:06 Отношения Many-to-One (M:1)
44:35 Отношения One-to-X (One-to-Fixed)
53:30 Отношения Many-to-Many (M2M)
57:40 Сортировка отношений
59:55 Фильтрация отношений
1:02:55 Добавляем отношения без их подгрузки
1:04:30 Подсчёт отношений/связей
— указать кодировку при подключении к базе
— проверить кодировку файла
— указать кодировку в htaccess
— указать кодировку в скрипте
а под конец еще и iconv все кодировать
Запутался я в корень… Поставил себе задачу, что из таблицы «clients» мне нужно получить все поля «name», которые там есть и внести из значения в веб-таблицу. При условии, что ID записей и их количество в базе данных я не знаю.
Такой вариант мне не подходит, так как здесь нужно выбрать определенные значения ID:
$cllients = R::load('clients', 2); echo $clients->name;
Я решил попробовать вариант такой:
$clients = R::findAll('clients'); print_r ($clients);
Но так я вывел массив.
Мне кажется, что можно как-то решить мою проблему с помощью loadAll. Но в таком случае я не могу понять, как обозначить тот факт, что id неизвестны. Например, в видео у Хауди Хо id именно перечисляются. А мое условие в том, что я не знаю, сколько записей, сколько id, но хочу получить все name.
Может быть сможете подсказать, в какую сторону надо смотреть?
$clients = R::findAll('client'); foreach ($clients as $client) { echo $client['name']; }
В общем, сделал я с помощью findAll и foreach выборку нужных мне значений в веб-таблицу. И возле каждой строки этой таблицы я сделал ссылку на редактирование оной, вида
href="edit.php?id=<?php echo $clients['id']; ?>"
По моим представлениям, это должна быть страница, на которой выводятся все остальные данные из таблицы «clients» (которые не вошли в веб-таблицу), и это должна быть также страницей редактирования (формы там всякие и так далее).
И вот, в чем загвоздка: я не понимаю, как по умолчанию при переходе на эту страницу объяснить базе данных, что сюда нужно выгружать данные только из определенного id таблицы. То есть вот я перешел по ссылке edit.php?id=6, значит тут все должно быть связано только с id=6 и никак иначе. А у меня там либо выгрузка со всех id, либо с определенного, но которое я указываю вручную((
А я хочу как-то так:
$clients = R::load('clients',id=тот_же_что_и_в_url); echo $clients['name']; //имя нужного клиента echo $clients['balance']; //баланс клиента и так далее
Но никак — тупик…$id = $_GET['id']; $clients = R::load('clients',$id);
Но на сколько это правильно в плане безопасности?
З.Ы.: я очень извиняюсь, что просто заполонил собой комменты, но почему-то как сюда напишу с вопросом, сразу какие-то решения приходят в голову))) Хотя до этого по несколько часов мог голову ломать.
Я так понимаю, — всё получилось?
Данная конструкция выглядит безопасно, на мой скромный взгляд. Собственно используя RedBean PHP можно сильно не переживать о безопасности, данная библиотека самостоятельно обрабатывает переменные. Поэтому она такая удобная. Главное всё делать, как в документации.
Я бы ещё на всякий случай (int) поставил.
Вот так:
$id = (int) $_GET['id']; $clients = R::load('clients',$id);
Если писать комменты помогает, то отлично! Единственное, что я из-за работы могу ответить не сразу, а через 1-2 дня. А решения всегда так, не сразу приходят, приходится поломать голову какое-то время.
Спасибо большое, добавил еще и (int) — лишним не будет точно))
Да, все получилось. Я для себя осознал одно (в свои уже 33 года!) — не зря в школе учителя говорили, что математика пригодится! Самое сложное в программировании (по крайней мере для меня), как я для себя понял, это выстроить нужный алгоритм действий, как оно все должно работать и взаимодействовать, логика. А вот когда это все в голове выстраивается, то написать код худо-бедно уже не так сложно. А в выстраивании алгоритмов очень бы пригодилась математика, так как там все это развивается на «ура»))
А что касается комментов, видимо мне в трудной ситуации очень удобно выразить все письменно, перечитать это и осознать, куда надо смотреть, выстроить алгоритм действий. Видимо мысли так укладываются более удобно)))
И по итогу оказывается, что мои тормоза заключаются именно в слабом понимании логики построения кода и получения данных (почему именно так, а не иначе; откуда взять те или иные данные, чтобы работать с ними; откуда взять нужные значения; почему нужно это прописать именно тут, а не там), отсюда и тупик. Но как только я все это осознаю, то написать сам код уже не проблема. Благо, что много мануалов и таких замечательных блогов, как Ваш, Алексей, где все очень подробно разжевывается.
Ну, и еще я понял, что надо учить параллельно английский — столько мануалов есть на нем…
Знал бы я, что мне в 33 года приспичит написать достаточно сложное веб-приложение и это меня так увлечет, выбор будущей специальности был бы однозначен. А так, гуманитарий я)))
Ох, опять многобукв… Простите))
В общем, спасибо большое Вам за подсказки, помощь и за отличный блог!)
Не прощаюсь!)))
З.Ы.: Прекрасно понимаю, что быстро отвечать Вы не можете — все же есть масса нужных дел, помимо этого. Но я, когда задаю вопрос, всегда уверен, что завис на нем надолго, поэтому готов ждать ответа столько, сколько нужно)) Просто почему-то пока получается так, что перечитав я понимаю — вот же он ответ, на самой поверхности!
Указанный метод в видео добавляет новую запись в бд. Можно узнать как-то без добавления?
Спасибо
Прошу помощи! Не могу понять, в чем моя ошибка?
Таблица такая: yadi.sk/i/-891uZ4ynTUzDw yadi.sk/i/EGEU2Z3b1XpFcg
Делаю запрос по старинке и при помощи RedBeanPHP — два разных результата. почему ReBeanPHP отдает только один пин?
<?php
require_once 'sys/db.php';
function dump($what)
{echo ' ';}
$db1 = mysqli_connect('localhost', 'test', 'root', '');
mysqli_set_charset($db1, 'utf8');
$q1 = $db1->query(«SELECT * FROM `pins` WHERE `direction` = 'output' ORDER BY `pin` ASC»);
dump($q1);
$db = R::findAll('pins', 'direction = ?', [«output»]);
dump($db);
?>
Возврат:
1. mysqli_result Object
(
[current_field] => 0
[field_count] => 4
[lengths] =>
[num_rows] => 7
[type] => 0
)
2. Array
(
[] => RedBeanPHP\OODBBean Object
(
[properties:protected] => Array
(
[pin] => 26
[name] => Предпоследний
[direction] => output
[status] => 1
)
[__info:protected] => Array
(
[type] => pins
[sys.id] => id
[sys.orig] => Array
(
[pin] => 26
[name] => Предпоследний
[direction] => output
[status] => 1
)
[tainted] =>
[changed] =>
)
[beanHelper:protected] => RedBeanPHP\BeanHelper\SimpleFacadeBeanHelper Object
(
)
[fetchType:protected] =>
[withSql:protected] =>
[withParams:protected] => Array
(
)
[aliasName:protected] =>
[via:protected] =>
[noLoad:protected] =>
[all:protected] =>
)
)
Меня смущает вот это:
$db1 = mysqli_connect('localhost', 'test', 'root', '');
Для соединения с БД в RedBeanPHP используется метод setup. И работая с RedBeanPHP любые mysqli функции не используются.
Либо RedBeanPHP, либо mysqli, но не одновременно.
R::setup( 'mysql:host=127.0.0.1;dbname=test','root', '' );
Вопрос в другом, почему в таблице 27 записей, а редбин возвращает только одну, даже если сделать запрос всех записей: $db = R::find('pins'); => возвращает только одну запись(последнюю)
Пишет, что ReadBean уже отправил заголовки.
Вызывался только метод setup().
Есть ли решение данной проблемы?
Подскажите, пожалуйста, по возможности.
Использую метод dispense для добавления данных.
Запрос имеет следующий вид:
$user = R::dispense('users_list'); $user->login = $data['login']; $user->email = $data['email']; $result = R::store($user);
Но при выполнении запроса получаю исключение:Invalid type: users_list
Если не ошибаюсь, то вроде бы нужно вносить какие то правки в настройки RBPHP для того, чтобы он принимал название таблиц в которых используется нижнее подчеркивание.