Small Orm Swoft : Redis connector

From small iceberg
Jump to navigation Jump to search

Small orm come now with a redis connector

For now, it is only implemented in Swoft package.

Configuring a connection[edit]

The connector use for now the native connector of Swoft, then almost all parameters are useless.

Here is an example config/sebk_small_orm.php

<?php
return [
    'bundlesBasePath' => __DIR__ . '/../app/Model/',
    'connections' => [
        "redis" => [
            'type' => 'swoft-redis',
            'host' => 'useless',
            'database' => 'useless',
            'encoding' => 'useless',
            'user' => 'useless',
            'password' => 'useless',
            'tryCreateDatabase' => false,
        ]
    ],
    'bundles' => [
        'TestBundle' => [
            'connections' => [
                'redis' => [
                    'dao_namespace' => 'App\Model\TestBundle\Dao',
                    'model_namespace' => 'App\Model\TestBundle\Model',
                    'validator_namespace' => 'App\Model\TestBundle\Validator',
                ],
            ],
        ],
    ],
];

The useless parameters are required.

DAO[edit]

The DAO are declared in the same way as mysql DAO, except that they extends 'AbstractRedisDao' abstract class :

<?php

namespace App\Model\TestBundle\Dao;

use Sebk\SmallOrmCore\Dao\AbstractRedisDao;
use Sebk\SmallOrmCore\Dao\Field;

class Test extends AbstractRedisDao
{

    protected function build()
    {
        $this->setDbTableName("app:test")
            ->setModelName("Test")
            ->addField("id", "id", null, Field::TYPE_INT)
            ->addField("libelle", "libelle")
        ;
    }

}

Model[edit]

The models are defined exactly as same way that mysql model :

<?php

namespace App\Model\TestBundle\Model;

use Sebk\SmallOrmCore\Dao\Model;

/**
 * @method getId()
 * @method setId($value)
 * @method getLibelle()
 * @method setLibelle($value)
 */
class Test extends Model
{
    public function onLoad()
    {
        $this->setLoaded(true);
    }

    public function beforeSave()
    {
        $this->setKey($this->getId());
        $this->setBeforeSave(true);
    }

    public function afterSave()
    {
        $this->setAfterSave(true);
    }

    public function beforeDelete()
    {
        $this->setBeforeDelete(true);
    }

    public function afterDelete()
    {
        $this->setAfterDelete(true);
    }
}

Note the 'setKey' call in 'beforeSave' method. It is no required but using this method will be helpfull (see 'persist' section).

Query[edit]

The redis connection come with a specific QueryBuilder class.

You can invoke it in the same way as mysql version :

        /** @var App\Model\TestBundle\Dao\Test $testDao */
        $testDao = bean('sebk_small_orm_dao')->get("TestBundle", "Test");

        $query = $testDao->createQueryBuilder();

Get models[edit]

The 'get' method allow you query redis database :

        /** @var App\Model\TestBundle\Dao\Test $testDao */
        $testDao = bean('sebk_small_orm_dao')->get("TestBundle", "Test");

        $query = $testDao->createQueryBuilder()
                     ->get(1)
        ;
        $model = $testDao->getResult($query)[0];

This request will get 'app:test:1' value in redis database and load the 'Test' model in $model.

You can do multiple requests in one query (The connector will use 'mget' redis instruction instead of 'get' instruction) :

        /** @var App\Model\TestBundle\Dao\Test $testDao */
        $testDao = bean('sebk_small_orm_dao')->get("TestBundle", "Test");

        $query = $testDao->createQueryBuilder()
                     ->get(1)
                     ->get(2)
                     ->get(3)
        ;
        $models = $testDao->getResult($query)[0];

This example will load the 3 corresponding models in an array in $models.

Note that on load, a 'key' field corresponding to redis key is added to the model.

Save model[edit]

The 'set' method allow you to save a model in redis database. As the 'get' method, you can chain the set instructions :

        /** @var App\Model\TestBundle\Dao\Test $testDao */
        $testDao = bean('sebk_small_orm_dao')->get("TestBundle", "Test");

        /** @var \App\Model\TestBundle\Model\Test $test */
        $test = $testDao->newModel();
        $test->setId(6);
        $test->setLibelle("ceci est un test mset");

        /** @var \App\Model\TestBundle\Model\Test $test2 */
        $test2 = $testDao->newModel();
        $test2->setId(7);
        $test2->setLibelle("ceci est un test mset 2");

        $query = $testDao->createQueryBuilder()
            ->set($test->getId(), $test)
            ->set($test2->getId(), $test2)
        ;

        $testDao->getResult($query);

