Git Product home page Git Product logo

doctrine-laminas-hydrator's People

Contributors

bakura10 avatar carusogabriel avatar davidwindell avatar dkmuir avatar driehle avatar fezfez avatar freemanirl avatar gianarb avatar greg0ire avatar heyratfans avatar jaapio avatar kokspflanze avatar kokx avatar michalbundyra avatar micheh avatar midnightdesign avatar mikesimonson avatar ocramius avatar pborreli avatar pietervogelaar avatar powerkiki avatar senseexception avatar slamdunk avatar snapshotpl avatar svycka avatar texdc avatar tomhanderson avatar xcame avatar zluiten avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

doctrine-laminas-hydrator's Issues

Documentation issues and hydration apparently not working for Embeddable

Hi,

I have checked the documentation for for 3.1.0.

https://www.doctrine-project.org/projects/doctrine-laminas-hydrator/en/3.1/basic-usage.html#basic-usage

For embedded case I see couple problems:

  1. The class Tag is actually Address (according to Person class)
  2. Hydrating example doesnt work. For new person object both address fields are null. One problem is the hydrating array is wrong:
[
    [
        'postalCode' => '48149',
        'city' => 'Münster',
    ],
],

it should be:

[
    'postalCode' => '48149',
    'city' => 'Münster',
],
  1. Both fields of Address are still null after hydrating even after fixing the above errors. The cause I guess is because

$metadata->hasAssociation($field) and is_callable([$object, $setter]) are false within hydrateByValue function... They are not working properly for Embeddable.

  1. I added the missing setAddress function but I am getting issues:
public function setAddress(Address $address): void
{
    $this->address = $address;
}

Person::setAddress(): Argument #1 ($address) must be of type Address, array given

  1. Only If I am creating a
	public function setAddress(Address | array $address): void
	{
		if(is_array($address)){
			print_r($address);

			$this->address->setCity($address['city']);
			$this->address->setPostalCode($address['postalCode']);
		} else {
			$this->address = $address;
		}
	}

the code is working properly and the Address is hydrate. Not sure if this is the expected behavior but I dont see it useful this way.

Testing setup:

doctrine/annotations 1.13.3 Docblock Annotations Parser
doctrine/cache 1.13.0 PHP Doctrine Cache library is a popular cache implementation that supports many different drivers such as redis, memcache, apc, mo...
doctrine/collections 1.7.0 PHP Doctrine Collections library that adds additional functionality on top of PHP arrays.
doctrine/common 3.3.1 PHP Doctrine Common project is a library that provides additional functionality that other Doctrine projects depend on such as bet...
doctrine/dbal 2.13.9 Powerful PHP database abstraction layer (DBAL) with many features for database schema introspection and management.
doctrine/deprecations v0.5.3 A small layer on top of trigger_error(E_USER_DEPRECATED) or PSR-3 logging with options to disable all deprecations or selectively ...
doctrine/doctrine-laminas-hydrator 3.1.0 Doctrine hydrators for Laminas applications
doctrine/doctrine-module 5.2.0 Laminas Module that provides Doctrine basic functionality required for ORM and ODM modules
doctrine/doctrine-orm-module 5.2.0 Laminas Module that provides Doctrine ORM functionality
doctrine/event-manager 1.1.2 The Doctrine Event Manager is a simple PHP event system that was built to be used with the various Doctrine projects.
doctrine/inflector 2.0.4 PHP Doctrine Inflector is a small library that can perform string manipulations with regard to upper/lowercase and singular/plural...
doctrine/instantiator 1.4.1 A small, lightweight utility to instantiate objects in PHP without invoking their constructors
doctrine/lexer 1.2.3 PHP Doctrine Lexer parser library that can be used in Top-Down, Recursive Descent Parsers.
doctrine/migrations 3.4.2 PHP Doctrine Migrations project offer additional functionality on top of the database abstraction layer (DBAL) for versioning your...
doctrine/orm 2.13.1 Object-Relational-Mapper for PHP
doctrine/persistence 3.0.3 The Doctrine Persistence project is a set of shared interfaces and functionality that the different Doctrine object mappers share.

