PHP code example of pdombrovsky / dyna-exp

1. Go to this page and download the library: Download pdombrovsky/dyna-exp 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/ */

    

pdombrovsky / dyna-exp example snippets


use DynaExp\Factories\Path;
use DynaExp\Factories\Key;
use DynaExp\Builders\ConditionBuilder;
use DynaExp\Builders\ExpressionBuilder;
use DynaExp\Evaluation\EvaluatorFactory;

$price = Path::create('price');
$stock = Path::create('inventory', 'total');

$condition = ConditionBuilder::allOf(
    $price->lessThanEqual(100),
    $stock->greaterThan(0)
)->build();

$expr = (new ExpressionBuilder())
    ->setFilter($condition)
    ->setKeyCondition(
        Key::create('pk')->equal('PRODUCT#123')
    )
    ->build(new EvaluatorFactory())
    ->toArray();

// [
//   'FilterExpression' => '#0 <= :0 AND #1 > :1',
//   'KeyConditionExpression' => '#2 = :2',
//   'ExpressionAttributeNames' => ['#0' => 'price', '#1' => 'total', '#2' => 'pk'],
//   'ExpressionAttributeValues' => [':0' => 100, ':1' => 0, ':2' => 'PRODUCT#123'],
// ]

use DynaExp\Factories\Path;
use DynaExp\Evaluation\Evaluator;

// Programmatic path
$p = Path::create('map', 'nested', 0, 'attr');   // map.nested[0].attr

// From string with quotes to keep dots inside a segment
$p2 = Path::fromString('map."a.b"[3].c');       // map.a.b[3].c

// JMESPath-like search expression (quoted segments). Optional index reset.
$p2->searchExpression();        // "map"."a.b"[3]."c"
$p2->searchExpression(true);    // "map"."a.b"[0]."c"

// Evaluation output with aliases
$evaluator = new Evaluator();
$exprPath = $p2->project()->evaluate($evaluator);   // "#0.#1[3].#2"
$namesMap = $evaluator->getAttributeNameAliases();  // ['#0' => 'map', '#1' => 'a.b', '#2' => 'c']

// Parent/child helpers
$p3 = Path::create('root', 'child');  // root.child
$p3Parent = $p3->parent();             // Path for 'root'
$p3Child  = $p3->child('leaf');        // root.child.leaf

// Check ancestry
$nested = $p3->child('leaf', 'branch');
$p3->isParentOf($nested); // true

$counter = Path::create('stats', 'counter');

// Reuse the same path for conditions and update actions
$isNonNegative = $counter->greaterThanEqual(0);                   // Semantics: stats.counter >= :0
$increment = $counter->set($counter->ifNotExists(0)->plus(1));    // Semantics: SET stats.counter = if_not_exists(stats.counter, :1) + :2

use DynaExp\Factories\Key;
use DynaExp\Builders\KeyConditionBuilder;

$hash  = Key::create('pk')->equal('H');
$range = Key::create('sk')->between(100, 200);

$kc = (new KeyConditionBuilder($hash))
    ->and($range)
    ->build();

use DynaExp\Factories\Path;

$sizeCond = Path::create('a')->size()->greaterThan(0);  // size(a) > :0

// You can nest size inside other expressions
$existsAndSize = ConditionBuilder::allOf(
    Path::create('a')->attributeExists(),
    Path::create('a')->size()->lessThanEqual(25)
)->build();

use DynaExp\Factories\Path;

$p = Path::create('counter');
$setIfNot = $p->set($p->ifNotExists(0));  // SET counter = if_not_exists(counter, :0)

// Preparing a default payload and storing a backup
$map = Path::create('items', 0);
$score = $map->child('score');
$backup = $map->child('backup');
$update = (new DynaExp\Builders\UpdateBuilder())
    ->add(
        $score->set(
            $score->ifNotExists(0)->plus($backup->ifNotExists(1))
        ),
        $backup->set($score->ifNotExists(0)),
    )
    ->build();

use DynaExp\Factories\Path;
use DynaExp\Builders\ConditionBuilder;
use DynaExp\Builders\ExpressionBuilder;
use DynaExp\Evaluation\EvaluatorFactory;

$a = Path::create('a');
$b = Path::create('b');

$nested = (new ConditionBuilder($a->attributeExists()))
    ->and(
        ConditionBuilder::anyOf(
            $b->notBetween(5, 10), // renders as: NOT b BETWEEN ...
            $b->in('x', 'y', 'z')  // renders as: b IN (...)
        ),
    )
    ->and($a->contains('x'))
    ->build();

// Evaluate to see final strings/aliases
$ctx = (new ExpressionBuilder())
    ->setFilter($nested)
    ->build(new EvaluatorFactory())
    ->toArray();

// $ctx === [
//     'FilterExpression' => 'attribute_exists (#0) AND (NOT #1 BETWEEN :0 AND :1 OR #1 IN (:2, :3, :4)) AND contains (#0, :5)',
//     'ExpressionAttributeNames' => ['#0' => 'a', '#1' => 'b'],
//     'ExpressionAttributeValues' => [':0' => 5, ':1' => 10, ':2' => 'x', ':3' => 'y', ':4' => 'z', ':5' => 'x'],
// ];

