diff --git a/readme.md b/readme.md index 67fabfa..48d2355 100644 --- a/readme.md +++ b/readme.md @@ -54,7 +54,9 @@ class User implements Serializable The `serializes` method returns an array of the properties that you want to serialize. Then the package will automatically serialize and deserialize the data based on the type hinted properties. -> Note: The package will only serialize public properties that are type hinted. +> **Note** +> - The package will only serialize public properties that are type hinted. +> - The package will serialize properties in the order they are defined in the `serialize` method. ### Serialization Handlers @@ -72,7 +74,7 @@ class UserHandler implements SerializationHandler { $this->userRepository = $userRepository; } - public function serialize($value): string + public function serialize(Serializable $serializable, $value): string { return $value->getId(); } @@ -82,7 +84,7 @@ class UserHandler implements SerializationHandler { * * @return ?User */ - public function deserialize($value): ?User + public function deserialize(Serializable $serializable, $value): ?User { return $this->userRepository->find($value); } diff --git a/src/Contracts/SerializationHandler.php b/src/Contracts/SerializationHandler.php index 41e1a61..a0e9f1c 100644 --- a/src/Contracts/SerializationHandler.php +++ b/src/Contracts/SerializationHandler.php @@ -9,12 +9,12 @@ interface SerializationHandler * * @return mixed */ - public function serialize($value); + public function serialize(Serializable $serializable, $value); /** * @param mixed $value * * @return mixed */ - public function deserialize($value); + public function deserialize(Serializable $serializable, $value); } diff --git a/src/Laravel/ModelSerializationHandler.php b/src/Laravel/ModelSerializationHandler.php index 07c35b1..75f525f 100644 --- a/src/Laravel/ModelSerializationHandler.php +++ b/src/Laravel/ModelSerializationHandler.php @@ -2,8 +2,10 @@ namespace YouCanShop\Cereal\Laravel; +use Illuminate\Contracts\Database\ModelIdentifier; use Illuminate\Database\Eloquent\Model; use Illuminate\Queue\SerializesAndRestoresModelIdentifiers; +use YouCanShop\Cereal\Contracts\Serializable; use YouCanShop\Cereal\Contracts\SerializationHandler; final class ModelSerializationHandler implements SerializationHandler @@ -13,19 +15,19 @@ final class ModelSerializationHandler implements SerializationHandler /** * @param Model $value * - * @return mixed + * @return ModelIdentifier|mixed */ - public function serialize($value) + public function serialize(Serializable $serializable, $value) { return $this->getSerializedPropertyValue($value); } /** - * @param $value + * @param ModelIdentifier|mixed $value * * @return mixed */ - public function deserialize($value) + public function deserialize(Serializable $serializable, $value) { return $this->getRestoredPropertyValue($value); } diff --git a/src/SerializationHandlerFactory.php b/src/SerializationHandlerFactory.php index 2c5e9ad..b990885 100644 --- a/src/SerializationHandlerFactory.php +++ b/src/SerializationHandlerFactory.php @@ -25,6 +25,7 @@ public static function getInstance(): self return self::$instance; } + public function getHandler(string $type): SerializationHandler { if (!isset($this->handlers[$type])) { diff --git a/src/Serializer.php b/src/Serializer.php index 59ee710..a79aeac 100644 --- a/src/Serializer.php +++ b/src/Serializer.php @@ -53,7 +53,10 @@ private function serialize(): void $this->serializations[$propertyName] = $this->getSerializationHandlerFactory() ->getHandler($type->getName()) - ->serialize($this->serializable->$propertyName); + ->serialize( + $this->serializable, + $this->serializable->$propertyName + ); } } @@ -98,7 +101,10 @@ public function deserialize(): void $this->serializable->$propertyName = $this->getSerializationHandlerFactory() ->getHandler($type->getName()) - ->deserialize($serialized); + ->deserialize( + $this->serializable, + $serialized + ); } } } diff --git a/tests/Unit/SerializerTest.php b/tests/Unit/SerializerTest.php index dd48554..322e026 100644 --- a/tests/Unit/SerializerTest.php +++ b/tests/Unit/SerializerTest.php @@ -2,10 +2,10 @@ namespace Tests; +use YouCanShop\Cereal\Cereal; use YouCanShop\Cereal\Contracts\Serializable; use YouCanShop\Cereal\Contracts\SerializationHandler; use YouCanShop\Cereal\SerializationHandlerFactory; -use YouCanShop\Cereal\Cereal; it('serializes scalar types', function () { class User implements Serializable @@ -77,21 +77,23 @@ public function __construct(array $lookupTable) } /** + * @param Serializable $serializable * @param Something $value * * @return string */ - public function serialize($value): string + public function serialize(Serializable $serializable, $value): string { return $value->getId(); } /** + * @param Serializable $serializable * @param string $value * * @return Something */ - public function deserialize($value): Something + public function deserialize(Serializable $serializable, $value): Something { return $this->lookupTable[$value]; } @@ -125,3 +127,80 @@ public function serializes(): array expect($deserialized->thing->getId()) ->toEqual($wrapper->thing->getId()); }); + +it('respects the serialization order', function () { + class Number + { + public int $value; + + public function __construct(int $value) + { + $this->value = $value; + } + } + + class SomeList implements Serializable + { + use Cereal; + + public Number $first; + public Number $second; + public Number $third; + + public function __construct(Number $first, Number $second, Number $third) + { + $this->first = $first; + $this->second = $second; + $this->third = $third; + } + + public function serializes(): array + { + return ['first', 'second', 'third']; + } + } + + class Handler implements SerializationHandler + { + /** + * @param Serializable $serializable + * @param Number $value + * + * @return mixed + */ + public function serialize(Serializable $serializable, $value) + { + return $value->value; + } + + /** + * @param Serializable $serializable + * @param int $value + * + * @return \Tests\Number + */ + public function deserialize(Serializable $serializable, $value): Number + { + if ($value === 4) { + expect($serializable->first) + ->toBeInstanceOf(Number::class) + ->and($serializable->first->value) + ->toEqual(2); + } + + return new Number($value); + } + } + + SerializationHandlerFactory::getInstance() + ->addHandler(Number::class, new Handler); + + $list = new SomeList( + new Number(2), + new Number(4), + new Number(8) + ); + + $serialized = serialize($list); + unserialize($serialized); +});