PHP code example of codememory / entity-response-control

1. Go to this page and download the library: Download codememory/entity-response-control 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/ */

    

codememory / entity-response-control example snippets


use Codememory\EntityResponseControl\Decorators as RCD;
use Codememory\EntityResponseControl\AbstractResponsePrototype;
use Codememory\EntityResponseControl\Collectors\BaseCollector;
use Codememory\Reflection\ReflectorManager;
use Symfony\Component\Cache\Adapter\FilesystemAdapter;
use Codememory\EntityResponseControl\Factory\ConfigurationFactory;
use Codememory\EntityResponseControl\Factory\ExecutionContextFactory;
use Codememory\EntityResponseControl\DecoratorHandlerRegistrar;

// We have some entity User
class User {
    private int $id = 1;
    private string $name = 'My Name';
    
    public function getId(): int 
    {
        return $this->id;
    }
    
    public function getName(): string 
    {
        return $this->name;
    }
    
    public function getCreatedAt(): DateTimeInterface
    {
        return new DateTime();
    }
}

// Our ResponsePrototype
class UserResponsePrototype extends AbstractResponsePrototype
{
    private ?int $id = null;
    private ?string $name = null;
    
    #[RCD\DateTime] // The default format is Y-m-d H:i:s
    private ?string $createdAt = null;
}

$userResponse = new UserResponsePrototype(
    new BaseCollector(),
    new ConfigurationFactory(),
    new ExecutionContextFactory(),
    new DecoratorHandlerRegistrar(),
    new ReflectorManager(new FilesystemAdapter('entity-response-control', '/var/cache/codememory'))
);
$response = $userResponse->collect(new User())->toArray();
        
// We get the answer in the form of an array:
[
    "id" => 1,
    "name" => "My Name",
    "created_at" => "2023-01-03 00:00"
]

use Attribute;
use Codememory\EntityResponseControl\Interfaces\DecoratorInterface;
use Codememory\EntityResponseControl\Interfaces\DecoratorHandlerInterface;
use Codememory\EntityResponseControl\Interfaces\ExecutionContextInterface;
use Symfony\Component\String\u;

// This decorator will change the getter prefix
#[Attribute(Attribute::TARGET_PROPERTY)]
final class MyDecorator implements DecoratorInterface
{
    public function __construct
    (
        public readonly string $prefix
    ) {}
    
    public function getHandler() : string
    {
        return MyDecoratorHandler::class;
    }
}

// Decorator handler
final class MyDecoratorHandler implements DecoratorHandlerInterface 
{
    // This method can return any result.
    public function handle(DecoratorInterface $decorator, ExecutionContextInterface $context) : void
    {
        $propertyName = $context->getProperty()->getName();
        
        $context->setNameGetterToGetValueFromObject(u("{$decorator->prefix}_{$propertyName}")->camel()); // Example: isPay
        
        // Update the value by getting it from the new method
        $context->setValue($context->getPrototypeObject()->{$context->getNameGetterToGetValueFromObject()}()); 
    }
}

// Before calling collect, refer to the configuration
$responsePrototype->getDecoratorHandlerRegistrar()->register(new MyDecoratorHandler());

// Collect prototype...

use Codememory\Reflection\ReflectorManager;
use Symfony\Component\Cache\Adapter\FilesystemAdapter;
use Codememory\EntityResponseControl\Interfaces\CollectorInterface;
use Codememory\EntityResponseControl\Interfaces\ResponsePrototypeInterface;
use Codememory\Reflection\Reflectors\PropertyReflector;
use Codememory\EntityResponseControl\Interfaces\DecoratorInterface;
use Codememory\EntityResponseControl\Factory\ExecutionContextFactory;
use Codememory\EntityResponseControl\Factory\ConfigurationFactory;
use Codememory\EntityResponseControl\DecoratorHandlerRegistrar;

