Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Drop Flyweight pattern #5036

Merged
merged 1 commit into from
Feb 5, 2022
Merged
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
38 changes: 38 additions & 0 deletions docs/en/reference/types.rst
Original file line number Diff line number Diff line change
Expand Up @@ -905,3 +905,41 @@ hook it into the database platform:
This would allow using a money type in the ORM for example and
have Doctrine automatically convert it back and forth to the
database.

It is also possible to register type instances directly, in case you
need to pass parameters to your instance::

<?php
namespace My\Project\Types;

use Doctrine\DBAL\Types\Type;
use Doctrine\DBAL\Platforms\AbstractPlatform;

final class StringReplacingType extends StringType
{
/**
* @param array<string, string> $replacements
*/
public function __construct(
private array $replacements,
) {
}

public function convertToDatabaseValue($value, AbstractPlatform $platform): string
{
return strtr($value, $this->replacements);
}
}

To do that, you can obtain the ``TypeRegistry`` singleton from ``Type``
and register your type in it::

<?php
Type::getTypeRegistry()->register('emojifyingType', new StringReplacingType(
[
':)' => '😊',
':(' => '😞',
':D' => '😄',
':P' => '😛',
]
));
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Although this paragraph is a how-to, the one above it is as well, and the DBAL docs do not have a cookbook/how-to section. Not sure what to do.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's fine to keep it here.

27 changes: 0 additions & 27 deletions src/Types/Exception/TypeAlreadyRegistered.php

This file was deleted.

1 change: 0 additions & 1 deletion src/Types/Type.php
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,6 @@ private static function createTypeRegistry(): TypeRegistry

/**
* Factory method to create type instances.
* Type instances are implemented as flyweights.
*
* @param string $name The name of the type.
*
Expand Down
28 changes: 3 additions & 25 deletions src/Types/TypeRegistry.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,20 @@
namespace Doctrine\DBAL\Types;

use Doctrine\DBAL\Exception;
use Doctrine\DBAL\Types\Exception\TypeAlreadyRegistered;
use Doctrine\DBAL\Types\Exception\TypeNotFound;
use Doctrine\DBAL\Types\Exception\TypeNotRegistered;
use Doctrine\DBAL\Types\Exception\TypesAlreadyExists;
use Doctrine\DBAL\Types\Exception\UnknownColumnType;

use function array_search;
use function in_array;

/**
* The type registry is responsible for holding a map of all known DBAL types.
* The types are stored using the flyweight pattern so that one type only exists as exactly one instance.
*/
final class TypeRegistry
{
/**
* Map of type names and their corresponding flyweight objects.
* Map of type names and their corresponding objects.
*
* @var array<string, Type>
*/
Expand Down Expand Up @@ -56,9 +53,9 @@ public function get(string $name): Type
*/
public function lookupName(Type $type): string
{
$name = $this->findTypeName($type);
$name = array_search($type, $this->instances, true);

if ($name === null) {
if ($name === false) {
throw TypeNotRegistered::new($type);
}

Expand All @@ -84,10 +81,6 @@ public function register(string $name, Type $type): void
throw TypesAlreadyExists::new($name);
}

if ($this->findTypeName($type) !== null) {
throw TypeAlreadyRegistered::new($type);
}

$this->instances[$name] = $type;
}

Expand All @@ -102,10 +95,6 @@ public function override(string $name, Type $type): void
throw TypeNotFound::new($name);
}

if (! in_array($this->findTypeName($type), [$name, null], true)) {
throw TypeAlreadyRegistered::new($type);
}

$this->instances[$name] = $type;
}

Expand All @@ -120,15 +109,4 @@ public function getMap(): array
{
return $this->instances;
}

private function findTypeName(Type $type): ?string
{
$name = array_search($type, $this->instances, true);

if ($name === false) {
return null;
}

return $name;
}
}
22 changes: 0 additions & 22 deletions tests/Types/Exception/TypeAlreadyRegisteredTest.php

This file was deleted.

23 changes: 7 additions & 16 deletions tests/Types/TypeRegistryTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ public function testRegister(): void
self::assertSame($newType, $this->registry->get('some'));
}

public function testRegisterWithAlradyRegisteredName(): void
public function testRegisterWithAlreadyRegisteredName(): void
{
$this->registry->register('some', new TextType());

Expand All @@ -96,10 +96,12 @@ public function testRegisterWithAlreadyRegisteredInstance(): void
{
$newType = new TextType();

$this->registry->register('some', $newType);

$this->expectException(Exception::class);
$this->registry->register('other', $newType);
$this->registry->register('type1', $newType);
$this->registry->register('type2', $newType);
self::assertSame(
$this->registry->get('type1'),
$this->registry->get('type2')
);
}

public function testOverride(): void
Expand All @@ -123,17 +125,6 @@ public function testOverrideAllowsExistingInstance(): void
self::assertSame($type, $this->registry->get('some'));
}

public function testOverrideWithAlreadyRegisteredInstance(): void
{
$newType = new TextType();

$this->registry->register('first', $newType);
$this->registry->register('second', new StringType());

$this->expectException(Exception::class);
$this->registry->override('second', $newType);
}

public function testOverrideWithUnknownType(): void
{
$this->expectException(Exception::class);
Expand Down