PHP code example of liqueurdetoile / cakephp-orm-json

1. Go to this page and download the library: Download liqueurdetoile/cakephp-orm-json library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

liqueurdetoile / cakephp-orm-json example snippets


\Lqdt\OrmJson\DatField\Compat3x::enable();


namespace App\Model\Table;

use Cake\ORM\Table;
use Lqdt\OrmJson\ORM\DatFieldAwareTrait;

class UsersTable extends Table {
  use DatFieldAwareTrait;

  // your model stuff
}


namespace App\Model\Table;

use Cake\ORM\Table;

class UsersTable extends Table
{
    public function initialize(array $config): void
    {
        $this->addBehavior('Lqdt/OrmJson.DatField');
    }
}

namespace App\Model\Entity;

use Cake\ORM\Entity;
use Lqdt\OrmJson\Model\Entity\DatFieldTrait;

class User extends Entity
{
    use DatFieldTrait;
}

// Assuming $table has DatFieldBehavior attached and its entity has DatFieldTrait attached
$customers = $table->find('json')
  // You can mix v1 and v2 syntax at will
  ->select(['id', 'attributes', 'name' => 'attributes->id.person.name'])
  ->where(['attributes->id.person.age >' => 40])
  ->order(['attributes->id.person.age'])
  ->all();

// Change the manager for all this customers
$customers = $table->patchEntities($customers, ['attributes->manager.id' => 153]);

// Update status
foreach ($customers as $customer) {
    $total = $customer->get('attributes->command.last.total');
    $stingy = $total < 50;
    $customer->set('attributes->status.stingy', $stingy);
    // You can also use array-like syntax
    $customer['attributes->status.vip'] = ($total > 500);
    // or curly syntax
    $customer->{'attributes->status.tobeCalled'} = !$stingy;
}

$table->saveMany($customers);

$e = $table->find()->select(['id', 'attributes->deep.nested.key'])->first();

/** Entity data will look like
* [
*   'id' => 0,
*   'attributes_deep_nested_key' => true
* ]
**/

$e = $table->find()->select(['id', 'key' => 'attributes->deep.nested.key'])->first();

/** Entity data will look like
* [
*   'id' => 0,
*   'key' => true,
* ]
**/

$e = $table->find()->select(['key' => 'attributes->deep.nested.key'])->enableAutoFields()->first();

/** Entity data will look like
* [
*   'id' => 0,
*   'key' => true,
*   'attributes' => [
*     'deep' => [
*       'nested' => [
*         'key' => true
*       ]
*     ]
*   ]
* ]
**/

// Simple search using v2 datfield notation
$data = $table->find()->where(['attributes->key' => 'key'])->first();
$data = $table->find()->where(['attributes->really.deep.number >=' => 10])->first();
$data = $table->find()->where(['attributes->key LIKE' => '%key%', 'attributes->really.deep.nested.key' => 'deep.nested.key'])->first();

// Looking for null will return all fields where key is missing or equals to null as default behavior
$data = $table->find()->where(['attributes->fool IS' => null])->first();

// Query builder is also fine
$data = $table
  ->find()
  ->where(function($exp) {
	   return $exp->between('attributes->lastkwown.position.lat', 2.257, 2.260);
   })
   ->first();

$q = $this->table->find();
$res = $q
  ->select(['kind' => 'data->group', 'total' => 'data->i + data->j', 'count' => $q->func()->count('*')])
  ->group('kind')
  ->having(['total >' => 10])
  ->distinct()
  ->all();

$e = $table->createEntity([
  'data->key' => 'foo',
  'data->really.deep.key' => 'not annoying'
]);

// $e will looks like
[
  'id' => null,
  'data' => [
    'key' => 'foo',
    'really' => [
      'deep' => [
        'key' => 'not annoying' // maybe yes if having to type array
      ]
    ]
  ]
]