laminas/laminas-authentication 2.11.0 provides an API for authentication and includes concrete authentication adapters for common use case scenarios
laminas/laminas-cache 3.4.0 Caching implementation with a variety of storage options, as well as codified caching strategies for callbacks, classes, and output
laminas/laminas-cache-storage-adapter-filesystem 2.0.1 Laminas cache adapter for filesystem
laminas/laminas-cache-storage-adapter-redis 2.2.0 Laminas cache adapter for redis
laminas/laminas-cli 1.5.0 Command-line interface for Laminas projects
laminas/laminas-code 4.6.0 Extensions to the PHP Reflection API, static code scanning, and code generation
laminas/laminas-component-installer 2.8.0 Composer plugin for injecting modules and configuration providers into application configuration
laminas/laminas-config 3.7.0 provides a nested object property based user interface for accessing this configuration data within application code
laminas/laminas-crypt 3.8.0 Strong cryptography tools and password hashing
laminas/laminas-db 2.15.0 Database abstraction layer, SQL abstraction, result set abstraction, and RowDataGateway and TableDataGateway implementations
laminas/laminas-development-mode 3.8.0 Laminas development mode script
laminas/laminas-di 3.9.1 Automated dependency injection for PSR-11 containers
laminas/laminas-diactoros 2.14.0 PSR HTTP Message implementations
laminas/laminas-escaper 2.10.0 Securely and safely escape HTML, HTML attributes, JavaScript, CSS, and URLs
laminas/laminas-eventmanager 3.5.0 Trigger and listen to events within a PHP application
laminas/laminas-filter 2.17.0 Programmatically filter and normalize data and files
laminas/laminas-form 3.4.1 Validate and display simple and complex forms, casting forms to business objects and vice versa
laminas/laminas-http 2.16.0 Provides an easy interface for performing Hyper-Text Transfer Protocol (HTTP) requests
laminas/laminas-hydrator 4.5.0 Serialize objects to arrays, and vice versa
laminas/laminas-i18n 2.17.0 Provide translations for your application, and filter and validate internationalized values
laminas/laminas-inputfilter 2.19.1 Normalize and validate input sets from the web, APIs, the CLI, and more, including files
laminas/laminas-json 3.3.0 provides convenience methods for serializing native PHP to JSON and decoding JSON to native PHP
laminas/laminas-loader 2.8.0 Autoloading and plugin loading strategies
laminas/laminas-log 2.15.2 Robust, composite logger with filtering, formatting, and PSR-3 support
laminas/laminas-mail 2.17.0 Provides generalized functionality to compose and send both text and MIME-compliant multipart e-mail messages
laminas/laminas-math 3.5.0 Create cryptographically secure pseudo-random numbers, and manage big integers
laminas/laminas-mime 2.9.1 Create and parse MIME messages and parts
laminas/laminas-modulemanager 2.12.x-dev 2a3d943 Modular application system for laminas-mvc applications
laminas/laminas-mvc 3.3.4 Laminas's event-driven MVC layer, including MVC Applications, Controllers, and Plugins
laminas/laminas-mvc-form 2.1.x-dev 6f46662 Metapackage with all requirements needed to use laminas-form with laminas-mvc.
laminas/laminas-mvc-i18n 1.4.0 Integration between laminas-mvc and laminas-i18n
laminas/laminas-mvc-plugin-flashmessenger 1.8.1 Plugin for creating and exposing flash messages via laminas-mvc controllers
laminas/laminas-mvc-plugin-identity 1.4.0 Plugin for retrieving the current authenticated identity within laminas-mvc controllers
laminas/laminas-navigation 2.14.0 Manage trees of pointers to web pages in order to build navigation systems
laminas/laminas-paginator 2.13.0 Paginate collections of data from arbitrary sources
laminas/laminas-permissions-acl 2.10.0 Provides a lightweight and flexible access control list (ACL) implementation for privileges management
laminas/laminas-psr7bridge 1.6.0 Bidirectional conversions between PSR-7 and laminas-http messages
laminas/laminas-router 3.7.0 Flexible routing system for HTTP and console applications
laminas/laminas-serializer 2.13.0 Serialize and deserialize PHP structures to a variety of representations
laminas/laminas-servicemanager 3.16.0 Factory-Driven Dependency Injection Container
laminas/laminas-session 2.13.0 Object-oriented interface to PHP sessions and storage
laminas/laminas-stdlib 3.11.0 SPL extensions, array utilities, error handlers, and more
laminas/laminas-uri 2.9.1 A component that aids in manipulating and validating » Uniform Resource Identifiers (URIs)
laminas/laminas-validator 2.23.0 Validation classes for a wide range of domains, and the ability to chain validators to create complex validation criteria
laminas/laminas-view 2.22.1 Flexible view layer supporting and providing multiple view layers, helpers, and more

