红豆戒色
Redbean简介 (An Introduction to Redbean)
When it comes to RAD and prototyping, there are lots of tools available to help get projects up-and-running quickly. From quick-starts to micro-frameworks, from build tools such as Composer to one-click installers, and of course ORMs – there are all sorts of ways to speed up development time. I'm going to look at Redbean, an ORM with a difference, which is ideal for prototyping.
当涉及RAD和原型制作时,有许多工具可以帮助您快速启动和运行项目。 从快速入门到微框架,从Composer等构建工具到一键式安装程序,当然还有ORM,都有各种各样的方法可以缩短开发时间。 我将看一看Redbean ,它是一个与众不同的ORM,它是原型制作的理想选择。
输入红豆 (Enter Redbean)
Redbean is an ORM (Object Relational Mapper), but it does more than that – it creates and modifies the underlying schema on-the-fly. Traditionally, you would use an ORM as a wrapper to a pre-planned, pre-existing database schema. That's fine for most projects, but when you're prototyping – or making it up as you go along! – having it done for you behind the scenes can speed things up even more.
Redbean是一个ORM(对象关系映射器),但它的作用还不止于此–它可以即时创建和修改基础架构。 传统上,您将使用ORM作为预先计划的,预先存在的数据库模式的包装。 这对于大多数项目都很好,但是当您进行原型制作时–或在进行过程中进行弥补! –在幕后为您完成操作可以进一步加快处理速度。
When you create an object with Redbean – or bean, to use the specific terminology – as soon as you save it to the database, the schema adapts itself to fit. This applies even if you're trying to save an object without a corresponding table!
当您使用Redbean(或bean,以使用特定术语)创建对象时,将其保存到数据库后,架构便会自动适应。 即使您尝试保存没有对应表的对象,这也适用!
安装 (Installation)
The easiest way to install Redbean is to download the all-in-one package. Then, you simply need to require the single file, rb.php
.
安装Redbean的最简单方法是下载多合一软件包 。 然后,您只需要一个文件rb.php
。
You can also install it via Composer; however, the author of the library does not recommend this approach – see the installation page for details .
您也可以通过Composer安装它; 但是,该库的作者不推荐这种方法-有关详细信息,请参见安装页面 。
点胶 (Dispensing)
The first step when using Redbean is to “dispense” a bean – which is basically an object. Note that I'll be using the term “bean” and object interchangeably throughout the rest of the post.
使用Redbean的第一步是“分配”一个bean,它基本上是一个对象。 请注意,在本文的其余部分中,我将互换使用术语“ bean”和对象。
Dispensing is done via a static method of the overarching Redbean class, “R
”, which takes the type as an argument.
分发是通过Redbean总体类“ R
”的静态方法完成的,该方法将类型作为参数。
For example:
例如:
$user = R::dispense('user');
This will create an empty object for a user, to which you can then assign properties. You can also dispense several at the same time by adding the number you want as a second parameter:
这将为用户创建一个空对象,然后您可以向其分配属性。 您还可以通过添加所需的数字作为第二个参数同时分配多个:
$users = R::dispense('user', 10);
It doesn't matter at this stage whether there's a table in the database to hold it; as soon as we try and store it, Redbean will take care of that.
在此阶段,数据库中是否有可以容纳它的表并不重要。 只要我们尝试将其存储,Redbean就会处理。
Let's try this – note the use of the static method store
, which is used to write to the database:
让我们尝试一下–注意使用静态方法store
,该方法用于写入数据库:
$user->name = 'Joe Bloggs';
$user->email = 'joe.bloggs@example.com';
$id = R::store($user);
print $id;
In most ORM's, you'd expect this to fail if you haven't yet created a table to hold users. However, using Redbean this succeeds because it creates the table for you. If you take a look in your database at this stage, you should see a table like this:
在大多数ORM中,如果您尚未创建用于容纳用户的表,则可能会失败。 但是,使用Redbean会成功,因为它会为您创建表。 如果您在此阶段查看数据库,则应该看到如下表:
user
----
id int(11) UN PK AI
name varchar(255)
email varchar(255)
By necessity, the naming convention is pretty strict; it's a singular, lower-case representation of the type you specified.
根据需要,命名约定非常严格。 它是您指定类型的单数形式,小写形式。
Now let's look at how the schema changes as we iterate. A user record will likely need a password field – but we forgot to create one.
现在,让我们看看模式在迭代时如何变化。 用户记录可能需要一个密码字段,但我们忘记了创建一个。
If you do this:
如果您这样做:
$user->password = 'secret';
R::store($user);
This time, Redbean knows how to store a user but there's a new field that the database table can't accommodate. No matter – it simply adds one, and your table will now look like this:
这次,Redbean知道如何存储用户,但是数据库表不能容纳一个新字段。 没关系–只需添加一个,您的表现在将如下所示:
user
----
id int(11) UN PK AI
name varchar(255)
email varchar(255)
password varchar(255)
现场数据类型 (Field Data Types)
Redbean tries to guess the data type of a field based on the information you provide. So if you did this:
Redbean尝试根据您提供的信息猜测字段的数据类型。 因此,如果您这样做:
$user->age = 30;
R::store($user);
You'll find that the age field has been created as a tiny integer.
您会发现age字段已创建为一个很小的整数。
If a field type doesn't prove sufficient later, Redbean simply alters it on-the-fly. If you tried to assign 3000 to the age now, the column would be changed to a normal integer. If you spelt out the name as “thirty”, it would be changed to a varchar. Set a varchar field to something greater than 255 characters and it becomes a TEXT field, and so on.
如果以后不能证明某个字段类型足够用,Redbean会即时对其进行更改。 如果您现在尝试为年龄分配3000,则该列将更改为普通整数。 如果将名称拼写为“三十”,它将被更改为varchar。 将varchar字段设置为大于255个字符的字段,它将变为TEXT字段,依此类推。
寻找豆子 (Finding Beans)
You can load a specific object by primary key using load
:
您可以使用load
通过主键load
特定对象:
$user = R::load('user', 1);
You can load several objects at a time (by primary key) by using the batch
method:
您可以使用batch
方法一次(通过主键)加载多个对象:
$users = R::batch('user', array(1, 2, 3));
This returns an array of beans.
这将返回一个bean数组。
You can also find beans using SQL. The second argument to the find
method is essentially SQL from the WHERE
clause onwards, excluding the WHERE
keyword itself. For example, to find users who aren't yet twenty:
您也可以使用SQL查找bean。 find
方法的第二个参数本质上是从WHERE
子句开始SQL,不包括WHERE
关键字本身。 例如,要查找还不到二十岁的用户:
$users = R::find('user', 'age < ?',
array(20)
);
Note that we're binding the parameters, hence the array as the third argument. This returns an array of beans using their ID's as keys.
请注意,我们要绑定参数,因此将数组作为第三个参数。 这将使用其ID作为键返回一个bean数组。
You can add more clauses to your SQL, for example:
您可以在SQL中添加更多子句,例如:
$users = R::find('user', 'age < ? ORDER BY age ASC',
array(20)
);
数数 (Counting)
You can find out the number of records using the count method:
您可以使用count方法找出记录数:
$number_of_users = R::count('user');
删除中 (Deleting)
To remove a single bean, use trash
:
要删除单个bean,请使用trash
:
R::trash($user);
To remove more of a particular type, use trashAll
:
要删除更多特定类型的文件,请使用trashAll
:
R::trashAll('user');
To delete all beans of a particular type, use wipe
:
要删除特定类型的所有bean,请使用wipe
:
R::wipe('user');
Or, to wipe out everything – which can be useful while prototyping – you nuke
it:
或者,要消灭一切-而其原型可能是有用的-你nuke
它:
R::nuke();
关系 (Relations)
As with any ORM, relationships between objects are supported.
与任何ORM一样,支持对象之间的关系。
One-to-many relations are referred to using the concept of “owning” related objects. For example if orders have a single user, that user is said to “own” those orders. By using a specific variable name, we can build that relationship like this:
一对多关系是使用“拥有”相关对象的概念来指代的。 例如,如果订单只有一个用户,则称该用户“拥有”这些订单。 通过使用特定的变量名,我们可以建立如下关系:
$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);
The key element here is the property ownOrders
. If you now inspect your database, you should find that Redbean has added the field user_id
to the order table, along with a corresponding foreign key.
这里的关键元素是属性ownOrders
。 如果现在检查数据库,则应该发现Redbean已将字段user_id
和相应的外键添加到订单表中。
The user that “owns” the order can simply be accessed as a property, e.g.:
“拥有”订单的用户可以简单地作为属性访问,例如:
$user = $order->user;
print 'This order belongs to ' . $user->name;
In order to demonstrate many-to-many relationships, let's create some roles:
为了演示多对多关系,让我们创建一些角色:
$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 don't just belong to individual users; they are shared. So to assign the first two roles to a user, and in doing so build the relationship in the database, we can do this:
角色不仅仅属于个人用户; 他们是共享的。 因此,要为用户分配前两个角色,并在数据库中建立关系,我们可以这样做:
$roles = R::batch('user', array(1,2));
$user->sharedRole = $roles;
R::store($user);
This time, you should find a new table called role_user
, which defines this relationship as a many-to-many.
这次,您应该找到一个名为role_user
的新表,该表将这种关系定义为多对多。
You can get the roles belonging to a user by reading the property:
您可以通过读取属性来获得属于用户的角色:
$roles = $user->sharedRole;
This lazy-loads the roles the first time they're accessed.
这会在第一次访问角色时延迟加载它们。
There's a lot more to relationships, including the ability to add properties to the relation using link, filtering by link, eager loading, and so on – check out the documentation for details.
关系还有很多,包括使用链接向关系中添加属性,按链接过滤,急切加载等的能力–请查看文档以了解详细信息。
楷模 (Models)
You can create models to correspond to bean types simply by following naming certain conventions. Models are then connected to beans using FUSE; as in, by following the relevant naming convention they are FUSEd together.
您只需遵循某些约定即可创建与bean类型相对应的模型。 然后使用FUSE将模型连接到bean。 例如,按照相关的命名约定将它们融合在一起。
The convention is simple; separate “Model” and the type with an underscore, e.g. Model_Type
. So for example, to create a model for users, you simply do this:
约定很简单; 用下划线分隔“ Model”和类型,例如Model_Type
。 因此,例如,要为用户创建模型,只需执行以下操作:
class Model_User extends RedBean_SimpleModel { }
Once you've defined a model, there are a number of methods you can implement which will get called at different points in the bean's lifecycle. This is illustrated in the table below, which maps the CRUD operations to the “hooks” you can implement:
定义模型后,您可以实现许多方法,这些方法将在Bean生命周期的不同点被调用。 下表对此进行了说明,该表将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()
So, for example, you could add validation by implementing update()
:
因此,例如,您可以通过实现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');
}
}
}
You can also create your own methods, of course, as well as custom GETters.
当然,您还可以创建自己的方法以及自定义GETter。
查询数据库 (Querying the Database)
You can execute a raw SQL query like this:
您可以像这样执行原始SQL查询:
R::exec('UPDATE user SET status = 1');
You can return a multidimensional array of rows like this:
您可以像这样返回多维的行数组:
R::getAll('SELECT * FROM user');
Additionally, you can use parameter binding:
此外,您可以使用参数绑定:
R::getAll('SELECT * FROM user WHERE status = :status',
array(':status' => 1)
);
You can fetch a single column like this:
您可以像这样获取单个列:
R::getCol('SELECT email FROM user');
You can also get an associative array using two columns of a table like so:
您还可以使用表的两列来获得关联数组,如下所示:
R::$adapter->getAssoc('SELECT id, email FROM user');
部署您的应用 (Deploying your Application)
Although it's arguably best suited for prototyping – or at least development – there's no reason you can't continue your use of Redbean into production, provided you follow certain steps.
尽管可以说它最适合原型设计或至少是开发,但只要您遵循某些步骤,就没有理由继续使用Redbean进行生产。
Redbean's mechanism for updating the schema on-the-fly is called “fluid mode”; however this isn't appropriate for production, and has a pretty significant performance overhead. However, you can turn it off by “freezing” it:
Redbean即时更新架构的机制称为“流体模式”; 但是,这不适用于生产,并且具有相当大的性能开销。 但是,您可以通过“冻结”它来关闭它:
R::freeze( true );
In going into production, you're going to want to follow a few more steps:
在投入生产时,您将需要执行以下一些步骤:
- review the column data types 查看列数据类型
- review the foreign keys and relations 审查外键和关系
- check the indexes – Redbean creates a few – and modify appropriately 检查索引-Redbean创建了一些-并进行了适当的修改
摘要 (Summary)
In this article, I've introduced Redbean as a handy way to kick-start your development process, by allowing you to play around with your domain models without worrying about building the underlying schema first. Whether it's viable for production remains to be seen – but for prototyping and rapid iterations, it's a great little tool. There's much I haven't covered, so be sure to check out the documentation.
在本文中,我介绍了Redbean,这是启动开发过程的便捷方法,它使您可以使用域模型,而不必担心首先构建基础架构。 对于生产是否可行尚待观察-但是对于原型设计和快速迭代,这是一个很棒的小工具。 我还没有介绍很多内容,因此请务必查看文档 。
红豆戒色