// Keep our previously created entity and patch it
$e = $table->patchEntity(['data->hacked' => true);

// $e will looks like
[
  'id' => null,
  'data' => [
    'hacked' => true,
  ]
]

// Damnit, let's restore lost data
$e->jsonMerge();
// or
$table->jsonMerge($e);

// $e will now looks like
[
  'id' => null,
  'data' => [
    'hacked' => true, // Not anymore
    'key' => 'foo',
    'really' => [
      'deep' => [
        'key' => 'not annoying' // maybe yes if using arrays
      ]
    ]
  ]
]

// Next time, use option
$e = $table->patchEntity(['data->hacked' => true, ['jsonMerge' => true]);

$e->get('attributes->deep.nested.value');
$e->get('deep.nested.value@attributes'); // both notations are supported
$e['attributes->deep.nested.value'];
$e['attributes->deep.nested.value'];
$e->{'attributes->deep.nested.value'};
$e->{'deep.nested.value@attributes'};

$e->set('attributes->deep.nested.value', 'foo');
$e->isDirty('attributes->deep.nested.value'); // true
$e->isDirty('attributes->deep.nested.othervalue'); // false
$e->isDirty('attributes'); // true
$e->isDirty(); // true

// Upgrade connection if not already done
$table->useDatFields();

// Register a single datfield as datetime type
$table->getSchema()->setJsonTypes('data->time', 'datetime');

// Register a single datfield as date and overrides marshal hook with a callback
$table->getSchema()->setJsonTypes('data->frenchDateFormat', [
	'type' => 'date',
	'marshal' => function(string $value): FrozenDate {
		return FrozenDate::createFromFormat('d/m/Y', $value);
	}
]);

// Register many datfields as datetime type
$table->getSchema()->setJsonTypes([
	'data->time' => 'datetime',
	'date->anothertime' => 'datetime'
]);

// Register multiple datfields with full syntax
$table->getSchema()->setJsonTypes([
	'data->time' => [
		'type' => 'datetime',
		'marshal' => array($table, 'marshalTime'), // overrides datetime type marshal operation
	],
	'data->weirdthing' => [ // providing a type is not mandatory
		'marshal' => array($table, 'importWeirdthing'),
		'toPHP' => array($table, 'weirdthingToPHP'),
		'toDatabase' => array($table, 'weirdthingToDatabase'),
	],
]);

// Upgrade connection if not already done
$table->useDatFields();

$q = $table->find('json', ['jsonTypeMap' => ['data->time' => 'datetime']])->all();

$Clients->datFieldHasOne('Agents', ['foreignKey' => 'data->agent_id']);
$Clients->datFieldBelongsToMany('Products', [
  'foreignKey' => 'data->client_id'
  'targetForeignKey' => 'data->product_id',
  'through' => 'Orders'
]);

// Assuming that DatFieldAwareTrait or DatFieldBehavior are set in UsersTable
$user = $this->Users
  ->find() // Special finder is not e]) // Disable translation overhead as not needed in this query
  ->all();

// Assuming that DatFieldAwareTrait or DatFieldBehavior are set in UsersTable
// Connection is not already upgraded
$user1 = $this->Users
  ->useDatFields() // returns model instance, so it's chainable
  ->find() // Special finder is not >phones.tel' => 'wathever_number3'])
  ->first();

$users = $this->Users
  ->find('all', ['useDatFields' => false]) // Disable translation overhead as not needed in this query
  ->all();

// Restore genuine driver
$this->Users->useDatFields(false);

// Assuming that DatFieldAwareTrait or DatFieldBehavior are set in UsersTable
// We're in a controller that is loading Users model and connection is not already upgraded
// We request connection upgrade as datfields will be used in query
$user = $this->Users
  ->find('datfields') // or ->find('json')
  ->where(['attributes->phones.tel' => 'wathever_number'])
  ->first();

// This will work fine because 2 databases requests will be made, 1 per model with respective connection setup
$this->Vehicles->find()->contain(['Locations'])->all();

// This will fail because only 1 request with an INNER JOIN will be done from `Locations` not upgraded connection
$this->Vehicles->find()->innerJoinWith('Locations', function($q) {
  return $q->where(['Locations.attributes->position->lat <' => 45.6]);
})->all();

// This will work because we're upgrading connection on Vehicles with `datfields` custom finder
// Vehicles model must at least use `DatFieldAwareTrait`
$this->Vehicles->find('datfields')->innerJoinWith('Locations', function($q) {
  return $q->where(['Locations.attributes->position->lat <' => 45.6]);
})->all();