DoctrineObject extractByReference on uninitialized variables (PHP 7.4)

summary

In php 7.4, variables that are not set have a state of uninitialized. If extracting an entity by reference, extractByReference will fail trying to access an uninitialized property.

expected behavior

Extraction should work with objects that can have uninitialized properties.

proposed solution

Adding a simple isInitialized check before accessing property values

    protected function extractByReference($object)
    {
        $fieldNames = array_merge($this->metadata->getFieldNames(), $this->metadata->getAssociationNames());
        $refl       = $this->metadata->getReflectionClass();
        $filter     = $object instanceof FilterProviderInterface
            ? $object->getFilter()
            : $this->filterComposite;

        $data = [];
        foreach ($fieldNames as $fieldName) {
            if ($filter && ! $filter->filter($fieldName)) {
                continue;
            }

            $reflProperty = $refl->getProperty($fieldName);
            if ($reflProperty->isInitialized($object)) {
                $reflProperty->setAccessible(true);

                $dataFieldName        = $this->computeExtractFieldName($fieldName);
                $data[$dataFieldName] = $this->extractValue($fieldName, $reflProperty->getValue($object), $object);
            }
        }

        return $data;
    }

Problem with the compare function of the AbstractCollectionStrategy

Recently we've updated this library and experience a problem with the compare function of the AbstractCollectionStrategy.
Previously the compare function used the strcmp function, that is changed into the spaceship operator. For some specific hash values this results in an other outcome. For us this leads now into an incorrect list of items to be removed or added.

This is how it was:
return strcmp(spl_object_hash($a), spl_object_hash($b));

That is changed in this commit in:
return spl_object_hash($a) <=> spl_object_hash($b);

When the hash of $a is "00000000000007e60000000000000000" and the hash of $b is "00000000000053110000000000000000" we get different results. The "old" code (strcmp) results in -5. The "new" code (<=>) results in 1. We think the "old" way is correct. What would be the best way to fix this?

Hydrating uploaded image array to entity

Hello there,

In the previous zend 2 version with doctrine, i could validate a form with a file type field and it hydrates the image field with the image array. But now it seems its not doing this anymore. I am using annotation now but previously i was using yaml as my entity mapper. How can i approach this auto hydration of my objects with my forms?

public function init()
    {
        $this->setHydrator(new DoctrineHydrator($this->entityManager));
        $this->setObject(new Category());
        $this->addElements();
        $this->addInputFilter();
    }

This is how i use the hydrator with my forms..

    /**
     * @ORM\Column(name="image", type="string", length=255)
     */
    private $image;

This is how i annotate my image field

hydrate composite PK

Hi! I want to hydrate an entity with a composite PK, the problem is that this line removes those values

https://github.com/rodsouto/doctrine-laminas-hydrator/blob/master/src/DoctrineObject.php#L485

I tried commenting out that line and it works, but there is one test failing with Error: Cannot access protected property DoctrineTest\Laminas\Hydrator\Assets\ByValueDifferentiatorEntity::$id

I think thats happening because in DoctrineObject::hydrateByReference() it is calling $reflProperty->setValue() but $object is not the same class as $metadata->getReflectionClass()

If in line 339 I replace $refl = $metadata->getReflectionClass(); with $refl = new \ReflectionClass($object) then all tests are green again

So, is using $refl = new \ReflectionClass($object) a valid fix to get the composite PK working? or is there a better way?

Collection nested collection

Live,
I'm using laminas-doctrine-hydrator with 2-level collections in one-to-many relationships.
The 2nd level fieldset gives the error "Call to a member function setValue() on null".
Is there any limitation?
As classes:

