Parcourir la source

add support for lazyObject and lazyArray for deferred entity loading

phpdevcommunity il y a 1 mois
Parent
commit
72a0e43924

+ 9 - 0
src/Event/Create/PostCreateEvent.php

@@ -0,0 +1,9 @@
+<?php
+
+namespace PhpDevCommunity\PaperORM\Event\Create;
+
+use PhpDevCommunity\PaperORM\Event\PaperEvent;
+
+class PostCreateEvent extends PaperEvent
+{
+}

+ 10 - 0
src/Event/Create/PreCreateEvent.php

@@ -0,0 +1,10 @@
+<?php
+
+namespace PhpDevCommunity\PaperORM\Event\Create;
+
+
+use PhpDevCommunity\PaperORM\Event\PaperEvent;
+
+class PreCreateEvent extends PaperEvent
+{
+}

+ 10 - 0
src/Event/Delete/PostDeleteEvent.php

@@ -0,0 +1,10 @@
+<?php
+
+namespace PhpDevCommunity\PaperORM\Event\Delete;
+
+use PhpDevCommunity\PaperORM\Event\PaperEvent;
+
+class PostDeleteEvent extends PaperEvent
+{
+
+}

+ 10 - 0
src/Event/Delete/PreDeleteEvent.php

@@ -0,0 +1,10 @@
+<?php
+
+namespace PhpDevCommunity\PaperORM\Event\Delete;
+
+
+use PhpDevCommunity\PaperORM\Event\PaperEvent;
+
+class PreDeleteEvent extends PaperEvent
+{
+}

+ 3 - 1
src/Event/PostCreateEvent.php → src/Event/PaperEvent.php

@@ -6,8 +6,9 @@ use PhpDevCommunity\Listener\Event;
 use PhpDevCommunity\PaperORM\Entity\EntityInterface;
 use PhpDevCommunity\PaperORM\EntityManagerInterface;
 
-class PostCreateEvent extends Event
+abstract class PaperEvent extends Event
 {
+
     private EntityManagerInterface $em;
     private EntityInterface $entity;
 
@@ -36,4 +37,5 @@ class PostCreateEvent extends Event
     {
         return $this->em;
     }
+
 }

+ 0 - 39
src/Event/PreCreateEvent.php

@@ -1,39 +0,0 @@
-<?php
-
-namespace PhpDevCommunity\PaperORM\Event;
-
-use PhpDevCommunity\Listener\Event;
-use PhpDevCommunity\PaperORM\Entity\EntityInterface;
-use PhpDevCommunity\PaperORM\EntityManagerInterface;
-
-class PreCreateEvent extends Event
-{
-    private EntityManagerInterface $em;
-    private EntityInterface $entity;
-
-    /**
-     * PreCreateEvent constructor.
-     *
-     * @param EntityManagerInterface $em
-     * @param EntityInterface $entity
-     */
-    public function __construct(EntityManagerInterface $em, EntityInterface $entity)
-    {
-        $this->entity = $entity;
-        $this->em = $em;
-    }
-
-
-    public function getEntity(): EntityInterface
-    {
-        return $this->entity;
-    }
-
-    /**
-     * @return EntityManagerInterface
-     */
-    public function getEm(): EntityManagerInterface
-    {
-        return $this->em;
-    }
-}

+ 0 - 29
src/Event/PreUpdateEvent.php

@@ -1,29 +0,0 @@
-<?php
-
-namespace PhpDevCommunity\PaperORM\Event;
-
-use PhpDevCommunity\Listener\Event;
-use PhpDevCommunity\PaperORM\Entity\EntityInterface;
-
-class PreUpdateEvent extends Event
-{
-
-    private EntityInterface $entity;
-
-    /**
-     * PreCreateEvent constructor.
-     *
-     * @param EntityInterface $entity
-     */
-    public function __construct(EntityInterface $entity)
-    {
-        $this->entity = $entity;
-    }
-
-
-    public function getEntity(): EntityInterface
-    {
-        return $this->entity;
-    }
-
-}

+ 10 - 0
src/Event/Update/PostUpdateEvent.php

@@ -0,0 +1,10 @@
+<?php
+
+namespace PhpDevCommunity\PaperORM\Event\Update;
+
+use PhpDevCommunity\PaperORM\Event\PaperEvent;
+
+class PostUpdateEvent extends PaperEvent
+{
+
+}

