DAO

The DAO class is responsible for loading and persistence operations on models :

Connecting to the database

Check that the database connection parameters are correctly entered in the configuration file:

Ubiquity config -f=database

Since 2.3.0 release

Database startup with DAO::startDatabase($config) in services.php file is useless, no need to start the database, the connection is made automatically at the first request. Use DAO::start() in app/config/services.php file when using several databases (with multi db feature)

Loading data

Loading an instance

Loading an instance of the models\User class with id 5

use Ubiquity\orm\DAO;

$user=DAO::getById(models\User::class, 5);

Loading an instance using a condition:

use Ubiquity\orm\DAO;

DAO::getOne(models\User::class, 'name= ?',false,['DOE']);

BelongsTo loading

By default, members defined by a belongsTo relationship are automatically loaded

Each user belongs to only one category:

$user=DAO::getById(models\User::class,5);
echo $user->getCategory()->getName();

It is possible to prevent this default loading ; the third parameter allows the loading or not of belongsTo members:

$user=DAO::getOne(models\User::class,5, false);
echo $user->getCategory();// NULL

HasMany loading

Loading hasMany members must always be explicit ; the third parameter allows the explicit loading of members.

Each user has many groups:

$user=DAO::getOne(models\User::class,5,['groupes']);
foreach($user->getGroupes() as $groupe){
    echo $groupe->getName().'<br>';
}

Composite primary key

Either the ProductDetail model corresponding to a product ordered on a command and whose primary key is composite:

app/models/ProductDetail.php
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
 namespace models;
 class ProductDetail{
     /**
      * @id
     */
     private $idProduct;

     /**
      * @id
     */
     private $idCommand;

     ...
 }

The second parameter $keyValues can be an array if the primary key is composite:

$productDetail=DAO::getOne(models\ProductDetail::class,[18,'BF327']);
echo 'Command:'.$productDetail->getCommande().'<br>';
echo 'Product:'.$productDetail->getProduct().'<br>';

Loading multiple objects

Loading instances of the User class:

$users=DAO::getAll(models\User::class);
foreach($users as $user){
    echo $user->getName()."<br>";
}

Querying using conditions

Simple queries

The condition parameter is equivalent to the WHERE part of an SQL statement:

$users=DAO::getAll(User::class,'firstName like "bren%" and not suspended',false);

To avoid SQL injections and benefit from the preparation of statements, it is preferable to perform a parameterized query:

$users=DAO::getAll(User::class,'firstName like ? and suspended= ?',false,['bren%',false]);

UQueries

The use of U-queries allows to set conditions on associate members:

Selection of users whose organization has the domain lecnam.net:

$users=DAO::uGetAll(User::class,'organization.domain= ?',false,['lecnam.net']);

It is possible to view the generated request in the logs (if logging is enabled):

../_images/uquery-users-log.png

The result can be verified by selecting all users in this organization:

$organization=DAO::getOne(Organization::class,'domain= ?',['users'],['lecnam.net']);
$users=$organization->getUsers();

The corresponding logs:

../_images/uquery-users-orga-log.png

Modifying data

Adding an instance

Adding an organization:

$orga=new Organization();
$orga->setName('Foo');
$orga->setDomain('foo.net');
if(DAO::save($orga)){
    echo $orga.' added in database';
}

Adding an instance of User, in an organization:

$orga=DAO::getById(Organization::class, 1);
$user=new User();
$user->setFirstname('DOE');
$user->setLastname('John');
$user->setEmail('doe@bar.net');
$user->setOrganization($orga);
if(DAO::save($user)){
    echo $user.' added in database in '.$orga;
}

Updating an instance

First, the instance must be loaded:

$orga=DAO::getOne(Organization::class,'domain= ?',false,['foo.net']);
$orga->setAliases('foo.org');
if(DAO::save($orga)){
    echo $orga.' updated in database';
}

Deleting an instance

If the instance is loaded from database:

$orga=DAO::getOne(Organization::class,5,false);
if(DAO::remove($orga)){
    echo $orga.' deleted from database';
}

If the instance is not loaded, it is more appropriate to use the delete method:

if(DAO::delete(Organization::class,5)){
    echo 'Organization deleted from database';
}

Deleting multiple instances

Deletion of multiple instances without prior loading:

if($res=DAO::deleteAll(models\User::class, 'id in (?,?,?)',[1,2,3])){
    echo "$res elements deleted";
}

Bulk queries

Bulk queries allow several operations (insertion, modification or deletion) to be performed in a single query, which contributes to improved performance.

Bulk inserts

Insertions example:

$u = new User();
$u->setName('Martin1');
DAO::toInsert($u);
$u = new User();
$u->setName('Martin2');
DAO::toInsert($u);
//Perform inserts
DAO::flushInserts();

Bulk updates

Updates example:

$users = DAO::getAll(User::class, 'name like ?', false, [
     'Martin%'
]);
foreach ($users as $user) {
     $user->setName(\strtoupper($user->getName()));
     DAO::toUpdate($user);
}
DAO::flushUpdates();

Bulk deletes

Deletions example

$users = DAO::getAll(User::class, 'name like ?', false, [
     'BULK%'
]);
DAO::toDeletes($users);
DAO::flushDeletes();

The DAO::flush() method can be called if insertions, updates or deletions are pending.

SDAO class

The SDAO class accelerates CRUD operations for the business classes without relationships.

Models must in this case declare public members only, and not respect the usual encapsulation.

app/models/Product.php
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
 namespace models;
 class Product{
     /**
      * @id
     */
     public $id;

     public $name;

     ...
 }

The SDAO class inherits from DAO and has the same methods for performing CRUD operations.

use Ubiquity\orm\DAO;

$product=DAO::getById(models\Product::class, 5);

Prepared DAO queries

Preparing certain requests can improve performance with Swoole, Workerman or Roadrunner servers.
This preparation initializes the objects that will then be used to execute the query.
This initialization is done at server startup, or at the startup of each worker, if such an event exists.

Swoole sample

Preparation

app/config/swooleServices.php
$swooleServer->on('workerStart', function ($srv) use (&$config) {
     \Ubiquity\orm\DAO::startDatabase($config);
     \Ubiquity\orm\DAO::prepareGetById('user', models\User::class);
     \Ubiquity\orm\DAO::prepareGetAll('productsByName', models\Product::class,'name like ?');
});

Usage

app/controllers/UsersController.php
public function displayUser($idUser){
     $user=DAO::executePrepared('user',[1]);
     echo $user->getName();
}

public function displayProducts($name){
     $products=DAO::executePrepared('productsByName',[$name]);
     ...
}