
In this post we will discuss a very interesting ORM framework
RedBeanPHP . It is remarkable, above all, the ability to create a database structure on the fly. In addition, the framework is easy to use as a penny. My story will be divided into 3 parts.
In the second part, the main topic will be the models. In the third - change the logic of the framework.
Before writing a post, I took the trouble and made a
test application with 15,000 entries, in order to be convinced in my experience of the possibility of incredibly easy work. After all, I probably am not the only one who prescribes the fields in several places with a terrible awareness of the meaninglessness of this work, especially at the initial stage of development. Finally, an analogue of Entity Framework Code First from .NET appeared, which at one time made me wildly delighted. So in order.
Origins
This miracle is written by a man with the equally wonderful name Gabor. Gabor is a failed student who has studied cognitive psychology. The failure happened because of the banal lack of demand for these specialists, but still ready to admit that Gabor is a very good psychologist. Using the framework does not leave me feeling simple and obvious what is happening.
Start
To connect you need to add only one file, which contains all the code.
')
require('rb.php');
Quite simply, isn't it? Let's look inside and find that the data file weighs 260 kilobytes and is a version of the framework assembled from a variety of files. On GitHub, you can download a regular version of about 40 files. In this case, you need the following code to connect:
require('redbean.inc.php');
Structure
The framework has a well-organized class structure. The structure includes drivers for PDO and Oracle. This means that RedBeanPHP supports a wide range of databases. The documentation indicates support for the following databases: MySQL 5, SQLite, PostgreSQL, CUBRID, Oracle. Support for the latter is not included in rb.php, it must be downloaded from GitHub separately. But no one bothers us to write our own driver, inheriting from the class RedBean_Driver.
And in order to modify the internal logic of the framework, you need to create your own version of QueryWriter. I will discuss this topic in detail in the third part of the review.
The framework supports Plugins, and has a simple Logger class for displaying all framework requests to the base on the screen. I did not find an entry in the file, but I don’t have any problems inheriting my own class.
Here is the code of the logger coming in the delivery:
class RedBean_Logger_Default implements RedBean_Logger { public function log() { if (func_num_args() > 0) { foreach (func_get_args() as $argument) { if (is_array($argument)) echo print_r($argument,true); else echo $argument; echo "<br>\n"; } } } }
All files are well documented using PHPDocs. Hints in the IDE work fine, with the exception of the object fields associated with the table columns.
Using
To connect, you must specify the PDO format string:
R::setup('mysql:host=localhost;dbname=mydatabase', 'user','password');
An example of creating a new record and a new table in the event of its absence (only in fluid mode):
And so the existing “bean” is loaded.
$book = R::load('book', $id);
The author calls bean'mi objects (bin - English bean plants) containing data. This object is not a model and has the goal of simply storing data and working with records in the database. How to associate a model containing business logic with them will be described in the second part of the review.
The framework decides whether to create or update a record by the presence of the id field of the object. How to change this logic, I will show in the third part.
The search for a bean occurs by specifying the WHERE expression:
$needles = R::find('needle', ' haystack = :haystack ORDER BY :sortorder', array( ':sortorder'=>$sortorder, ':haystack'=>$haystack ) );
In the same place, in the second parameter, you can specify the ORDER BY and LIMIT constructs.
Connections
Working with a relational database implies connectivity between tables. RedBeanPHP supports all necessary types of links. To create a one-to-many relationship, we use the property with the prefix own.
A table will be created in the database. The village_id field will be added to the building table, indicating the id field of the village table. It will also create a link in the parent table and create the necessary indexes. The link will have a cascade update and delete property.
If you look at the other side of the connection, it is possible to refer to the parent object as follows:
$village = $mill->village
RedBeanPHP supports the concept of “lazy loading”. That is, the loading of related data will occur at the moment of accessing the object field.
Own field is an associative array, so we can replace a separate object:
$village->ownBuilding[$id] = $house;
To remove the connection between the objects, you must call the following code (the objects themselves will not be deleted):
unset($village->ownBuilding[$someID]); R::store($village);
To remove the bean and its associated parent objects:
R::trash( $book );
To clear the table:
R::wipe( 'book' );
To create a many-to-many relationship, use the property with the prefix shared.
$army = R::dispense('army'); $village->sharedArmy[] = $army; $village2->sharedArmy[] = $army;
As a result, an additional table army_village will be created and links and indices will be created. The rest of the work with shared lists is similar to the own list.
Typically, the type of a bean is indicated by the name of an object field.
But sometimes it is necessary to assign bean to fields of an object not following this rule.
list($teacher,$student) = R::dispense('person',2); $project->student = $student; $project->teacher = $teacher;
When saving, the framework is guided by the type of bean specified in dispence, and both child objects will be saved in the person table, and the student_id and teacher_id fields will be created in the project table.
In this case, when sampling a bean from the database, a non-unambiguous situation can occur, since the framework cannot determine which type is in the $ project-> student and $ project-> teacher fields. In this case, the type is specified by calling fetchAs:
$teacher = $project->fetchAs('person')->teacher;
Trees
The framework supports one-to-many, many-to-many ring links.
For example, creating a category tree:
The parent_id field and the necessary links and indexes will be created in the table.
Speed ​​performance
Freymfork has 2 modes of operation: fluide and frozen. In fluide mode of the RedBeanPHP, it will take care of the structure of your table itself, sacrificing speed. After development is complete, you can increase performance by translating the framework with the frozen mode:
R::freeze( true );
Requests to the database
ORM supports SQL queries.
R::exec( 'update page set title="test" where id=1' );
The query builder is also present:
R::$f->begin() ->select('*')->from('bean') ->where(' field1 = ? ')->put('a')->get('row');
Overview of models
I'll run a little bit in the second part and describe how the model is created in RedBeanPHP.
At the beginning you work with bean, without attracting models. When you need a model, you create a class of the form Model_BeanName, for example Model_User, and there you describe additional logic. The bean and model are linked automatically.
$user = R::dispence('user'); $user->modelMethod();
That is, we start with ActiveRecord and, if necessary, expand to models. The author calls this approach FUSE (English fusion).
In the second part, we will continue to talk about the functions of the framework for daily work:
- Models
- Transactions
- and other topics
In the third part we will discuss additional features of the RedBeanPHP:
- Debugging
- Server for Javascript application.
- Plugins
- A practical example of changing internal logic
- and other topics
Resources
RedBeanPHP official website