Introduction to Redbean

Share this article

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.

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.

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!

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.

You can also install it via Composer; however, the author of the library does not recommend this approach – see the installation page for details .

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.

Dispensing is done via a static method of the overarching Redbean class, “R”, which takes the type as an argument.

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.

Let’s try this – note the use of the static method store, which is used to write to the database:

$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:

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:

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:

$user->age = 30;
R::store($user);

You’ll find that the age field has been created as a tiny integer.

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.

Finding Beans

You can load a specific object by primary key using load:

$user = R::load('user', 1);

You can load several objects at a time (by primary key) by using the batch method:

$users = R::batch('user', array(1, 2, 3));

This returns an array of beans.

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:

$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.

You can add more clauses to your SQL, for example:

$users = R::find('user', 'age < ? ORDER BY age ASC',
    array(20)
);

Counting

You can find out the number of records using the count method:

$number_of_users = R::count('user');

Deleting

To remove a single bean, use trash:

R::trash($user);

To remove more of a particular type, use trashAll:

R::trashAll('user');

To delete all beans of a particular type, use wipe:

R::wipe('user');

Or, to wipe out everything – which can be useful while prototyping – you nuke it:

R::nuke();

Relations

As with any ORM, relationships between objects are supported.

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.

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.

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.

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:

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:

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():

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.

Querying the Database

You can execute a raw SQL query like this:

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’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:

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

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.

Frequently Asked Questions (FAQs) about RedBeanPHP

What are the key features of RedBeanPHP?

RedBeanPHP is a simple, lightweight Object Relational Mapping (ORM) tool that offers a range of features designed to simplify database interactions. It is known for its “zero-config” approach, meaning it requires minimal setup and configuration. It automatically builds your database schema based on the objects you create, and it can adjust the schema as needed when your objects change. RedBeanPHP also supports fluid and frozen modes, allowing you to switch between development and production environments easily. It includes built-in tree structures and supports bean canning and dispensing for easy storage and retrieval of objects.

How does RedBeanPHP compare to other ORM tools?

Compared to other ORM tools, RedBeanPHP stands out for its simplicity and ease of use. It requires no configuration files, no SQL, and no model classes. This makes it a great choice for beginners or for projects where a full-featured ORM would be overkill. However, it still offers powerful features like automatic schema modification and tree structures, making it versatile enough for more complex projects as well.

How do I install and set up RedBeanPHP?

RedBeanPHP can be installed via Composer, a popular dependency management tool for PHP. Once installed, you can set up RedBeanPHP by including the RedBeanPHP file in your script and setting up a database connection. RedBeanPHP will automatically create and modify tables as needed based on your objects.

What is the “fluid mode” in RedBeanPHP?

Fluid mode is a feature of RedBeanPHP that allows it to automatically adjust your database schema as your objects change. This can be a huge time-saver during development, as you don’t have to manually modify your database every time you make a change to your objects. However, it’s recommended to switch to “frozen mode” in production for performance and security reasons.

How does RedBeanPHP handle relationships between objects?

RedBeanPHP supports several types of relationships between objects, including one-to-one, one-to-many, and many-to-many. These relationships are handled through the use of “beans”, which are simple objects that represent rows in a database table. You can easily associate beans with each other to represent relationships between objects.

Can I use RedBeanPHP with my existing database?

Yes, RedBeanPHP can be used with an existing database. However, it’s important to note that RedBeanPHP’s automatic schema modification features may make changes to your database structure, so it’s recommended to back up your database before using RedBeanPHP.

Is RedBeanPHP suitable for large, complex projects?

While RedBeanPHP is known for its simplicity and ease of use, it also offers powerful features that make it suitable for larger, more complex projects. Its automatic schema modification, support for various types of relationships, and built-in tree structures can all be valuable in a larger project. However, for very large or complex projects, a more full-featured ORM tool may be more appropriate.

How does RedBeanPHP handle security?

RedBeanPHP includes several features designed to enhance security. It uses prepared statements to help prevent SQL injection attacks, and it recommends using “frozen mode” in production to prevent unwanted schema changes. However, as with any tool, it’s important to follow best practices for security and to keep RedBeanPHP up to date.

What is “bean canning” in RedBeanPHP?

Bean canning is a feature of RedBeanPHP that allows you to store and retrieve entire sets of beans (objects) at once. This can be a convenient way to handle large amounts of data, and it can also help to improve performance by reducing the number of database queries.

Can I use RedBeanPHP without Composer?