+ 10 - 0
src/Event/Update/PreUpdateEvent.php

@@ -0,0 +1,10 @@
+<?php
+
+namespace PhpDevCommunity\PaperORM\Event\Update;
+
+use PhpDevCommunity\PaperORM\Event\PaperEvent;
+
+class PreUpdateEvent extends PaperEvent
+{
+
+}

+ 1 - 1
src/EventListener/PostCreateEventListener.php

@@ -3,7 +3,7 @@
 namespace PhpDevCommunity\PaperORM\EventListener;
 
 use PhpDevCommunity\PaperORM\Assigner\AutoIncrementAssigner;
-use PhpDevCommunity\PaperORM\Event\PostCreateEvent;
+use PhpDevCommunity\PaperORM\Event\Create\PostCreateEvent;
 use PhpDevCommunity\PaperORM\Mapper\ColumnMapper;
 use PhpDevCommunity\PaperORM\Mapping\Column\AutoIncrementColumn;
 

+ 24 - 0
src/EventListener/PostUpdateEventListener.php

@@ -0,0 +1,24 @@
+<?php
+
+namespace PhpDevCommunity\PaperORM\EventListener;
+
+use PhpDevCommunity\PaperORM\Assigner\AutoIncrementAssigner;
+use PhpDevCommunity\PaperORM\Event\Update\PostUpdateEvent;
+use PhpDevCommunity\PaperORM\Mapper\ColumnMapper;
+use PhpDevCommunity\PaperORM\Mapping\Column\AutoIncrementColumn;
+
+class PostUpdateEventListener
+{
+    public function __invoke(PostUpdateEvent $event)
+    {
+        $entity = $event->getEntity();
+        $em = $event->getEm();
+
+        $autoIncrementAssigner = new AutoIncrementAssigner($em->sequence());
+        foreach (ColumnMapper::getColumns($entity) as $column) {
+            if ($column instanceof AutoIncrementColumn) {
+                $autoIncrementAssigner->commit($column);
+            }
+        }
+    }
+}

+ 2 - 1
src/EventListener/PreCreateEventListener.php

@@ -7,7 +7,8 @@ use PhpDevCommunity\PaperORM\Assigner\SlugAssigner;
 use PhpDevCommunity\PaperORM\Assigner\TimestampAssigner;
 use PhpDevCommunity\PaperORM\Assigner\TokenAssigner;
 use PhpDevCommunity\PaperORM\Assigner\UuidAssigner;
-use PhpDevCommunity\PaperORM\Event\PreCreateEvent;
+
+use PhpDevCommunity\PaperORM\Event\Create\PreCreateEvent;
 use PhpDevCommunity\PaperORM\Mapper\ColumnMapper;
 use PhpDevCommunity\PaperORM\Mapping\Column\AutoIncrementColumn;
 use PhpDevCommunity\PaperORM\Mapping\Column\SlugColumn;

+ 4 - 5
src/EventListener/PreUpdateEventListener.php

@@ -2,11 +2,10 @@
 
 namespace PhpDevCommunity\PaperORM\EventListener;
 
-use DateTimeImmutable;
-use PhpDevCommunity\PaperORM\Event\PreUpdateEvent;
+use PhpDevCommunity\PaperORM\Assigner\TimestampAssigner;
+use PhpDevCommunity\PaperORM\Event\Update\PreUpdateEvent;
 use PhpDevCommunity\PaperORM\Mapper\ColumnMapper;
 use PhpDevCommunity\PaperORM\Mapping\Column\TimestampColumn;