class Entity1 {
   /**
@ORM\OneToMany(targetEntity="Entity2", mappedBy="entity1", orphanRemoval=true, cascade={"persist", "remove", "merge"})
    */
   protected $entities2;
}
class Entity2 {
   /**
@ORM\ManyToOne(targetEntity="Entity1", inversedBy="entities2")
    */
   protected $entity1;
   /**
@ORM\OneToMany(targetEntity="Entity3", mappedBy="entity2", orphanRemoval=true, cascade={"persist", "remove", "merge"})
    */
   protected $entities3;
}
class Entity3 {
   /**
@ORM\ManyToOne(targetEntity="Entity2", inversedBy="entities3")
    */
   protected $entity2;
}

o form e fieldset:

class Entity1Form {
   public function __construct(EntityManager $entityManager) {
       // Some elements ...
       $this->add(array(
           'type' => 'Zend\Form\Element\Collection',
           'name' => 'entities2',
           'options' => array(
               'count' => 0,
               'should_create_template' => true,
               'allow_add' => true,
               'allow_remove' => true,
               'target_element' => new Entity2Fieldset($entityManager)
           )
       ));
       $this->setHydrator(new DoctrineObject($entityManager))->setObject(new Entity1());
   }
}
class Entity2Fieldset {
   public function __construct(EntityManager $entityManager) {
       // Some elements ...
       $this->add(array(
           'type' => 'Zend\Form\Element\Collection',
           'name' => 'entities3',
           'options' => array(
               'count' => 0,
               'should_create_template' => true,
               'allow_add' => true,
               'allow_remove' => true,
               'target_element' => new Entity3Fieldset($entityManager)
           )
       ));
       $this->setHydrator(new DoctrineObject($entityManager))->setObject(new Entity2());
   }
}
class Entity3Fieldset {
       public function __construct(EntityManager $entityManager) {
           // Some elements ...
           $this->setHydrator(new DoctrineObject($entityManager))->setObject(new Entity3());
       }
   }

Wrong case of decimal and bigint

Hi everyone,

I've already create a PR for this issue but it wasn't merged or commented.
At the moment, decimal are casted as "string" this lead to errors when using strict types in php7.4

Best regards,
Alexander

Backed Enum Hydration ends up in a type conversion

The Doctrine Hydrator can not handle backed enum typed entity properties,
Let us discuss the following example.

enum Suit: string {
    case Hearts = 'H';
    case Diamonds = 'D';
    case Clubs = 'C';
    case Spades = 'S';
}

#[Entity]
class Card
{
    /** ... */

    #[Column(type: 'string', enumType: Suit::class)]
    public Suit $suit;

    public function getSuit(): Suit
    {
        return $this->suit;
    }

    public function setSuit(Suit $suit): void
    {
        $this->suit = $suit;
    }
}

As you can see the get and set method are typed as Suit and not as string because the value is an instance of the Suit enumeration. For this purpose I created a hydrator strategy.

namespace Marcel\Hydrator\Strategy;
use Laminas\Hydrator\Strategy\StrategyInterface;

class SuitHydratorStrategy implements StrategyInterface
{
    public function hydrate($value, ?array $data)
    {
        return Suit::from($value);
    }

    public function extract($value, ?object $object = null)
    {
        ...
    }
}
use Doctrine\Laminas\Hydrator\DoctrineObject as DoctrineHydrator;
use Marcel\Entity\Card;
use Marcel\Hydrator\Strategy\SuitHydratorStrategy;

$hydrator = new DoctrineHydrator($entityManager);
$hydrator->addStrategy('suit', new \Marcel\Hydrator\Strategy\SuitHydratorStrategy());

$card = new Card();
$hydrator->hydrate([ 'suit' => 'H' ], $card);

This will end up in a type conversion error since DoctrineObject::handleTypeConversions($value, ?$typeOfField) does not recognize backed enums. The $value param holds an instance of the Suit enum, which implements the BackedEnum interface. One could easily avoid this behaviour by adding the following line of code.

protected function handleTypeConversions($value, ?string $typeOfField)
{
    ...
    if (interface_exists('BackedEnum') && $value instanceof BackedEnum) {
        $value = $value->value;
    }
    ...
}

Removal of identifier values in toMany() function

Hi,

