PHP code example of kabiroman / adaptive-entity-manager

1. Go to this page and download the library: Download kabiroman/adaptive-entity-manager 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/ */

    

kabiroman / adaptive-entity-manager example snippets


// Create configuration
$config = new Config(
    entityFolder: "your_project_dir/src/Entity",
    entityNamespace: 'App\\Entity\\',
    cacheFolder: "your_project_dir/var/cache"
);

// Initialize the Entity Manager
$entityManager = new AdaptiveEntityManager(
    $config,
    new DefaultEntityMetadataProvider(),
    new DefaultEntityDataAdapterProvider()
);

// Work with entities
$entity = $entityManager->find(YourEntity::class, $id);
$entityManager->persist($entity);
$entityManager->flush();

$entityManager->find(Entity::class, $id);      // Find an entity by ID
$entityManager->persist($entity);              // Stage an entity for persistence
$entityManager->remove($entity);               // Stage an entity for removal
$entityManager->flush();                       // Execute all staged operations

$repository = $entityManager->getRepository(Entity::class);
$entities = $repository->findBy(['status' => 'active']);

$entityManager->beginTransaction();
try {
    // Perform operations
    $entityManager->flush();
    $entityManager->commit();
} catch (\Exception $e) {
    $entityManager->rollback();
    throw $e;
}

use Kabiroman\AEM\ValueObject\Common\Email;
use Kabiroman\AEM\ValueObject\Common\Money;
use Kabiroman\AEM\ValueObject\Converter\ValueObjectConverterRegistry;

// Enable ValueObject support
$registry = new ValueObjectConverterRegistry();
$entityManager = new AdaptiveEntityManager(
    $config,
    $metadataProvider,
    $dataAdapterProvider,
    valueObjectRegistry: $registry
);

// Using Email ValueObject
$user = new User();
$user->setEmail(new Email('[email protected]'));

// Automatic conversion during persistence
$entityManager->persist($user);  // Email converts to string
$entityManager->flush();

// Automatic conversion during hydration
$loadedUser = $entityManager->find(User::class, 1);
$email = $loadedUser->getEmail();  // Returns Email ValueObject
echo $email->getDomain();  // "example.com"

// In your entity metadata class
use Kabiroman\AEM\Constant\FieldTypeEnum;
use Kabiroman\AEM\ValueObject\Common\Email;

$metadata->addField('email', FieldTypeEnum::ValueObject, Email::class);

use Kabiroman\AEM\ValueObject\ValueObjectInterface;

class ProductCode implements ValueObjectInterface
{
    public function __construct(private readonly string $code)
    {
        if (!preg_match('/^[A-Z]{2}\d{4}$/', $code)) {
            throw new \InvalidArgumentException('Invalid product code format');
        }
    }

    public function toPrimitive(): string
    {
        return $this->code;
    }

    public static function fromPrimitive($value): self
    {
        return new self((string) $value);
    }

    public function equals(ValueObjectInterface $other): bool
    {
        return $other instanceof self && $this->code === $other->code;
    }

    public function __toString(): string
    {
        return $this->code;
    }
}

use Kabiroman\AEM\Event\PrePersistEvent;
use Psr\EventDispatcher\EventDispatcherInterface;

class MyEventListener
{
    public function onPrePersist(PrePersistEvent $event): void
    {
        $entity = $event->getEntity();
        // Perform custom logic before persistence, e.g., set creation date
        if (method_exists($entity, 'setCreatedAt') && $entity->getCreatedAt() === null) {
            $entity->setCreatedAt(new \DateTimeImmutable());
        }
        // You can stop propagation of the event if needed
        // $event->stopPropagation();
    }
}

// Assuming you have a PSR-14 EventDispatcher instance
/** @var EventDispatcherInterface $eventDispatcher */
$eventDispatcher = /* ... your event dispatcher instance ... */;

// In a non-Symfony project, you might need a ListenerProvider:
// $listenerProvider = new \League\Event\ListenerProvider();
// $listenerProvider->addListener(PrePersistEvent::class, [new MyEventListener(), 'onPrePersist']);
// $eventDispatcher = new \League\Event\EventDispatcher($listenerProvider);

// Add your listener to the dispatcher
// The exact method depends on your PSR-14 implementation
$eventDispatcher->addListener(PrePersistEvent::class, [new MyEventListener(), 'onPrePersist']);

// When AdaptiveEntityManager (specifically UnitOfWork) dispatches PrePersistEvent,
// MyEventListener::onPrePersist will be called.



namespace Example\DataAdapter;

use Kabiroman\AEM\DataAdapter\AbstractDataAdapter;
use GuzzleHttp\ClientInterface;

class UserApiAdapter extends AbstractDataAdapter
{
    private const API_ENDPOINT = 'https://api.example.com/users';

    public function __construct(
        private readonly ClientInterface $httpClient
    ) {}

    public function loadById(array $identifier): ?array
    {
        $response = $this->httpClient->request('GET', self::API_ENDPOINT . '/' . $identifier['id']);
        $data = json_decode($response->getBody()->getContents(), true);
        
        if (!$data) {
            return null;
        }

        // Convert response fields from snake_case to camelCase
        $this->toCamelCaseParams($data);
        
        return $data;
    }

    public function insert(array $row): array
    {
        // Convert entity fields from camelCase to snake_case
        $this->toSnakeCaseParams($row);
        
        $response = $this->httpClient->request('POST', self::API_ENDPOINT, [
            'json' => $row
        ]);
        
        $data = json_decode($response->getBody()->getContents(), true);
        $this->toCamelCaseParams($data);
        
        return $data;
    }