-use PhpDevCommunity\PaperORM\Tools\EntityAccessor;
 
 class PreUpdateEventListener
 {
@@ -14,10 +13,10 @@ class PreUpdateEventListener
     public function __invoke(PreUpdateEvent $event)
     {
         $entity = $event->getEntity();
+        $timestampAssigner = new TimestampAssigner();
         foreach (ColumnMapper::getColumns($entity) as $column) {
             if ($column instanceof TimestampColumn && $column->isOnUpdated()) {
-                $property = $column->getProperty();
-                EntityAccessor::setValue($entity, $property, new DateTimeImmutable('now'));
+                $timestampAssigner->assign($entity, $column);
             }
         }
     }

+ 3 - 3
src/PaperConfiguration.php

@@ -6,9 +6,9 @@ use LogicException;
 use PhpDevCommunity\Listener\ListenerProvider;
 use PhpDevCommunity\PaperORM\Cache\EntityMemcachedCache;
 use PhpDevCommunity\PaperORM\Driver\DriverManager;
-use PhpDevCommunity\PaperORM\Event\PostCreateEvent;
-use PhpDevCommunity\PaperORM\Event\PreCreateEvent;
-use PhpDevCommunity\PaperORM\Event\PreUpdateEvent;
+use PhpDevCommunity\PaperORM\Event\Create\PostCreateEvent;
+use PhpDevCommunity\PaperORM\Event\Create\PreCreateEvent;
+use PhpDevCommunity\PaperORM\Event\Update\PreUpdateEvent;
 use PhpDevCommunity\PaperORM\EventListener\PostCreateEventListener;
 use PhpDevCommunity\PaperORM\EventListener\PreCreateEventListener;
 use PhpDevCommunity\PaperORM\EventListener\PreUpdateEventListener;

+ 23 - 6
src/Persistence/EntityPersistence.php

@@ -4,9 +4,12 @@ namespace PhpDevCommunity\PaperORM\Persistence;
 
 use PhpDevCommunity\PaperORM\Entity\EntityInterface;
 use PhpDevCommunity\PaperORM\EntityManagerInterface;
-use PhpDevCommunity\PaperORM\Event\PostCreateEvent;
-use PhpDevCommunity\PaperORM\Event\PreCreateEvent;
-use PhpDevCommunity\PaperORM\Event\PreUpdateEvent;
+use PhpDevCommunity\PaperORM\Event\Create\PostCreateEvent;
+use PhpDevCommunity\PaperORM\Event\Create\PreCreateEvent;
+use PhpDevCommunity\PaperORM\Event\Delete\PostDeleteEvent;
+use PhpDevCommunity\PaperORM\Event\Delete\PreDeleteEvent;
+use PhpDevCommunity\PaperORM\Event\Update\PostUpdateEvent;
+use PhpDevCommunity\PaperORM\Event\Update\PreUpdateEvent;
 use PhpDevCommunity\PaperORM\Hydrator\ReadOnlyEntityHydrator;
 use PhpDevCommunity\PaperORM\Mapper\ColumnMapper;
 use PhpDevCommunity\PaperORM\Mapper\EntityMapper;
@@ -49,6 +52,7 @@ class EntityPersistence
         if ($this->dispatcher) {
             $this->dispatcher->dispatch(new PreCreateEvent($this->em, $entity));
         }
+
         $schema = $this->platform->getSchema();
         $tableName = EntityMapper::getTable($entity);
         $qb = QueryBuilder::insert($schema->quote($tableName));
@@ -89,7 +93,7 @@ class EntityPersistence
         }
 
         if ($this->dispatcher) {
-            $this->dispatcher->dispatch(new PreUpdateEvent($entity));
+            $this->dispatcher->dispatch(new PreUpdateEvent($this->em, $entity));
         }
 
         if ($entity instanceof ProxyInterface) {
@@ -114,8 +118,13 @@ class EntityPersistence
             $values[$key] = $value;
         }
         $rows = $this->execute($qb, $values);
-        if ($rows > 0 && $entity instanceof ProxyInterface) {
-            $entity->__reset();
+        if ($rows > 0) {
+            if ($entity instanceof ProxyInterface) {
+                $entity->__reset();
+            }
+            if ($this->dispatcher) {
+                $this->dispatcher->dispatch(new PostUpdateEvent($this->em, $entity));
+            }
         }
         return $rows;
     }
@@ -130,6 +139,10 @@ class EntityPersistence
             throw new \LogicException(static::class . sprintf(' Cannot delete an entity %s without a primary key ', get_class($entity)));
         }
 
+        if ($this->dispatcher) {
+            $this->dispatcher->dispatch(new PreDeleteEvent($this->em, $entity));
+        }
+
         $tableName = EntityMapper::getTable($entity);
         $schema = $this->platform->getSchema();
         $qb = QueryBuilder::delete($schema->quote($tableName))
