This is an outdated version of the Manual. Visit the NEW Manual

Internals

PDO types

RedBeanPHP is a weakly typed ORM. It accepts all kinds of types in beans; integers, strings, booleans and NULL values. After a bean has been retrieved from the database each property of the bean contains a value of one of the following types: string, NULL, array or RedBean_OODBBean (object). RedBeanPHP will never return long values, booleans or integers. In fact, most values are returned as a string, with the exception of NULL which remains NULL. Composite types are also preserved and are limited to arrays and RedBean_OODBBean objects (embedded beans).

Value conversion in PDO binding

RedBeanPHP tries to convert data types by itself to preserve information. It's very important that you understand how RedBeanPHP deals with data types. If a value is numeric, the value will be bound to a prepared statement as an integer. However this is only the case if the integer representation is the same as a string representation. So while RedBeanPHP will bind 1900 as an integer, it will bind 007 as a string to preserve the padding zeros. Null values will be bound to statements using the NULL type. Also be careful with fractions. RedBean stores floats and doubles as doubles (bound as string). If you dont want this (to enable a higher level of data precision) I recommend to bypass RedBeanPHP and store these values yourself. Also consider using a proper Math library if working with high precision calculations.

Note that we talk here about PDO bindings, to set 007 in a bean property and preserve the zeros set the meta property: $agent->setMeta("cast.agentname","string"); -- where agentname is the property and $agent is the bean.

Objects

If you don't like static methods, you can use the objects behind the facade directly. Every method of the R-class is available through the original RedBeanPHP objects as well. The facade is just that: a thin layer on top of these objects. Here is an overview of the most important R-methods and how to use them 'the non-static way'.

Note that there are three important objects in RedBeanPHP: the adapter (RedBean_Adapter), the query writer (RedBean_QueryWriter) and the RedBeanPHP object database (RedBean_OODB). We call these objects the core objects, because together they represent the foundation on which RedBeanPHP has been built. Other objects need these core objects, that's why they are bundled in a toolbox (RedBean_ToolBox). So, if you need let's say an instance of the Tag Manager class (RedBean_TagManager) you'll have to pass an instance of the toolbox to the contructor.

Starting RedBeanPHP in Object Mode

To start RedBeanPHP in object mode you can use the RedBeanPHP Kickstarter.


    $toolbox 
RedBean_Setup::kickstart($dsn$user$pass$frozen);

This is how you obtain a toolbox. Yes, still static methods. If you really want to not use any static method at all, you can manually assemble your toolbox like this:


    $pdo 
= new RedBean_Driver_PDO($dsn);
    
$adapter = new RedBean_Adapter_DBAdapter($pdo);
    
$writer = new RedBean_QueryWriter_MySQL($adapter);
    
$oodb = new RedBean_OODB($writer);
    
$tb = new RedBean_ToolBox($oodb$adapter$writer);

The purpose of the Kickstarter becomes quite obvious now; if you do this manually you have to decide which driver to use (PDO or OCI) and which writer to use (MySQL, MariaDB, Postgres, CUBRID or SQLiteT). The Kickstarter acts as a factory, inferring the appropriate toolbox from your DSN.

Wiring

RedBeanPHP has a very decoupled architecture, which makes it very flexibile. However this means you need to introduce some objects to eachother. First we need to tell RedBeanPHP how beans can obtain the toolbox, this means we need to define our own BeanHelper:


    
class BeanHelper extends RedBean_BeanHelper_Facade {
            private 
$toolbox;
            public function 
getToolbox() {
                    return 
$this->toolbox;
            }
            public function 
setToolbox($toolbox) {
                    
$this->toolbox $toolbox;
            }
    }

Now let's do the wiring:


    $r 
$tb->getRedBean();
    
    
//A helper for OODB to give to its beans
    
$b = new BeanHelper;
    
$b->setToolbox($tb);
    
$r->setBeanHelper($b);
    
    
//allow OODB to associate beans
    
$r->setAssociationManager(new RedBean_AssociationManager($tb));
    
    
//enable FUSE
    
$h = new RedBean_ModelHelper;
    
$h->attachEventListeners($r);

Normally the facade does all this dull work for you. You can also let the facade do this work and still work with instances; simply steal the toolbox from the facade after it has been configured:


    R
::setup(...);
    
$toolbox R::$toolbox//give it to me!

Creating a service object

Many methods in the R-facade are just wrappers around calls to methods on one of these core objects: OODB, Writer and Adapter. However many static methods in R also call so-called service objects. Service objects offer secondary functionality. To instantiate a service object you need to pass the toolbox to its constructor. The toolbox contains the tools a service object needs to operate: the adapter to connect to the database, the OODB object to call basic ORM methods and the writer to write queries for the database.