    public function update(array $identifier, array $row)
    {
        $this->toSnakeCaseParams($row);
        
        $this->httpClient->request('PUT', self::API_ENDPOINT . '/' . $identifier['id'], [
            'json' => $row
        ]);
    }

    public function delete(array $identifier)
    {
        $this->httpClient->request('DELETE', self::API_ENDPOINT . '/' . $identifier['id']);
    }

    public function loadAll(
        array $criteria = [],
        ?array $orderBy = null,
        ?int $limit = null,
        ?int $offset = null
    ): array {
        $query = http_build_query(array_filter([
            'filter' => $criteria,
            'sort' => $orderBy,
            'limit' => $limit,
            'offset' => $offset,
        ]));

        $response = $this->httpClient->request('GET', self::API_ENDPOINT . '?' . $query);
        $data = json_decode($response->getBody()->getContents(), true);

        foreach ($data as &$row) {
            $this->toCamelCaseParams($row);
        }

        return $data;
    }

    public function refresh(array $identifier): array
    {
        return $this->loadById($identifier) ?? 
            throw new \RuntimeException('Entity not found');
    }
}

use Kabiroman\AEM\AdaptiveEntityManager;
use Kabiroman\AEM\Config;
use Example\Entity\User;
use Example\DataAdapter\UserApiAdapter;

// Create HTTP client
$httpClient = new \GuzzleHttp\Client();

// Create data adapter
$userAdapter = new UserApiAdapter($httpClient);

// Configure entity manager
$config = new Config([
    'dataAdapters' => [
        User::class => $userAdapter
    ]
]);

// Create entity manager
$entityManager = new AdaptiveEntityManager($config);

// Use the entity manager
$user = $entityManager->find(User::class, 1);
$user->setEmail('[email protected]');

$entityManager->persist($user);
$entityManager->flush();



namespace App\Metadata;

use Kabiroman\AEM\Metadata\AbstractClassMetadata;
use App\Entity\User;
use App\Entity\Role;
use App\Entity\Post;
use App\DataAdapter\UserDataAdapter;

class UserMetadata extends AbstractClassMetadata
{
    public function __construct()
    {
        $this->metadata = [
            User::class => [
                // Specify the data adapter for this entity
                'dataAdapterClass' => UserDataAdapter::class,
                
                // Define identifier fields
                'id' => [
                    'id' => [
                        'type' => 'integer',
                        'column' => 'user_id',
                        'generator' => 'AUTO'
                    ]
                ],
                
                // Define regular fields
                'fields' => [
                    'email' => [
                        'type' => 'string',
                        'column' => 'email_address',
                        'nullable' => false
                    ],
                    'username' => [
                        'type' => 'string',
                        'column' => 'username',
                        'nullable' => false
                    ],
                    'createdAt' => [
                        'type' => 'datetime',
                        'column' => 'created_at',
                        'nullable' => false
                    ]
                ],
                
                // Define relationships
                'hasOne' => [
                    'role' => [
                        'targetEntity' => Role::class,
                        'joinColumn' => [
                            'name' => 'role_id',
                            'referencedColumnName' => 'id'
                        ],
                        'fetch' => 'LAZY'
                    ]
                ],
                'hasMany' => [
                    'posts' => [
                        'targetEntity' => Post::class,
                        'mappedBy' => 'author',
                        'fetch' => 'LAZY'
                    ]
                ],
                
                // Define lifecycle callbacks
                'lifecycleCallbacks' => [
                    'prePersist' => ['setCreatedAt']
                ]
            ]
        ];
    }
}

'fields' => [
    'isActive' => [
        'type' => 'boolean',
        'column' => 'ACTIVE',
        'nullable' => false,
        'values' => [
            'Y' => true,
            'N' => false,
        ],
    ],
]



namespace App\Entity;

use DateTime;
use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\ArrayCollection;

class User
{
    private ?int $id = null;
    private string $email;
    private string $username;
    private string $password;
    private DateTime $createdAt;
    private bool $isActive = true;
    
    private Role $role;
    private Collection $posts;
    
    public function __construct()
    {
        $this->posts = new ArrayCollection();
    }
    
    // Lifecycle callback
    public function setCreatedAt(): void
    {
        $this->createdAt = new DateTime();
    }
    
    // Getters and setters...
}

use Kabiroman\AEM\ValueObject\Common\Email;
use Kabiroman\AEM\ValueObject\Common\Money;
use Kabiroman\AEM\ValueObject\Converter\ValueObjectConverterRegistry;

// Enable Value Object support
$valueObjectRegistry = new ValueObjectConverterRegistry();
$entityManager = new AdaptiveEntityManager(
    config: $config,
    classMetadataProvider: $metadataProvider,
    entityDataAdapterProvider: $adapterProvider,
    valueObjectRegistry: $valueObjectRegistry
);

// Use Value Objects in entities
class Product
{
    private Email $contactEmail;
    private Money $price;
    
    public function setContactEmail(Email $email): void
    {
        $this->contactEmail = $email;
    }
    
    public function setPrice(Money $price): void
    {
        $this->price = $price;
    }
}

// Create and use Value Objects
$product = new Product();
$product->setContactEmail(Email::fromPrimitive('[email protected]'));
$product->setPrice(Money::fromPrimitive(['amount' => 12500, 'currency' => 'USD']));

$entityManager->persist($product);
$entityManager->flush();