use DynaExp\Factories\Key;
use DynaExp\Builders\KeyConditionBuilder;

$left  = Key::create('pk')->equal('H');
$right = Key::create('sk')->beginsWith('ORD#');

$keyCond = (new KeyConditionBuilder($left))
    ->and($right)
    ->build();

use DynaExp\Builders\ProjectionBuilder;
use DynaExp\Factories\Path;

$projection = (new ProjectionBuilder(
    Path::create('a'),
    Path::create('b')
))->build();

use DynaExp\Builders\UpdateBuilder;
  use DynaExp\Factories\Path;
  use DynaExp\Builders\ExpressionBuilder;
  use DynaExp\Evaluation\EvaluatorFactory;
  
  $counter = Path::create('counter');
  $deprecatedFlag = Path::create('flags', 'deprecated');
  
  $update = (new UpdateBuilder())
      ->add(
          $counter->set(1),            // SET counter = :0
          $deprecatedFlag->remove()    // REMOVE flags.deprecated
      )
      ->build();
  
  $ctx = (new ExpressionBuilder())
      ->setUpdate($update)
      ->build(new EvaluatorFactory())
      ->toArray();
  
  // Example output:
  // $ctx['UpdateExpression'] === 'SET #0 = :0 REMOVE #1.#2'
  // $ctx['ExpressionAttributeNames'] === ['#0' => 'counter', '#1' => 'flags', '#2' => 'deprecated']
  // $ctx['ExpressionAttributeValues'] === [':0' => 1]
  

use DynaExp\Builders\UpdateBuilder;
use DynaExp\Factories\Path;
use DynaExp\Builders\ExpressionBuilder;
use DynaExp\Evaluation\EvaluatorFactory;

$listAttr = Path::create('listAttr');
$counter  = Path::create('counter');

$appendItems = $listAttr->set(
    $listAttr->ifNotExists([])->listAppend([1, 2, 3])
);

$incrementCounter = $counter->set(
    $counter->ifNotExists(0)->plus(1)
);

$update = (new UpdateBuilder())
    ->add($appendItems, $incrementCounter)
    ->build();

$ctx = (new ExpressionBuilder())
    ->setUpdate($update)
    ->build(new EvaluatorFactory())
    ->toArray();

// Example output:
// $ctx['UpdateExpression'] === 'SET #0 = list_append(if_not_exists(#0, :0), :1), #1 = if_not_exists(#1, :2) + :3'
// $ctx['ExpressionAttributeNames'] === ['#0' => 'listAttr', '#1' => 'counter']
// $ctx['ExpressionAttributeValues'] === [':0' => [], ':1' => [1, 2, 3], ':2' => 0, ':3' => 1]

$itemRoot = Path::create('items', 0);
$score = $itemRoot->child('score');
$backup = $itemRoot->child('scoreBackup');
$history = $itemRoot->child('history');
$historyPayload = $itemRoot->child('historyPayload');
$stats = Path::create('stats', 'totalScore');
$tags = $itemRoot->child('tags');

$update = (new UpdateBuilder())
    ->add(
        $score->set(
            $score->ifNotExists(0)->plus($backup->ifNotExists(1))
        ),
        $history->set(
            $history->ifNotExists([])->listAppend(
                $historyPayload->ifNotExists([])
            )
        ),
        $stats->add(10),
        $tags->delete(['legacy'])
    )
    ->build();

$ctx = (new ExpressionBuilder())
    ->setUpdate($update)
    ->build(new EvaluatorFactory())
    ->toArray();

// SET #0[0].#1 = if_not_exists(#0[0].#1, :0) + if_not_exists(#0[0].#2, :1),
//     #0[0].#3 = list_append(if_not_exists(#0[0].#3, :2), if_not_exists(#0[0].#4, :3))
// ADD #5.#6 :4
// DELETE #0[0].#7 :5

use DynaExp\Builders\ConditionBuilder;
use DynaExp\Builders\ExpressionBuilder;
use DynaExp\Builders\ProjectionBuilder;
use DynaExp\Builders\UpdateBuilder;
use DynaExp\Evaluation\EvaluatorFactory;
use DynaExp\Factories\Key;
use DynaExp\Factories\Path;

$name = Path::create('name');
$price = Path::create('price');
$status = Path::create('status');

$filter = ConditionBuilder::allOf(
    $price->lessThan(100),
    $status->equal('ACTIVE')
)->build();

$projection = (new ProjectionBuilder($name, $price))->build();

$keyCondition = Key::create('pk')->equal('PRODUCT#123');

$update = (new UpdateBuilder())
    ->add($status->set('ACTIVE'))
    ->build();

$expr = (new ExpressionBuilder())
    ->setFilter($filter)
    ->setProjection($projection)
    ->setKeyCondition($keyCondition)
    ->setUpdate($update)
    ->build(new EvaluatorFactory());

$array = $expr->toArray();
// Keys reflect DynamoDB API: ProjectionExpression, FilterExpression, UpdateExpression,
// KeyConditionExpression (if any), plus ExpressionAttributeNames/ExpressionAttributeValues when needed.

// Optional value transformation
$array = $expr->toArray(function (array $values) {
    // Convert your domain/custom types to wire format here
    return $values;
});