class MyObjectCollector implements CollectorInterface {
    public function collect(ResponsePrototypeInterface $responsePrototype, object $prototypeObject, array $properties): array
    {
        $collectedResponse = [];
    
        foreach ($properties as $property) {
            if ($property instanceof PropertyReflector) {
                // Create a context
                $context = $responsePrototype->getExecutionContextFactory()->createExecutionContext($responsePrototype, $property, $prototypeObject);
                foreach ($property->getAttributes() as $attribute) {
                    $decorator = $attribute->getInstance();
                    
                    if ($decorator instanceof DecoratorInterface) {
                        // Getting a decorator handler
                        $decoratorHandler = $responsePrototype->getDecoratorHandlerRegistrar()->getHandler($decorator->getHandler());
                        
                        // Calling a decorator handler
                        $decoratorHandler->handle($decorator, $context);
                    }
                }
                
                // Collecting an array of data
                $collectedResponse[$context->getResponseKey()] = $context->getValue();
            }
        }
        
        return $collectedResponse;
    }
}

// An example of using our UserPrototype with the new Collector

$userResponse = new UserResponse(
    new MyObjectCollector(),
    new ConfigurationFactory(),
    new ExecutionContextFactory(),
    new DecoratorHandlerRegistrar(),
    new ReflectorManager(new FilesystemAdapter('entity-response-control', '/var/cache/codememory'))
);

$userResponse
    ->collect([new User()])
    ->toArray(); // Response to array

use Codememory\EntityResponseControl\Interfaces\ExecutionContextInterface;
use Codememory\EntityResponseControl\Interfaces\ExecutionContextFactoryInterface;
use Codememory\EntityResponseControl\Interfaces\ResponsePrototypeInterface;
use Codememory\Reflection\Reflectors\PropertyReflector;

// Create a context
final class MyContext implements ExecutionContextInterface
{
    // Implementing Interface Methods...
}

// Creating a context factory
final class MyContextFactory implements ExecutionContextFactoryInterface
{
    public function createExecutionContext(ResponsePrototypeInterface $responsePrototype, PropertyReflector $property, object $prototypeObject): ExecutionContextInterface
    {
        $context = new MyContext();
        // ...
        
        return $context;
    }
}

use Codememory\EntityResponseControl\Interfaces\ResponseKeyNamingStrategyInterface;

final class MyStrategyName implements ResponseKeyNamingStrategyInterface
{
    private ?\Closure $extension = null;

    public function convert(string $propertyName) : string
    {
        $name =  "_$propertyName";
        
        if (null !== $this->extension) {
            return call_user_func($this->extension, $name);
        }
        
        return $name;
    }
    
    // With this method, you need to give the opportunity to extend the convert method
    public function setExtension(callable $callback) : ResponseKeyNamingStrategyInterface
    {
        $this->extension = $callback;
        
        return $this;
    }
}

$myPrototype = new MyResponsePrototype(new BaseCollector(), new ConfigurationFactory(), ...);

// To use this strategy, you need to change the configuration
$myPrototype->getConfiguration()->setDataKeyNamingStrategy(new MyStrategyName());

use Codememory\EntityResponseControl\Provider\ResponsePrototypePrivatePropertyProvider;
use Codememory\Reflection\Reflectors\ClassReflector;

// The provider will say that only private properties need to be processed
final class MyPropertyProvider implements ResponsePrototypePrivatePropertyProvider
{
    private ?\Closure $extension = null;

    public function getProperties(ClassReflector $classReflector) : array
    {
        $properties = $classReflector->getPrivateProperties();
        
        if (null !== $this->extension) {
            return call_user_func($this->extension, $properties);
        }
        
        return $properties;
    }
    
    // With this method, you need to give the opportunity to extend the getProperties method
    public function setExtension(callable $callback) : ResponsePrototypePrivatePropertyProvider
    {
        $this->extension = $callback;
        
        return $this;
    }
}

$myPrototype = new MyResponsePrototype(new BaseCollector(), new ConfigurationFactory(), ...);

// Change the provider in the configuration
$myPrototype->getConfiguration()->setResponsePrototypePropertyProvider(new MyPropertyProvider());