While Composer is the recommended way to install RedBeanPHP, it’s also possible to download and include the RedBeanPHP file directly in your script. However, using Composer can make it easier to manage and update RedBeanPHP and any other dependencies your project may have.

Lukas WhiteLukas White
View Author

Lukas is a freelance web and mobile developer based in Manchester in the North of England. He's been developing in PHP since moving away from those early days in web development of using all manner of tools such as Java Server Pages, classic ASP and XML data islands, along with JavaScript - back when it really was JavaScript and Netscape ruled the roost. When he's not developing websites and mobile applications and complaining that this was all fields, Lukas likes to cook all manner of World foods.

Share this article
Read Next
7 Easy Ways to Make a Magento 2 Website Faster
7 Easy Ways to Make a Magento 2 Website Faster
Konstantin Gerasimov
Powerful React Form Builders to Consider in 2024
Powerful React Form Builders to Consider in 2024
Femi Akinyemi
Quick Tip: How to Animate Text Gradients and Patterns in CSS
Quick Tip: How to Animate Text Gradients and Patterns in CSS
Ralph Mason
Sending Email Using Node.js
Sending Email Using Node.js
Craig Buckler
Creating a Navbar in React
Creating a Navbar in React
Vidura Senevirathne
A Complete Guide to CSS Logical Properties, with Cheat Sheet
A Complete Guide to CSS Logical Properties, with Cheat Sheet
Ralph Mason
Using JSON Web Tokens with Node.js
Using JSON Web Tokens with Node.js
Lakindu Hewawasam
How to Build a Simple Web Server with Node.js
How to Build a Simple Web Server with Node.js
Chameera Dulanga
Building a Digital Fortress: How to Strengthen DNS Against DDoS Attacks?
Building a Digital Fortress: How to Strengthen DNS Against DDoS Attacks?
Beloslava Petrova
Crafting Interactive Scatter Plots with Plotly
Crafting Interactive Scatter Plots with Plotly
Binara Prabhanga
GenAI: How to Reduce Cost with Prompt Compression Techniques
GenAI: How to Reduce Cost with Prompt Compression Techniques
Suvoraj Biswas
How to Use jQuery’s ajax() Function for Asynchronous HTTP Requests
How to Use jQuery’s ajax() Function for Asynchronous HTTP Requests
Aurelio De RosaMaria Antonietta Perna
Quick Tip: How to Align Column Rows with CSS Subgrid
Quick Tip: How to Align Column Rows with CSS Subgrid
Ralph Mason
15 Top Web Design Tools & Resources To Try in 2024
15 Top Web Design Tools & Resources To Try in 2024
SitePoint Sponsors
7 Simple Rules for Better Data Visualization
7 Simple Rules for Better Data Visualization
Mariia Merkulova
Cloudways Autonomous: Fully-Managed Scalable WordPress Hosting
Cloudways Autonomous: Fully-Managed Scalable WordPress Hosting
SitePoint Team
Best Programming Language for AI
Best Programming Language for AI
Lucero del Alba
Quick Tip: How to Add Gradient Effects and Patterns to Text
Quick Tip: How to Add Gradient Effects and Patterns to Text
Ralph Mason
Logging Made Easy: A Beginner’s Guide to Winston in Node.js
Logging Made Easy: A Beginner’s Guide to Winston in Node.js
Vultr
How to Optimize Website Content for Featured Snippets
How to Optimize Website Content for Featured Snippets
Dipen Visavadiya
Psychology and UX: Decoding the Science Behind User Clicks
Psychology and UX: Decoding the Science Behind User Clicks
Tanya Kumari
Build a Full-stack App with Node.js and htmx
Build a Full-stack App with Node.js and htmx
James Hibbard
Digital Transformation with AI: The Benefits and Challenges
Digital Transformation with AI: The Benefits and Challenges
Priyanka Prajapat
Quick Tip: Creating a Date Picker in React
Quick Tip: Creating a Date Picker in React
Dianne Pena
How to Create Interactive Animations Using React Spring
How to Create Interactive Animations Using React Spring
Yemi Ojedapo
10 Reasons to Love Google Docs
10 Reasons to Love Google Docs
Joshua KrausZain Zaidi
How to Use Magento 2 for International Ecommerce Success
How to Use Magento 2 for International Ecommerce Success
Mitul Patel
5 Exciting New JavaScript Features in 2024
5 Exciting New JavaScript Features in 2024
Olivia GibsonDarren Jones
Tools and Strategies for Efficient Web Project Management
Tools and Strategies for Efficient Web Project Management
Juliet Ofoegbu
Choosing the Best WordPress CRM Plugin for Your Business
Choosing the Best WordPress CRM Plugin for Your Business
Neve Wilkinson
ChatGPT Plugins for Marketing Success
ChatGPT Plugins for Marketing Success
Neil Jordan
Managing Static Files in Django: A Comprehensive Guide
Managing Static Files in Django: A Comprehensive Guide
Kabaki Antony
The Ultimate Guide to Choosing the Best React Website Builder
The Ultimate Guide to Choosing the Best React Website Builder
Dianne Pena
Exploring the Creative Power of CSS Filters and Blending
Exploring the Creative Power of CSS Filters and Blending
Joan Ayebola
How to Use WebSockets in Node.js to Create Real-time Apps
How to Use WebSockets in Node.js to Create Real-time Apps
Craig Buckler
Best Node.js Framework Choices for Modern App Development
Best Node.js Framework Choices for Modern App Development
Dianne Pena
SaaS Boilerplates: What They Are, And 10 of the Best
SaaS Boilerplates: What They Are, And 10 of the Best
Zain Zaidi
Understanding Cookies and Sessions in React
Understanding Cookies and Sessions in React
Blessing Ene Anyebe
Enhanced Internationalization (i18n) in Next.js 14
Enhanced Internationalization (i18n) in Next.js 14
Emmanuel Onyeyaforo
Essential React Native Performance Tips and Tricks
Essential React Native Performance Tips and Tricks
Shaik Mukthahar
How to Use Server-sent Events in Node.js
How to Use Server-sent Events in Node.js
Craig Buckler
Five Simple Ways to Boost a WooCommerce Site’s Performance
Five Simple Ways to Boost a WooCommerce Site’s Performance
Palash Ghosh
Elevate Your Online Store with Top WooCommerce Plugins
Elevate Your Online Store with Top WooCommerce Plugins
Dianne Pena
Unleash Your Website’s Potential: Top 5 SEO Tools of 2024
Unleash Your Website’s Potential: Top 5 SEO Tools of 2024
Dianne Pena
How to Build a Chat Interface using Gradio & Vultr Cloud GPU
How to Build a Chat Interface using Gradio & Vultr Cloud GPU
Vultr
Enhance Your React Apps with ShadCn Utilities and Components
Enhance Your React Apps with ShadCn Utilities and Components
David Jaja
10 Best Create React App Alternatives for Different Use Cases
10 Best Create React App Alternatives for Different Use Cases
Zain Zaidi
Control Lazy Load, Infinite Scroll and Animations in React
Control Lazy Load, Infinite Scroll and Animations in React
Blessing Ene Anyebe
Building a Research Assistant Tool with AI and JavaScript
Building a Research Assistant Tool with AI and JavaScript
Mahmud Adeleye
Understanding React useEffect
Understanding React useEffect
Dianne Pena
Web Design Trends to Watch in 2024
Web Design Trends to Watch in 2024
Juliet Ofoegbu
Building a 3D Card Flip Animation with CSS Houdini
Building a 3D Card Flip Animation with CSS Houdini
Fred Zugs
How to Use ChatGPT in an Unavailable Country
How to Use ChatGPT in an Unavailable Country
Dianne Pena
An Introduction to Node.js Multithreading
An Introduction to Node.js Multithreading
Craig Buckler
How to Boost WordPress Security and Protect Your SEO Ranking
How to Boost WordPress Security and Protect Your SEO Ranking
Jaya Iyer
Understanding How ChatGPT Maintains Context
Understanding How ChatGPT Maintains Context
Dianne Pena
Building Interactive Data Visualizations with D3.js and React
Building Interactive Data Visualizations with D3.js and React
Oluwabusayo Jacobs
JavaScript vs Python: Which One Should You Learn First?
JavaScript vs Python: Which One Should You Learn First?
Olivia GibsonDarren Jones
13 Best Books, Courses and Communities for Learning React
13 Best Books, Courses and Communities for Learning React
Zain Zaidi
5 jQuery.each() Function Examples
5 jQuery.each() Function Examples
Florian RapplJames Hibbard
Implementing User Authentication in React Apps with Appwrite
Implementing User Authentication in React Apps with Appwrite
Yemi Ojedapo
AI-Powered Search Engine With Milvus Vector Database on Vultr
AI-Powered Search Engine With Milvus Vector Database on Vultr
Vultr
Understanding Signals in Django
Understanding Signals in Django
Kabaki Antony
Why React Icons May Be the Only Icon Library You Need
Why React Icons May Be the Only Icon Library You Need
Zain Zaidi
View Transitions in Astro
View Transitions in Astro
Tamas Piros
Getting Started with Content Collections in Astro
Getting Started with Content Collections in Astro
Tamas Piros
What Does the Java Virtual Machine Do All Day?
What Does the Java Virtual Machine Do All Day?
Peter Kessler
Become a Freelance Web Developer on Fiverr: Ultimate Guide
Become a Freelance Web Developer on Fiverr: Ultimate Guide
Mayank Singh
Layouts in Astro
Layouts in Astro
Tamas Piros
.NET 8: Blazor Render Modes Explained
.NET 8: Blazor Render Modes Explained
Peter De Tender
Mastering Node CSV
Mastering Node CSV
Dianne Pena
A Beginner’s Guide to SvelteKit
A Beginner’s Guide to SvelteKit
Erik KückelheimSimon Holthausen
Brighten Up Your Astro Site with KwesForms and Rive
Brighten Up Your Astro Site with KwesForms and Rive
Paul Scanlon
Which Programming Language Should I Learn First in 2024?
Which Programming Language Should I Learn First in 2024?
Joel Falconer
Managing PHP Versions with Laravel Herd
Managing PHP Versions with Laravel Herd
Dianne Pena
Accelerating the Cloud: The Final Steps
Accelerating the Cloud: The Final Steps
Dave Neary
An Alphebetized List of MIME Types
An Alphebetized List of MIME Types
Dianne Pena
The Best PHP Frameworks for 2024
The Best PHP Frameworks for 2024
Claudio Ribeiro
11 Best WordPress Themes for Developers & Designers in 2024
11 Best WordPress Themes for Developers & Designers in 2024
SitePoint Sponsors
Top 10 Best WordPress AI Plugins of 2024
Top 10 Best WordPress AI Plugins of 2024
Dianne Pena
20+ Tools for Node.js Development in 2024
20+ Tools for Node.js Development in 2024
Dianne Pena
The Best Figma Plugins to Enhance Your Design Workflow in 2024
The Best Figma Plugins to Enhance Your Design Workflow in 2024
Dianne Pena
Harnessing the Power of Zenserp for Advanced Search Engine Parsing
Harnessing the Power of Zenserp for Advanced Search Engine Parsing
Christopher Collins
Build Your Own AI Tools in Python Using the OpenAI API
Build Your Own AI Tools in Python Using the OpenAI API
Zain Zaidi
The Best React Chart Libraries for Data Visualization in 2024
The Best React Chart Libraries for Data Visualization in 2024
Dianne Pena
7 Free AI Logo Generators to Get Started
7 Free AI Logo Generators to Get Started
Zain Zaidi
Turn Your Vue App into an Offline-ready Progressive Web App
Turn Your Vue App into an Offline-ready Progressive Web App
Imran Alam
Clean Architecture: Theming with Tailwind and CSS Variables
Clean Architecture: Theming with Tailwind and CSS Variables
Emmanuel Onyeyaforo
How to Analyze Large Text Datasets with LangChain and Python
How to Analyze Large Text Datasets with LangChain and Python
Matt Nikonorov
6 Techniques for Conditional Rendering in React, with Examples
6 Techniques for Conditional Rendering in React, with Examples
Yemi Ojedapo
Introducing STRICH: Barcode Scanning for Web Apps
Introducing STRICH: Barcode Scanning for Web Apps
Alex Suzuki
Using Nodemon and Watch in Node.js for Live Restarts
Using Nodemon and Watch in Node.js for Live Restarts
Craig Buckler
Task Automation and Debugging with AI-Powered Tools
Task Automation and Debugging with AI-Powered Tools
Timi Omoyeni
Quick Tip: Understanding React Tooltip
Quick Tip: Understanding React Tooltip
Dianne Pena
12 Outstanding AI Tools that Enhance Efficiency & Productivity
12 Outstanding AI Tools that Enhance Efficiency & Productivity
Ilija Sekulov
React Performance Optimization
React Performance Optimization
Blessing Ene Anyebe
Introducing Chatbots and Large Language Models (LLMs)
Introducing Chatbots and Large Language Models (LLMs)
Timi Omoyeni
Migrate to Ampere on OCI with Heterogeneous Kubernetes Clusters
Migrate to Ampere on OCI with Heterogeneous Kubernetes Clusters
Ampere Computing
Scale Your React App with Storybook and Chromatic
Scale Your React App with Storybook and Chromatic
Daine Mawer
10 Tips for Implementing Webflow On-page SEO
10 Tips for Implementing Webflow On-page SEO
Milan Vracar
Get the freshest news and resources for developers, designers and digital creators in your inbox each week