I use a custom ID generator (UUID) for my Doctrine entities.

    /**
     * @ORM\Id()
     * @ORM\Column(type="uuid", unique=true)
     * @ORM\GeneratedValue(strategy="CUSTOM")
     * @ORM\CustomIdGenerator(class=UuidGenerator::class)
     */
    protected $id;

The generator only generates a new UUID if there is none set.
At the moment it is impossible to do that with the hydrator, because of the following line:

unset($value[$field]); // removed identifier from persistable data

Is the removal of the identifier really necessary?

Association extraction

I want to use this library without laminas forms. When I try to extract an entity with a many-to-many relationship, I receive the PersistentCollection in the result array. Association extraction is not covered in the documentation. Could you please help me?

Here is my example entities:

#[ORM\Entity]
class Order extends IdEntity
{
    #[ORM\Id]
    #[ORM\Column(type: 'string')]
    protected string $id;

    #[ORM\ManyToMany(targetEntity: Tag::class)]
    public Collection $tags;

    public function __construct()
    {
        $this->id = uniqid('order');
        $this->tags = new ArrayCollection();
    }

    public function getId():string
    {
        return $this->id;
    }

    public function getTags():Collection
    {
        return $this->tags;
    }
}

#[ORM\Entity]
final class Tag extends IdEntity
{
    #[ORM\Id]
    #[ORM\Column(type: 'string')]
    public string $id;

    #[ORM\Column(type: 'string')]
    public string $name;

    public function __construct()
    {
        $this->id = uniqid('tag');
    }

    public function getId():string
    {
        return $this->id;
    }

    public function getName():string
    {
        return $this->name;
    }
}

Here is my code where i'm trying to extract data:

$order = $entityManager->find(Order::class,'order641c4493aa1ad');
$doctrineHydrator = new \Doctrine\Laminas\Hydrator\DoctrineObject($entityManager);
$data = $doctrineHydrator->extract($order);
print_r(get_debug_type($data['tags']));

Here is output:

Doctrine\ORM\PersistentCollection

I'm expecting array with tags there.

Deprecation notices from doctrine\common

Report
Version 2.0.2

Summary
The Doctrine\Common\Util\Inflector class is deprecated, use Doctrine\Common\Inflector\Inflector from doctrine/inflector package instead.

Expected behavior
No deprecation should be triggered.

Hydrator is trying to update instead of replace collection entities - can this be prevented?

Hello!

In trying to hydrate collection 'changes' (e.g., an update operation) - I've encountered an issue where adding and removing an element from this collection (via Fieldset) in a single operation causes duplicate key problems as Doctrine flushes.

I've created a repository to evidence the difficulties being encountered here:
https://github.com/Saeven/CollectionHydration

Is there a means to achieve what I'm after the "Doctrine way", or is clearing and the repopulating the collection the intended behavior? This collection can contain thousands of entities in production, reissuing so many inserts seems wasteful...

I've got a band-aid for now, but was looking for 'the right way' to get this done!

Thank you.
Alex

Issue with unassigned members / PHP 7.4 (Typed property must not be accessed before initialization)

Hi,

Under PHP 7.4 there is issue with unassigned members.


File:

    /project/module/.........../IdTrait.php:18

Message:

    Typed property Supplier::$id must not be accessed before initialization

Stack trace:

    #0 /project/vendor/doctrine/doctrine-laminas-hydrator/src/DoctrineObject.php(219):Supplier->getId()
    #1 /project/vendor/doctrine/doctrine-laminas-hydrator/src/DoctrineObject.php(119): Doctrine\Laminas\Hydrator\DoctrineObject->extractByValue()
    #2 /project/vendor/laminas/laminas-form/src/Fieldset.php(659): Doctrine\Laminas\Hydrator\DoctrineObject->extract()
    #3 /project/vendor/laminas/laminas-form/src/Form.php(979): Laminas\Form\Fieldset->extract()
    #4 /project/vendor/laminas/laminas-form/src/Form.php(314): Laminas\Form\Form->extract()
/**
 * @ORM\Id
 * @ORM\GeneratedValue(strategy="IDENTITY")
 * @ORM\Column(name="id", type="integer", nullable=false, options={"unsigned"=true})
 * @Annotation\Exclude()
 */
protected int $id;

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.