The 'set' method take two parameters :

  • First one is the redis key
  • The second one is the model to save

Delete a model[edit]

Same principle for deleting a model, you can use the 'del' method :

        /** @var App\Model\TestBundle\Dao\Test $testDao */
        $testDao = bean('sebk_small_orm_dao')->get("TestBundle", "Test");

        $query = $testDao->createQueryBuilder()
                     ->del(1)
                     ->del(2)
                     ->del(3)
        ;
        $testDao->getResult($query);

This code will delete the following redis keys :

  • 'app:test:1'
  • 'app:test:2'
  • 'app:test:3'

Persist a model[edit]

You can persist a model with the shortcut method 'persist' on any model :

        /** @var App\Model\TestBundle\Dao\Test $testDao */
        $testDao = bean('sebk_small_orm_dao')->get("TestBundle", "Test");

        $query = $testDao->createQueryBuilder()
                     ->get(1)
        ;
        $model->setLibelle('Changed label');
        $model->persist();

Note that to persist a model, you must set the key field.

A load the key is automatically set but for new models, you must assign the key :

        /** @var App\Model\TestBundle\Dao\Test $testDao */
        $testDao = bean('sebk_small_orm_dao')->get("TestBundle", "Test");

        /** @var \App\Model\TestBundle\Model\Test $test */
        $test = $testDao->newModel();
        $test->setId(6);
        $test->setLibelle("ceci est un test mset");
      
        // Persist new model
        $test->setKey(6);
        $test->persist();

A good shortcut to do that, when you have link between a field and key, is to use the beforeSave method to assign key as in section "model".

This is also a good method to systematize a rule to generate key :

<?php

namespace App\Model\TestBundle\Model;

use Sebk\SmallOrmCore\Dao\Model;

/**
 * @method getId()
 * @method setId($value)
 * @method getLibelle()
 * @method setLibelle($value)
 */
class Test extends Model
{
    public function beforeSave()
    {
        $this->setKey($this->getCustomerId() . "_" . $this->getOrderId);
    }
}

Find shortcuts[edit]

The 'findOneBy' and 'findBy' are also available in DAO. Instead of using an array to specify search criteria, you can use directly keys :

        /** @var App\Model\TestBundle\Dao\Test $testDao */
        $testDao = bean('sebk_small_orm_dao')->get("TestBundle", "Test");

        $models = $testDao->FindBy(1); // return the model of key 'app:test:1' in an array
        $models = $testDao->findBy([1, 2]); // return the models of keys 'app:test:1 and 'app:test:2' in an array
        $model = $testDao->findOneBy(2); // return the model of key 'app:test:2'

loadToOne and loadToMany[edit]

The loadToOne and loadToMany methods of DAO are available and cross connection. You can load a mysql DAO from a Redis DAO with the same syntax

Here is an example in a redis DAO :

<?php

namespace App\Model\TestBundle\Dao;

use Sebk\SmallOrmCore\Dao\AbstractRedisDao;
use Sebk\SmallOrmCore\Dao\Field;

class TestPay extends AbstractRedisDao
{

    protected function build()
    {
        $this->setDbTableName("app:test-pay")
            ->setModelName("TestPay")
            ->addField("customerId", "customerId, null, Field::TYPE_INT)
            ->addField("amount", "amount", null, Field::TYPE_FLOAT)

            ->addToOne("customer", ["customerId" => "customerId"], "Customer", "MysqlBundle")
        ;
    }

}

And now we can load the mysql model with loadToOne :

        /** @var TestPay $testPayDao */
        $testPayDao = $this->daoFactory->get("TestBundle", "TestPay");

        /** @var TestPay $testPay */
        $testPay = $testPayDao->newModel();
        $testPay->setCustomerId(1583385);
        $testPay->setAmount(18.5);

        $testPay->loadToOne("customer");

        return JsonResponse($testPay);