Let's consider an example. Let's say we want to use a function like R::find() to find a bean, but we want to use objects rather than static methods. How do we accomplish this ?
First, we glance at the table to discover we need to have an instance of the Finder to use this method. Finder is a service object, specialized in well,... finding stuff!


    $f 
= new RedBean_Finder($tb);

That's it. Now we have an instance of the Finder service object. Now to find a bean use:


    $x 
$f->find('music'' composer = ? ''Bach');

Now $x contains all compositions by Bach. Like the result of R::find(), $x contains a collection of beans. Unlike R::find() we had to build the service object ourselves.

Conversion table

Here is a kind of conversion table to look up R-methods and find the corresponding methods on objects behind the facade.

R::method() Class and Method Description
R::dispense RedBean_OODB : dispense Dispense a bean
R::load RedBean_OODB : load Load a bean
R::store RedBean_OODB : store Store a bean
R::trash RedBean_OODB : trash Delete a bean
R::find RedBean_Finder : find Finds a bean
R::exec RedBean_Adapter_DBAdapter[1] : execExecutes SQL
R::getAll RedBean_Adapter_DBAdapter[1] : getQuery the database
R::dup RedBean_DuplicationManager : setFilters, dupDuplicate a bean
R::exportAll RedBean_DuplicationManager : exportAllExport beans
R::associate RedBean_AssociationManager[2] : associateAssociate two beans
R::tag RedBean_TagManager : tagTag a bean
R::related RedBean_AssociationManager : relatedSimpleRetrieve related beans
R::commit RedBean_Adapter_DBAdapter[3] : commitCommits transaction
R::begin RedBean_Adapter_DBAdapter[3] : startTransactionBegins transaction
R::rollback RedBean_Adapter_DBAdapter[3] : rollbackRolls back a transaction
R::nuke RedBean_QueryWriter[4] : wipeAllDestroys database
R::dependenciesRedBean_OODB : setDepListSets dependent beans
R::getColumns RedBean_QueryWriter : getColumnsList columns of a table
R::genSlots RedBean_SQLHelper[5] : genSlotsGenerates slots
R::freeze RedBean_OODB : freezeFreezes the schema
1In fluid mode the facade suppresses table/column not found exceptions.
2If you pass a base bean (3rd param) facade will use RedBean_AssociationManager_ExtAssociationManager.
3Facade ignores these calls in fluid mode (to avoid exceptions in some DB systems).
4Be careful, Facade ignores this method in Frozen mode!
5SQLHelper constructor requires only the Adapter, not the entire toolbox.

Note that R::dup() first sets filters (if any) and then calls the dup() method on the Duplication Manager service object.

Facade-only methods

While most Facade methods are also available in instances, there are some exceptions. First there are some batch methods like StoreAll, trashAll, dispenseAll these are just loops around store() and trash() but they are only available in the facade. Similarly, R::transaction is just a wrapper around the transaction methods (commit,begin and rollback). Some methods just deal with the facade itself: configureFacadeWithToolbox(), addDatabase(), selectDatabase() - these methods occur only in the facade of course. Then there is R::inspect, this is just a wrapper around $writer->getColumns and $writer->getTables. Finally there the loadMulti method is a facade-only method because it's actually just a loop around R::load.

Why static methods in the first place?

The purpose of RedBeanPHP is to boost productivity and maintainability. Static methods have certain advantages: they are short (no need to instantiate a class) and always available (no need to pass them around). This is great for developers in a dynamic environment (like me).

Plugins

In RedBeanPHP ORM, plugins serve a dual purpose. First they provide additional functionality. Second they keep the core clean.

A plugin is simply an additional PHP file residing in the /plugin folder. For your convenience, all plugins discussed here are included in the all-in-one package.

Since 3.3: Plugins can define additional static methods to be included in the R-facade class. This can be done by adding a line of code after the @plugin directive in the plugin source file.

For more information on how to build a custom all-in-one package please consult the manual page about the build script: Replica.

Dynamic Plugins (3.5+)

As of RedBeanPHP 3.5 you can dynamically add new methods to the R facade (only works in PHP 5.3 and higher).


    
//Install the tea plugin    
    
R::ext'makeTea', function($flavour) {
        return 
"Tea: {$flavour}";
    } );
    
    
//Make some tea
    
echo R::makeTea('Earl Grey');

 
 

RedBeanPHP Easy ORM for PHP © 2024 Gabor de Mooij and the RedBeanPHP community - Licensed New BSD/GPLv2