@@ -145,6 +158,10 @@ class EntityPersistence
             if ($this->managed->contains($entity)) {
                 $this->managed->detach($entity);
             }
+
+            if ($this->dispatcher) {
+                $this->dispatcher->dispatch(new PostDeleteEvent($this->em, $entity));
+            }
         }
         return $rows;
     }

+ 21 - 1
src/Query/Fetcher.php

@@ -75,15 +75,35 @@ final class Fetcher
     {
         return $this->getResult(QueryBuilder::HYDRATE_ARRAY);
     }
+    public function toLazyArray(): callable
+    {
+        return function () {
+            return $this->toArray();
+        };
+    }
 
     public function toObject()
     {
        return $this->getResult(QueryBuilder::HYDRATE_OBJECT);
     }
 
+    public function toLazyObject(): callable
+    {
+        return function () {
+            return $this->toObject();
+        };
+    }
+
     public function toReadOnlyObject()
     {
-        return $this->getResult(QueryBuilder::HYDRATE_OBJECT_READONLY)  ;
+        return $this->getResult(QueryBuilder::HYDRATE_OBJECT_READONLY) ;
+    }
+
+    public function toLazyReadOnlyObject(): callable
+    {
+        return function () {
+            return $this->toReadOnlyObject();
+        };
     }
 
     public function toCount(): int

+ 11 - 5
src/Query/QueryBuilder.php

@@ -28,8 +28,6 @@ final class QueryBuilder
     private SchemaInterface $schema;
     private EntityMemcachedCache $cache;
 
-    private string $primaryKey;
-
     private AliasGenerator $aliasGenerator;
     private array $select = [];
     private array $where = [];
@@ -42,13 +40,12 @@ final class QueryBuilder
 
     private array $params = [];
 
-    public function __construct(EntityManagerInterface $em, string $primaryKey = 'id')
+    public function __construct(EntityManagerInterface $em)
     {
         $this->platform = $em->getPlatform();
         $this->schema = $this->platform->getSchema();;
         $this->cache = $em->getCache();
         $this->aliasGenerator = new AliasGenerator();
-        $this->primaryKey = $primaryKey;
     }
 
     public function getResultIterator(string $hydrationMode = self::HYDRATE_OBJECT): iterable
@@ -314,7 +311,16 @@ final class QueryBuilder
             $properties = ColumnMapper::getColumns($entityName);
         }
         $columns = $this->convertPropertiesToColumns($entityName, $properties);
-        $joinQl = new JoinQL($this->platform->getConnection()->getPdo(), $this->primaryKey);
+        $primaryKey = ColumnMapper::getPrimaryKeyColumnName($entityName);
+        $primaryKeyQuoted = $this->schema->quote($primaryKey);
+        if (!in_array($primaryKeyQuoted, $columns)) {
+            $columns[] = $primaryKeyQuoted;
+        }
+        if ($columns[0] !== $primaryKeyQuoted) {
+            $columns = array_unique([$primaryKeyQuoted, ...$columns]);
+        }
+
+        $joinQl = new JoinQL($this->platform->getConnection()->getPdo(), $primaryKey);
         $joinQl->select($this->schema->quote($table), $alias, $columns);
         foreach ($this->joins as $join) {
             $fromAlias = $join['fromAlias'];

+ 1 - 2
tests/Entity/InvoiceTest.php

@@ -35,8 +35,7 @@ class InvoiceTest implements EntityInterface
         return [
             (new PrimaryKeyColumn())->bindProperty('id'),
             (new AutoIncrementColumn(null, 'invoice.number', 6, 'INV-{YYYY}-'))->bindProperty('number'),
-            (new AutoIncrementColumn(null, 'invoice.code', 8, null))->bindProperty('code'),
-            (new JoinColumn('post_id', PostTest::class))->bindProperty('post'),
+            (new AutoIncrementColumn(null, 'invoice.code', 8, null))->bindProperty('code')
         ];
     }
 

+ 1 - 0
tests/PersistAndFlushTest.php

@@ -55,6 +55,7 @@ class PersistAndFlushTest extends TestCase
         $em->persist($user);
         $em->flush();
 
+
         $this->assertStringLength($user->getToken(), 32);
         $this->assertNotNull($user->getId());
         $this->assertInstanceOf(\DateTimeInterface::class, $user->getCreatedAt());