Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 0 additions & 28 deletions src/Mongo/MongoPersistenceStrategy.php
Original file line number Diff line number Diff line change
Expand Up @@ -95,32 +95,4 @@ public function isScheduledForInsert(object $object): bool

return $uow->isScheduledForInsert($object) || $uow->isScheduledForUpsert($object);
}

public function findBy(string $class, array $criteria, ?array $orderBy = null, ?int $limit = null, ?int $offset = null): array
{
$qb = $this->objectManagerFor($class)
->getRepository($class)
->createQueryBuilder()
->refresh();

foreach ($criteria as $field => $value) {
$qb->field($field)->equals($value);
}

if ($orderBy) {
foreach ($orderBy as $field => $direction) {
$qb->sort($field, $direction);
}
}

if ($limit) {
$qb->limit($limit);
}

if ($offset) {
$qb->skip($offset);
}

return $qb->getQuery()->execute()->toArray(); // @phpstan-ignore method.nonObject
}
}
33 changes: 0 additions & 33 deletions src/ORM/AbstractORMPersistenceStrategy.php
Original file line number Diff line number Diff line change
Expand Up @@ -97,37 +97,4 @@ final public function managedNamespaces(): array

return \array_values(\array_merge(...$namespaces));
}

final public function findBy(string $class, array $criteria, ?array $orderBy = null, ?int $limit = null, ?int $offset = null): array
{
$qb = $this->objectManagerFor($class)->getRepository($class)->createQueryBuilder('o');

foreach ($criteria as $field => $value) {
$paramName = \str_replace('.', '_', $field);
if (\is_array($value)) {
$qb->andWhere("o.{$field} IN(:{$paramName})");
} else {
$qb->andWhere("o.{$field} = :{$paramName}");
}
$qb->setParameter($paramName, $value);
}

if ($orderBy) {
foreach ($orderBy as $field => $direction) {
$qb->addOrderBy('o.'.$field, $direction);
}
}

if ($limit) {
$qb->setMaxResults($limit);
}

if ($offset) {
$qb->setFirstResult($offset);
}

return $qb->getQuery()
->setHint(Query::HINT_REFRESH, true)
->getResult();
}
}
17 changes: 0 additions & 17 deletions src/Persistence/PersistenceManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -419,23 +419,6 @@ public static function isOrmOnly(): bool
})();
}

/**
* @template T of object
*
* @param class-string<T> $class
* @param array<string, mixed> $criteria
* @param array<string, string>|null $orderBy
* @phpstan-param array<string, 'asc'|'desc'|'ASC'|'DESC'>|null $orderBy
*
* @return list<T>
*/
public function findBy(string $class, array $criteria = [], ?array $orderBy = null, ?int $limit = null, ?int $offset = null): array
{
$class = ProxyGenerator::unwrap($class);

return $this->strategyFor($class)->findBy($class, $criteria, $orderBy, $limit, $offset);
}

private function flushAllStrategies(): void
{
foreach ($this->strategies as $strategy) {
Expand Down
14 changes: 0 additions & 14 deletions src/Persistence/PersistenceStrategy.php
Original file line number Diff line number Diff line change
Expand Up @@ -92,20 +92,6 @@ public function getIdentifierValues(object $object): array
*/
abstract public function managedNamespaces(): array;

/**
* Uses a query builder to be able to pass hints to UoW and to force Doctrine to return fresh objects.
*
* @template T of object
*
* @param class-string<T> $class
* @param array<string, mixed> $criteria
* @param array<string, string>|null $orderBy
* @phpstan-param array<string, 'asc'|'desc'|'ASC'|'DESC'>|null $orderBy
*
* @return list<T>
*/
abstract public function findBy(string $class, array $criteria, ?array $orderBy = null, ?int $limit = null, ?int $offset = null): array;

/**
* @param class-string $owner
*
Expand Down
23 changes: 15 additions & 8 deletions src/Persistence/Proxy/PersistedObjectsTracker.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ public function add(object ...$objects): void
{
foreach ($objects as $object) {
if (self::$buffer->offsetExists($object) && self::$buffer[$object]) {
self::proxifyObject($object, self::$buffer[$object]);

continue;
}

Expand Down Expand Up @@ -78,16 +80,21 @@ private static function proxifyObjects(): void
continue;
}

$reflector = new \ReflectionClass($object);
self::proxifyObject($object, $id);
}
}

if ($reflector->isUninitializedLazyObject($object)) {
continue;
}
private static function proxifyObject(object $object, mixed $id): void
{
$reflector = new \ReflectionClass($object);

$clone = clone $object;
$reflector->resetAsLazyGhost($object, function($object) use ($clone, $id) {
Configuration::instance()->persistence()->autorefresh($object, $id, $clone);
});
if ($reflector->isUninitializedLazyObject($object)) {
return;
}

$clone = clone $object;
$reflector->resetAsLazyGhost($object, function($object) use ($clone, $id) {
Configuration::instance()->persistence()->autorefresh($object, $id, $clone);
});
}
}
15 changes: 1 addition & 14 deletions src/Persistence/RepositoryDecorator.php
Original file line number Diff line number Diff line change
Expand Up @@ -133,20 +133,7 @@ public function findAll(): array
*/
public function findBy(array $criteria, ?array $orderBy = null, $limit = null, $offset = null): array
{
if ($this->inMemory) {
$results = $this->inner()->findBy($this->normalize($criteria), $orderBy, $limit, $offset);
} else {
try {
$results = Configuration::instance()->persistence()->findBy($this->class, $this->normalize($criteria), $orderBy, $limit, $offset);
} catch (\LogicException|\Error) {
// prevent entities/documents with readonly properties to create an error
// LogicException is for ORM / Error is for ODM
// @see https://github.com/doctrine/orm/issues/9505
$results = $this->inner()->findBy($this->normalize($criteria), $orderBy, $limit, $offset);
}
}

$objects = \array_values($results);
$objects = \array_values($this->inner()->findBy($this->normalize($criteria), $orderBy, $limit, $offset));

if (!$this instanceof ProxyRepositoryDecorator) {
Configuration::instance()->persistedObjectsTracker?->add(...$objects);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
<?php

declare(strict_types=1);

/*
* This file is part of the zenstruck/foundry package.
*
* (c) Kevin Bond <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Zenstruck\Foundry\Tests\Fixture\Entity\EdgeCases\ManyToOneWithAutoGeneratedUlid;

use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\IdGenerator\UlidGenerator;
use Symfony\Bridge\Doctrine\Types\UlidType;
use Symfony\Component\Uid\Ulid;

/**
* @author Nicolas PHILIPPE <[email protected]>
*/
#[ORM\Entity]
#[ORM\Table('many_to_one_with_auto_generated_ulid_inverse')]
class InverseSide
{
#[ORM\Id]
#[ORM\Column(type: UlidType::NAME, unique: true)]
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
#[ORM\CustomIdGenerator(class: UlidGenerator::class)]
public ?Ulid $id = null;

/** @var Collection<int,OwningSide> */
#[ORM\OneToMany(targetEntity: OwningSide::class, mappedBy: 'inverseSide', cascade: ['persist'])]
public Collection $owningSides;

public function __construct() {
$this->owningSides = new ArrayCollection();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

declare(strict_types=1);

/*
* This file is part of the zenstruck/foundry package.
*
* (c) Kevin Bond <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Zenstruck\Foundry\Tests\Fixture\Entity\EdgeCases\ManyToOneWithAutoGeneratedUlid;

use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\IdGenerator\UlidGenerator;
use Symfony\Bridge\Doctrine\Types\UlidType;
use Symfony\Component\Uid\Ulid;

/**
* @author Nicolas PHILIPPE <[email protected]>
*/
#[ORM\Entity]
#[ORM\Table('many_to_one_with_auto_generated_ulid_owning')]
class OwningSide
{
#[ORM\Id]
#[ORM\Column(type: UlidType::NAME, unique: true)]
#[ORM\GeneratedValue(strategy: 'CUSTOM')]
#[ORM\CustomIdGenerator(class: UlidGenerator::class)]
public ?Ulid $id = null;

#[ORM\ManyToOne(cascade: ['persist'], inversedBy: 'owningSides')]
public ?InverseSide $inverseSide = null;
}
15 changes: 15 additions & 0 deletions tests/Integration/ORM/EdgeCasesRelationshipTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
use Zenstruck\Foundry\Tests\Fixture\Entity\EdgeCases\InversedOneToOneWithoutNullable;
use Zenstruck\Foundry\Tests\Fixture\Entity\EdgeCases\InversedOneToOneWithSetter;
use Zenstruck\Foundry\Tests\Fixture\Entity\EdgeCases\ManyToOneToSelfReferencing;
use Zenstruck\Foundry\Tests\Fixture\Entity\EdgeCases\ManyToOneWithAutoGeneratedUlid;
use Zenstruck\Foundry\Tests\Fixture\Entity\EdgeCases\OneToManyWithUnionType;
use Zenstruck\Foundry\Tests\Fixture\Entity\EdgeCases\RichDomainMandatoryRelationship;
use Zenstruck\Foundry\Tests\Fixture\Factories\Entity\EdgeCases\MultipleMandatoryRelationshipToSameEntity;
Expand Down Expand Up @@ -304,6 +305,20 @@ static function(InversedOneToOneWithNonNullableOwning\OwningSide $o) use ($inver
self::assertSame($owningSide, $owningSide->inverseSide->getOwningSide());
}

/**
* @test
*/
#[Test]
public function it_can_find_and_object_with_ulid_as_id(): void
{
$this->expectNotToPerformAssertions();

$inverseSide = persistent_factory(ManyToOneWithAutoGeneratedUlid\InverseSide::class)->create();

persistent_factory(ManyToOneWithAutoGeneratedUlid\OwningSide::class)->many(2)->create(['inverseSide' => $inverseSide]);
persistent_factory(ManyToOneWithAutoGeneratedUlid\OwningSide::class)::random(['inverseSide' => $inverseSide]);
}

/**
* @test
*/
Expand Down