├── .env
├── .env.dist
├── .gitignore
├── .travis.yml
├── LICENSE
├── README.md
├── autoload.php
├── cache
└── .gitkeep
├── composer.json
├── docker-compose.yml
├── docker
├── hhvm
│ ├── Dockerfile
│ └── entrypoint.sh
└── php
│ ├── Dockerfile
│ ├── config
│ └── php.ini
│ └── entrypoint.sh
├── phpbench.json.dist
└── src
├── AbstractBench.php
├── Bench
├── BetterSerializerBenchmark.php
├── GsonBenchmark.php
├── IvoryBenchmark.php
├── JmsBenchmark.php
├── JmsMinimalBenchmark.php
├── JsonSerializableBenchmark.php
├── SerializardClosureBenchmark.php
├── SerializardReflectionBenchmark.php
├── SymfonyGetSetNormalizerBenchmark.php
├── SymfonyObjectNormalizerBenchmark.php
└── TSantosBenchmark.php
├── BenchExtension.php
├── BenchFinder.php
├── Command
└── InfoCommand.php
├── DataProvider.php
└── Model
├── Category.php
├── Comment.php
├── Forum.php
├── Thread.php
├── TimestampableTrait.php
└── User.php
/.env:
--------------------------------------------------------------------------------
1 | # Permissions
2 | GROUP_ID=1000
3 | USER_ID=1000
4 |
--------------------------------------------------------------------------------
/.env.dist:
--------------------------------------------------------------------------------
1 | # Permissions
2 | GROUP_ID=1000
3 | USER_ID=1000
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | /.env
2 | /cache/*
3 | !/cache/.gitkeep
4 | /vendor
5 | /composer.lock
6 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: php
2 | #
3 | #branches:
4 | # only: master
5 |
6 | matrix:
7 | fast_finish: true
8 | include:
9 | - php: 7.2
10 |
11 | install:
12 | - phpenv config-rm xdebug.ini || echo 'xdebug not available'
13 | - phpenv config-add docker/php/config/php.ini
14 | - composer install --classmap-authoritative
15 |
16 | script:
17 | - ./vendor/bin/phpbench info
18 | - ./vendor/bin/phpbench run --report=bench --progress=travis
19 |
20 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2016-2017 Eric GELOEN
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
4 | documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
5 | rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
6 | persons to whom the Software is furnished to do so, subject to the following conditions:
7 |
8 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
9 | Software.
10 |
11 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
12 | WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
13 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
14 | OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
15 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # README
2 |
3 | This project benchmarks the most popular & feature rich PHP serializers. It measures the time consumed during the
4 | serialization of an object graph and give you a report of the execution.
5 |
6 | The result of the benchmark is directly available on travis: https://travis-ci.org/php-serializers/ivory-serializer-benchmark
7 |
8 | This repository is a fork of [egeloen/ivory-serializer-benchmark](https://github.com/egeloen/ivory-serializer-benchmark),
9 | the project was looking not maintained for a while, please refer to this as the next reference point when benchmarking
10 | PHP serializers.
11 |
12 | ## Documentation
13 |
14 | If you're interesting to use the project locally, follow the next steps.
15 |
16 | ### Set up the project
17 |
18 | The easiest way to set up the project is to install [Docker](https://www.docker.com) and
19 | [Docker Composer](https://docs.docker.com/compose/) and build the project. The configuration is shipped with a
20 | distribution environment file allowing you to customize your current user/group ID:
21 |
22 | ``` bash
23 | $ cp .env.dist .env
24 | ```
25 |
26 | **The most important part is the `USER_ID` and `GROUP_ID` which should match your current user/group.**
27 |
28 | Once you have configured your environment, you can build the project:
29 |
30 | ``` bash
31 | $ docker-compose build
32 | ```
33 |
34 | ### Install dependencies
35 |
36 | Install the dependencies via [Composer](https://getcomposer.org/):
37 |
38 | ``` bash
39 | $ docker-compose run --rm php composer install
40 | ```
41 |
42 | ### Benchmark
43 |
44 | We use [PHPBench](https://phpbench.readthedocs.io/) internally, with sane defaults setup for benchmarking the serializers.
45 |
46 | To benchmark serialization, you can use:
47 |
48 | ``` bash
49 | $ docker-compose run --rm php ./vendor/bin/phpbench run --report=bench
50 | ```
51 |
52 | By default, the benchmark runs 5 [Revolutions](https://phpbench.readthedocs.io/en/latest/writing-benchmarks.html#improving-precision-revolutions) and 5 [Iterations](https://phpbench.readthedocs.io/en/latest/writing-benchmarks.html#verifying-and-improving-stability-iterations).
53 | You can override either with the `iterations` and `revs` options.
54 |
55 | ``` bash
56 | $ docker-compose run --rm php ./vendor/bin/phpbench run --report=bench --iterations=10 --revs=10
57 | ```
58 |
59 | By default, the benchmark runs different configurations of horizontal and vertical complexity.
60 | If you wish to specify your own, you can use the `parameters` option which is an array of two
61 | integers, the first representing the horizontal and the second representing the vertical complexity.
62 |
63 | ``` bash
64 | $ docker-compose run --rm php ./vendor/bin/phpbench run --report=bench --parameters='[1,2]'
65 | ```
66 |
67 | If you want to run the benchmark only for a specific or subset of serializers, you can use the `filter` option:
68 |
69 | ``` bash
70 | $ docker-compose run --rm php ./vendor/bin/phpbench run --report=bench --filter=Symfony
71 | ```
72 |
73 | ### Available serializers
74 |
75 | You can see a list of the serializer available and its current version by running the following command:
76 |
77 | ``` bash
78 | $ docker-compose run --rm php ./vendor/bin/phpbench info
79 | ```
80 |
81 | Available implementations:
82 |
83 | * `BetterSerializer`
84 | * `Ivory`
85 | * `JaneAutomapper`
86 | * `Jms`
87 | * `JmsMinimal`
88 | * `JsonSerializable`
89 | * `SerializardClosure`
90 | * `SerializardReflection`
91 | * `SymfonyGetSetNormalizer`
92 | * `SymfonyObjectNormalizer`
93 | * `TSantos`
94 | * `Gson`
95 |
96 |
97 | ## Contribute
98 |
99 | We love contributors! PhpSerializers is an open source project. If you'd like to contribute, feel free to propose a PR!.
100 |
101 | ## License
102 |
103 | The Php Serializers Benchmark is under the MIT license. For the full copyright and license information, please read the
104 | [LICENSE](/LICENSE) file that was distributed with this source code.
105 |
--------------------------------------------------------------------------------
/autoload.php:
--------------------------------------------------------------------------------
1 | > /etc/hhvm/php.ini
12 | fi
13 |
14 | # Remove XDebug temporary configuration
15 | rm -f /var/www/xdebug.ini
16 |
17 | # Permissions
18 | groupmod -g ${GROUP_ID} www-data
19 | usermod -u ${USER_ID} www-data
20 |
21 | # Start bash or forward command
22 | if [ "$1" = "bash" ]; then
23 | su www-data
24 | else
25 | su www-data -c "$*"
26 | fi
27 |
--------------------------------------------------------------------------------
/docker/php/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM php:7.2
2 |
3 | # APT packages
4 | RUN apt-get update && apt-get install -y \
5 | zlib1g-dev \
6 | git \
7 | && rm -rf /var/lib/apt/lists/*
8 |
9 | # APCU extension
10 | RUN pecl install apcu \
11 | && docker-php-ext-enable apcu \
12 | && rm -rf /tmp/pear
13 |
14 | ## PHP configuration
15 | COPY config/php.ini /usr/local/etc/php/php.ini
16 |
17 | # Composer
18 | RUN curl -sS https://getcomposer.org/installer | php -- --filename=composer --install-dir=/usr/local/bin
19 |
20 | # Bash
21 | RUN chsh -s /bin/bash www-data
22 |
23 | # Workdir
24 | WORKDIR /var/www/html
25 |
26 | # Entrypoint
27 | COPY entrypoint.sh /usr/local/bin/entrypoint.sh
28 | ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]
29 |
--------------------------------------------------------------------------------
/docker/php/config/php.ini:
--------------------------------------------------------------------------------
1 | apc.enabled=1
2 | apc.enable_cli=1
3 | memory_limit = -1
4 | opcache.enable_cli = 1
5 | session.gc_probability = 0
6 | extension = apcu.so
7 |
--------------------------------------------------------------------------------
/docker/php/entrypoint.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -e
4 |
5 | GROUP_ID=${GROUP_ID-1000}
6 | USER_ID=${USER_ID-1000}
7 | XDEBUG=${XDEBUG-0}
8 |
9 | # Disable XDebug
10 | if [ ! "$XDEBUG" = 1 ]; then
11 | rm -f /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini /usr/local/etc/php/conf.d/xdebug.ini
12 | fi
13 |
14 | # Permissions
15 | groupmod -g ${GROUP_ID} www-data
16 | usermod -u ${USER_ID} www-data
17 |
18 | # Start bash or forward command
19 | if [ "$1" = "bash" ]; then
20 | su www-data
21 | else
22 | su www-data -c "$*"
23 | fi
24 |
--------------------------------------------------------------------------------
/phpbench.json.dist:
--------------------------------------------------------------------------------
1 | {
2 | "bootstrap": "autoload.php",
3 | "path": "src/Bench",
4 | "reports": {
5 | "bench": {
6 | "extends": "aggregate",
7 | "break": ["params"],
8 | "cols": [ "benchmark", "mean", "diff", "worst", "best", "mem_real" ],
9 | "sort": {"mean": "asc"}
10 | }
11 | },
12 | "extensions": [
13 | "PhpSerializers\\Benchmarks\\BenchExtension"
14 | ]
15 | }
16 |
--------------------------------------------------------------------------------
/src/AbstractBench.php:
--------------------------------------------------------------------------------
1 | dataProvider = new DataProvider();
26 | }
27 |
28 | final public function initData(array $params): void
29 | {
30 | $this->data = $this->dataProvider->getData(...$params);
31 | }
32 |
33 | /**
34 | * @ParamProviders("provideComplexity")
35 | */
36 | final public function benchSerialize(): void
37 | {
38 | $this->serialize($this->data);
39 | }
40 |
41 | public function provideComplexity(): array
42 | {
43 | return [
44 | [10, 10],
45 | [1, 60],
46 | [60, 1],
47 | [60, 60],
48 | ];
49 | }
50 |
51 | abstract public function initSerializer(): void;
52 |
53 | abstract protected function serialize(Forum $data): void;
54 |
55 | abstract public function getPackageName(): string;
56 |
57 | abstract public function getNote(): string;
58 | }
59 |
--------------------------------------------------------------------------------
/src/Bench/BetterSerializerBenchmark.php:
--------------------------------------------------------------------------------
1 | enableApcuCache();
31 | } else {
32 | $builder->enableFilesystemCache(dirname(__DIR__, 1) . '/cache/better-serializer');
33 | }
34 |
35 | $this->serializer = $builder->createSerializer();
36 | }
37 |
38 | /**
39 | * {@inheritdoc}
40 | */
41 | public function serialize(Forum $data): void
42 | {
43 | $this->serializer->serialize(
44 | $data,
45 | SerializationType::JSON()
46 | );
47 | }
48 |
49 | public function getPackageName(): string
50 | {
51 | return 'better-serializer/better-serializer';
52 | }
53 |
54 | public function getNote(): string
55 | {
56 | return <<<'NOTE'
57 | Serializer for PHP 7.2+ supporting JSON
58 | NOTE;
59 | }
60 | }
61 |
--------------------------------------------------------------------------------
/src/Bench/GsonBenchmark.php:
--------------------------------------------------------------------------------
1 |
15 | */
16 | class GsonBenchmark extends AbstractBench
17 | {
18 | /**
19 | * @var Gson
20 | */
21 | private $gson;
22 |
23 | public function initSerializer(): void
24 | {
25 | $cache = new ApcuCache();
26 | $this->gson = Gson::builder()
27 | ->enableCache(true)
28 | ->setCache($cache)
29 | ->setEnableScalarAdapters(false)
30 | ->setPropertyNamingPolicy(PropertyNamingPolicy::IDENTITY)
31 | ->build();
32 | }
33 |
34 | public function serialize(Forum $data): void
35 | {
36 | $this->gson->toJson($data);
37 | }
38 |
39 | public function getPackageName(): string
40 | {
41 | return 'tebru/gson-php';
42 | }
43 |
44 | public function getNote(): string
45 | {
46 | return <<<'NOTE'
47 | Serialize object graphs
48 | NOTE;
49 | }
50 | }
51 |
--------------------------------------------------------------------------------
/src/Bench/IvoryBenchmark.php:
--------------------------------------------------------------------------------
1 |
20 | */
21 | class IvoryBenchmark extends AbstractBench
22 | {
23 | /**
24 | * @var Serializer
25 | */
26 | private $serializer;
27 |
28 | public function initSerializer(): void
29 | {
30 | $classMetadataFactory = new CacheClassMetadataFactory(
31 | ClassMetadataFactory::create(),
32 | new ApcuAdapter('IvoryMetadata')
33 | );
34 |
35 | $typeRegistry = TypeRegistry::create([
36 | Type::OBJECT => new ObjectType($classMetadataFactory),
37 | ]);
38 |
39 | $this->serializer = new Serializer(new Navigator($typeRegistry));
40 | }
41 |
42 | public function serialize(Forum $data): void
43 | {
44 | $this->serializer->serialize($data, 'json');
45 | }
46 |
47 | public function getPackageName(): string
48 | {
49 | return 'egeloen/serializer';
50 | }
51 |
52 | public function getNote(): string
53 | {
54 | return <<<'NOTE'
55 | Serializer for PHP 5.6+ supporting JSON, XML, YAML & CSV
56 | NOTE;
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/Bench/JmsBenchmark.php:
--------------------------------------------------------------------------------
1 |
18 | */
19 | class JmsBenchmark extends AbstractBench
20 | {
21 | /**
22 | * @var Serializer
23 | */
24 | private $serializer;
25 |
26 | public function initSerializer(): void
27 | {
28 | $cache = new ApcuCache();
29 | $this->serializer = SerializerBuilder::create()
30 | ->setAnnotationReader(new CachedReader(new AnnotationReader(), $cache, false))
31 | ->setMetadataCache(new DoctrineCacheAdapter(__CLASS__, $cache))
32 | ->build();
33 | }
34 |
35 | public function serialize(Forum $data): void
36 | {
37 | $this->serializer->serialize($data, 'json');
38 | }
39 |
40 | public function getPackageName(): string
41 | {
42 | return 'jms/serializer';
43 | }
44 |
45 | public function getNote(): string
46 | {
47 | return <<<'NOTE'
48 | Serialize object graphs with default handlers enabled
49 | NOTE;
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/Bench/JmsMinimalBenchmark.php:
--------------------------------------------------------------------------------
1 |
18 | */
19 | class JmsMinimalBenchmark extends AbstractBench
20 | {
21 | /**
22 | * @var Serializer
23 | */
24 | private $serializer;
25 |
26 | public function initSerializer(): void
27 | {
28 | $cache = new ApcuCache();
29 | $this->serializer = SerializerBuilder::create()
30 | ->setAnnotationReader(new CachedReader(new AnnotationReader(), $cache, false))
31 | ->setMetadataCache(new DoctrineCacheAdapter(__CLASS__, $cache))
32 | ->configureListeners(function () {
33 | })
34 | ->configureHandlers(function () {
35 | })
36 | ->build();
37 | }
38 |
39 | public function serialize(Forum $data): void
40 | {
41 | $this->serializer->serialize($data, 'json');
42 | }
43 |
44 | public function getPackageName(): string
45 | {
46 | return 'jms/serializer';
47 | }
48 |
49 | public function getNote(): string
50 | {
51 | return <<<'NOTE'
52 | Serialize object graphs with a minimal set of handlers
53 | NOTE;
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/Bench/JsonSerializableBenchmark.php:
--------------------------------------------------------------------------------
1 |
11 | */
12 | class JsonSerializableBenchmark extends AbstractBench
13 | {
14 | public function initSerializer(): void
15 | {
16 |
17 | }
18 |
19 | public function serialize($data): void
20 | {
21 | json_encode(
22 | $data
23 | );
24 | }
25 |
26 | public function getPackageName(): string
27 | {
28 | return 'php/json-serializable';
29 | }
30 |
31 | public function getNote(): string
32 | {
33 | return <<<'NOTE'
34 | Serialize object graphs using the native JsonSerializable interface
35 | NOTE;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/Bench/SerializardClosureBenchmark.php:
--------------------------------------------------------------------------------
1 |
20 | */
21 | class SerializardClosureBenchmark extends AbstractBench
22 | {
23 | /**
24 | * @var Serializard
25 | */
26 | private $serializer;
27 |
28 | public function initSerializer(): void
29 | {
30 | $formats = new FormatContainer();
31 | $formats->add('json', new JsonFormat());
32 |
33 | $normalizers = new FallbackNormalizerContainer();
34 | $normalizers->add(Forum::class, function (Forum $forum) {
35 | return [
36 | 'id' => $forum->getId(),
37 | 'name' => $forum->getName(),
38 | 'threads' => $forum->getThreads(),
39 | 'category' => $forum->getCategory(),
40 | 'createdAt' => $forum->getCreatedAt(),
41 | 'updatedAt' => $forum->getUpdatedAt(),
42 | ];
43 | });
44 | $normalizers->add(Thread::class, function (Thread $thread) {
45 | return [
46 | 'id' => $thread->getId(),
47 | 'popularity' => $thread->getPopularity(),
48 | 'title' => $thread->getTitle(),
49 | 'comments' => $thread->getComments(),
50 | 'description' => $thread->getDescription(),
51 | 'createdAt' => $thread->getCreatedAt(),
52 | 'updatedAt' => $thread->getUpdatedAt(),
53 | ];
54 | });
55 | $normalizers->add(Comment::class, function (Comment $comment) {
56 | return [
57 | 'id' => $comment->getId(),
58 | 'content' => $comment->getContent(),
59 | 'author' => $comment->getAuthor(),
60 | 'createdAt' => $comment->getCreatedAt(),
61 | 'updatedAt' => $comment->getUpdatedAt(),
62 | ];
63 | });
64 | $normalizers->add(\DateTimeImmutable::class, function (\DateTimeImmutable $dt) {
65 | return $dt->format(\DATE_ATOM);
66 | });
67 | $normalizers->add(Category::class, function (Category $category) {
68 | return [
69 | 'id' => $category->getId(),
70 | 'parent' => $category->getParent(),
71 | 'children' => $category->getChildren(),
72 | 'createdAt' => $category->getCreatedAt(),
73 | 'updatedAt' => $category->getUpdatedAt(),
74 | ];
75 | });
76 |
77 | $hydrators = new FallbackHydratorContainer();
78 |
79 | $this->serializer = new Serializard($formats, $normalizers, $hydrators);
80 | }
81 |
82 | public function serialize(Forum $data): void
83 | {
84 | $this->serializer->serialize($data, 'json');
85 | }
86 |
87 | public function getPackageName(): string
88 | {
89 | return 'thunderer/serializard';
90 | }
91 |
92 | public function getNote(): string
93 | {
94 | return <<<'NOTE'
95 | Serialize object graphs using closures as custom normalizers
96 | NOTE;
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/src/Bench/SerializardReflectionBenchmark.php:
--------------------------------------------------------------------------------
1 |
21 | */
22 | class SerializardReflectionBenchmark extends AbstractBench
23 | {
24 | /**
25 | * @var Serializard
26 | */
27 | private $serializer;
28 |
29 | public function initSerializer(): void
30 | {
31 | $formats = new FormatContainer();
32 | $formats->add('json', new JsonFormat());
33 |
34 | $normalizers = new FallbackNormalizerContainer();
35 | $normalizers->add(Forum::class, new ReflectionNormalizer());
36 | $normalizers->add(Thread::class, new ReflectionNormalizer());
37 | $normalizers->add(Comment::class, new ReflectionNormalizer());
38 | $normalizers->add(Category::class, new ReflectionNormalizer());
39 | $normalizers->add(\DateTimeImmutable::class, function (\DateTimeImmutable $dt) {
40 | return $dt->format(\DATE_ATOM);
41 | });
42 |
43 | $hydrators = new FallbackHydratorContainer();
44 |
45 | $this->serializer = new Serializard($formats, $normalizers, $hydrators);
46 | }
47 |
48 | public function serialize(Forum $data): void
49 | {
50 | $this->serializer->serialize($data, 'json');
51 | }
52 |
53 | public function getPackageName(): string
54 | {
55 | return 'thunderer/serializard';
56 | }
57 |
58 | public function getNote(): string
59 | {
60 | return <<<'NOTE'
61 | Serialize object graphs extracting its value through property reflection
62 | NOTE;
63 | }
64 | }
65 |
--------------------------------------------------------------------------------
/src/Bench/SymfonyGetSetNormalizerBenchmark.php:
--------------------------------------------------------------------------------
1 |
21 | */
22 | class SymfonyGetSetNormalizerBenchmark extends AbstractBench
23 | {
24 | /**
25 | * @var Serializer
26 | */
27 | private $serializer;
28 |
29 | public function initSerializer(): void
30 | {
31 | $classMetadataFactory = new CacheClassMetadataFactory(
32 | new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader())),
33 | new ApcuAdapter('SymfonyMetadata')
34 | );
35 |
36 | $this->serializer = new Serializer(
37 | [new DateTimeNormalizer(), new GetSetMethodNormalizer($classMetadataFactory)],
38 | [new JsonEncoder()]
39 | );
40 | }
41 |
42 | public function serialize(Forum $data): void
43 | {
44 | $this->serializer->serialize($data, 'json');
45 | }
46 |
47 | public function getPackageName(): string
48 | {
49 | return 'symfony/serializer';
50 | }
51 |
52 | public function getNote(): string
53 | {
54 | return <<<'NOTE'
55 | Serialize object graphs extracting the property values through its getter method
56 | NOTE;
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/src/Bench/SymfonyObjectNormalizerBenchmark.php:
--------------------------------------------------------------------------------
1 |
22 | */
23 | class SymfonyObjectNormalizerBenchmark extends AbstractBench
24 | {
25 | /**
26 | * @var Serializer
27 | */
28 | private $serializer;
29 |
30 | public function initSerializer(): void
31 | {
32 | $classMetadataFactory = new CacheClassMetadataFactory(
33 | new ClassMetadataFactory(new AnnotationLoader(new AnnotationReader())),
34 | new ApcuAdapter('SymfonyMetadata')
35 | );
36 |
37 | $propertyAccessor = PropertyAccess::createPropertyAccessorBuilder()
38 | ->setCacheItemPool(new ApcuAdapter('SymfonyPropertyAccessor'))
39 | ->getPropertyAccessor();
40 |
41 | $this->serializer = new Serializer(
42 | [new DateTimeNormalizer(), new ObjectNormalizer($classMetadataFactory, null, $propertyAccessor)],
43 | [new JsonEncoder()]
44 | );
45 | }
46 |
47 | public function serialize(Forum $data): void
48 | {
49 | $this->serializer->serialize($data, 'json');
50 | }
51 |
52 | public function getPackageName(): string
53 | {
54 | return 'symfony/serializer';
55 | }
56 |
57 | public function getNote(): string
58 | {
59 | return <<<'NOTE'
60 | Serialize object graphs using Symfony Property Access component
61 | NOTE;
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/Bench/TSantosBenchmark.php:
--------------------------------------------------------------------------------
1 |
19 | */
20 | class TSantosBenchmark extends AbstractBench
21 | {
22 | /**
23 | * @var \TSantos\Serializer\Serializer
24 | */
25 | private $serializer;
26 |
27 | public function initSerializer(): void
28 | {
29 | if (!file_exists($cache = __DIR__. '/../../cache/hydrators')) {
30 | mkdir($cache);
31 | }
32 |
33 | $this->serializer = (new SerializerBuilder())
34 | ->setMetadataDriver(new AnnotationDriver(new AnnotationReader(), new ApcuCache(), false))
35 | ->setHydratorDir($cache)
36 | ->setMetadataCache(new PsrCacheAdapter('TSantosMetadata', new ApcuAdapter()))
37 | ->enableBuiltInNormalizers()
38 | ->setDebug(false)
39 | ->build();
40 | }
41 |
42 | public function serialize(Forum $data): void
43 | {
44 | $this->serializer->serialize($data);
45 | }
46 |
47 | public function getPackageName(): string
48 | {
49 | return 'tsantos/serializer';
50 | }
51 |
52 | public function getNote(): string
53 | {
54 | return <<<'NOTE'
55 | Serializes an object graphs using generated data extractor for each class
56 | NOTE;
57 |
58 | }
59 |
60 |
61 | }
62 |
--------------------------------------------------------------------------------
/src/BenchExtension.php:
--------------------------------------------------------------------------------
1 |
11 | */
12 | class BenchExtension implements ExtensionInterface
13 | {
14 | public function load(Container $container)
15 | {
16 | $container->register('ivory_benchmark.bench_finder', function (Container $container) {
17 | return new BenchFinder(
18 | $container->get('benchmark.benchmark_finder'),
19 | $container->getParameter('path')
20 | );
21 | });
22 |
23 | $container->register('ivory_benchmark.info_command', function (Container $container) {
24 | return new InfoCommand($container->get('ivory_benchmark.bench_finder'));
25 | }, ['console.command' => []]);
26 | }
27 |
28 | public function getDefaultConfig()
29 | {
30 | return [];
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/src/BenchFinder.php:
--------------------------------------------------------------------------------
1 |
12 | */
13 | class BenchFinder
14 | {
15 | const DEFAULT_VERSION = 'N/A';
16 |
17 | /**
18 | * @var \PhpBench\Benchmark\BenchmarkFinder
19 | */
20 | private $internalFinder;
21 |
22 | /**
23 | * @var string
24 | */
25 | private $path;
26 |
27 | /**
28 | * BenchmarkFinder constructor.
29 | * @param \PhpBench\Benchmark\BenchmarkFinder $internalFinder
30 | * @param string $path
31 | */
32 | public function __construct(\PhpBench\Benchmark\BenchmarkFinder $internalFinder, string $path)
33 | {
34 | $this->internalFinder = $internalFinder;
35 | $this->path = $path;
36 | }
37 |
38 | public function findAll(): array
39 | {
40 | $benchmarks = [];
41 |
42 | /** @var BenchmarkMetadata $metadata */
43 | foreach ($this->internalFinder->findBenchmarks($this->path) as $metadata) {
44 | $data = $this->createBenchData($metadata);
45 | $benchmarks[$data['package']][] = $this->createBenchData($metadata);
46 | }
47 |
48 | return $benchmarks;
49 | }
50 |
51 | public function findOne(string $name): array
52 | {
53 | $benchmarksFound = $this->internalFinder->findBenchmarks($this->path, [$name]);
54 |
55 | if (empty($benchmarksFound)) {
56 | throw new \InvalidArgumentException('There is no benchmark with name "' . $name . '"');
57 | }
58 |
59 | $bench = current($benchmarksFound);
60 |
61 | return $this->createBenchData($bench);
62 | }
63 |
64 | private function createBenchData(BenchmarkMetadata $metadata): array
65 | {
66 | $ref = new \ReflectionClass($metadata->getClass());
67 |
68 | $bench = $ref->newInstance();
69 |
70 | try {
71 | $versionParts = explode('@', Versions::getVersion($bench->getPackageName()));
72 | $version = $versionParts[0];
73 | } catch (\OutOfBoundsException $boundsException) {
74 | $version = self::DEFAULT_VERSION;
75 | }
76 |
77 | return [
78 | 'bench' => $bench,
79 | 'name' => $ref->getShortName(),
80 | 'package' => $bench->getPackageName(),
81 | 'version' => $version,
82 | 'note' => $bench->getNote()
83 | ];
84 | }
85 | }
86 |
--------------------------------------------------------------------------------
/src/Command/InfoCommand.php:
--------------------------------------------------------------------------------
1 |
16 | */
17 | class InfoCommand extends Command
18 | {
19 | /**
20 | * @var BenchFinder
21 | */
22 | private $finder;
23 |
24 | /**
25 | * InfoCommand constructor.
26 | * @param BenchFinder $finder
27 | */
28 | public function __construct(BenchFinder $finder)
29 | {
30 | parent::__construct();
31 | $this->finder = $finder;
32 | }
33 |
34 | protected function configure()
35 | {
36 | $this
37 | ->setName('info')
38 | ->addArgument('serializer', InputArgument::OPTIONAL, 'Serializer name to inspect')
39 | ->setDescription('Show information about available serializers.')
40 | ->setHelp(
41 | 'The %command.name% displays detailed information about a serializer (e.g. version, capabilities and notes),
42 | or lists all serialized available'
43 | );
44 | }
45 |
46 | protected function execute(InputInterface $input, OutputInterface $output)
47 | {
48 | if (null === $benchmark = $input->getArgument('serializer')) {
49 | $this->displayAll($output);
50 | return;
51 | }
52 |
53 | $this->displayOne($output, $benchmark);
54 | }
55 |
56 | private function displayAll(OutputInterface $output): void
57 | {
58 | $rows = [];
59 |
60 | foreach ($this->finder->findAll() as $benchmarks) {
61 | foreach ($benchmarks as $i => $benchmark) {
62 | $row = [
63 | $benchmark['name'],
64 | ];
65 |
66 | if ($i === 0) {
67 | $row[] = new TableCell($benchmark['version'], ['rowspan' => count($benchmarks)]);
68 | }
69 |
70 | $row[] = $benchmark['note'];
71 | $rows[] = $row;
72 | }
73 |
74 | $rows[] = new TableSeparator();
75 | }
76 |
77 | array_pop($rows);
78 |
79 | $table= new Table($output);
80 | $table->setHeaders(['Benchmark', 'Version', 'Note']);
81 | $table->setRows($rows);
82 | $table->render();
83 | }
84 |
85 | private function displayOne(OutputInterface $output, string $benchmark): void
86 | {
87 | $foundBenchmark = $this->finder->findOne($benchmark);
88 | $output->writeln(sprintf('name : %s', $foundBenchmark['name']));
89 | $output->writeln(sprintf('package : %s', $foundBenchmark['package']));
90 | $output->writeln(sprintf('version : %s', $foundBenchmark['version']));
91 | $output->writeln(sprintf('note : %s', $foundBenchmark['note']));
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/src/DataProvider.php:
--------------------------------------------------------------------------------
1 | setCategory($this->createCategory($verticalComplexity));
19 |
20 | for ($i = 0; $i < $horizontalComplexity * 2; ++$i) {
21 | $forum->addThread($this->createThread($i, $horizontalComplexity));
22 | }
23 |
24 | return $forum;
25 | }
26 |
27 | private function createCategory(int $verticalComplexity = 1): Category
28 | {
29 | $original = $category = new Category(1);
30 |
31 | for ($i = 0; $i < $verticalComplexity * 2; ++$i) {
32 | $category->setParent($parent = new Category($i + 1));
33 | $category = $parent;
34 | }
35 |
36 | return $original;
37 | }
38 |
39 | private function createThread(int $index, int $horizontalComplexity = 1): Thread
40 | {
41 | $thread = new Thread($index, 'Great thread ' . $index . '!', 'Great description ' . $index, $index / 100);
42 |
43 | for ($i = 0; $i < $horizontalComplexity * 5; ++$i) {
44 | $thread->addComment($this->createComment($index * $i + $i));
45 | }
46 |
47 | return $thread;
48 | }
49 |
50 | private function createComment(int $index): Comment
51 | {
52 | return new Comment($index, 'Great comment ' . $index . '!');
53 | }
54 | }
55 |
--------------------------------------------------------------------------------
/src/Model/Category.php:
--------------------------------------------------------------------------------
1 |
13 | */
14 | class Category implements \JsonSerializable
15 | {
16 | use TimestampableTrait;
17 |
18 | /**
19 | * @Ivory\Type("int")
20 | * @Jms\Type("integer")
21 | * @TSantos\Type("integer")
22 | *
23 | * @var int
24 | */
25 | private $id;
26 |
27 | /**
28 | * @Ivory\Type("PhpSerializers\Benchmarks\Model\Category")
29 | * @Jms\Type("PhpSerializers\Benchmarks\Model\Category")
30 | * @TSantos\Type("PhpSerializers\Benchmarks\Model\Category")
31 | *
32 | * @var Category|null
33 | */
34 | private $parent;
35 |
36 | /**
37 | * @Ivory\Type("array")
38 | * @Jms\Type("array")
39 | * @TSantos\Type("PhpSerializers\Benchmarks\Model\Category[]")
40 | *
41 | * @var Category[]
42 | */
43 | private $children = [];
44 |
45 | /**
46 | * @param int $id
47 | * @param Category|null $parent
48 | * @param Category[] $children
49 | */
50 | public function __construct(int $id, Category $parent = null, array $children = [])
51 | {
52 | $this->setId($id);
53 | $this->setParent($parent);
54 | $this->setChildren($children);
55 | $this->initializeTimestampable();
56 | }
57 |
58 | /**
59 | * @return int
60 | */
61 | public function getId(): int
62 | {
63 | return $this->id;
64 | }
65 |
66 | /**
67 | * @param int $id
68 | */
69 | public function setId(int $id)
70 | {
71 | $this->id = $id;
72 | }
73 |
74 | /**
75 | * @return Category|null
76 | */
77 | public function getParent(): ?Category
78 | {
79 | return $this->parent;
80 | }
81 |
82 | /**
83 | * @param Category|null $parent
84 | */
85 | public function setParent(Category $parent = null)
86 | {
87 | $this->parent = $parent;
88 | }
89 |
90 | /**
91 | * @return Category[]
92 | */
93 | public function getChildren(): array
94 | {
95 | return $this->children;
96 | }
97 |
98 | /**
99 | * @param Category[] $children
100 | */
101 | public function setChildren(array $children)
102 | {
103 | $this->children = $children;
104 | }
105 |
106 | /**
107 | * @param Category $child
108 | */
109 | public function addChild(Category $child)
110 | {
111 | $this->children[] = $child;
112 | }
113 |
114 | /**
115 | * {@inheritdoc}
116 | */
117 | public function jsonSerialize()
118 | {
119 | return [
120 | 'id' => $this->id,
121 | 'parent' => $this->parent,
122 | 'children' => $this->children,
123 | 'createdAt' => $this->createdAt instanceof \DateTimeInterface ? $this->createdAt->format(\DateTime::ATOM) : null,
124 | 'updatedAt' => $this->updatedAt instanceof \DateTimeInterface ? $this->updatedAt->format(\DateTime::ATOM) : null,
125 | ];
126 | }
127 | }
128 |
--------------------------------------------------------------------------------
/src/Model/Comment.php:
--------------------------------------------------------------------------------
1 |
13 | */
14 | class Comment implements \JsonSerializable
15 | {
16 | use TimestampableTrait;
17 |
18 | /**
19 | * @Ivory\Type("int")
20 | * @Jms\Type("integer")
21 | * @TSantos\Type("integer")
22 | *
23 | * @var int
24 | */
25 | private $id;
26 |
27 | /**
28 | * @Ivory\Type("string")
29 | * @Jms\Type("string")
30 | * @TSantos\Type("string")
31 | *
32 | * @var string
33 | */
34 | private $content;
35 |
36 | /**
37 | * @Ivory\Type("PhpSerializers\Benchmarks\Model\User")
38 | * @Jms\Type("PhpSerializers\Benchmarks\Model\User")
39 | * @TSantos\Type("PhpSerializers\Benchmarks\Model\User")
40 | *
41 | * @var User
42 | */
43 | private $author;
44 |
45 | /**
46 | * @param int $id
47 | * @param string $content
48 | * @param User|null $author
49 | */
50 | public function __construct(int $id, string $content, User $author = null)
51 | {
52 | $this->setId($id);
53 | $this->setContent($content);
54 | $this->setAuthor($author);
55 | $this->initializeTimestampable();
56 | }
57 |
58 | /**
59 | * @return int
60 | */
61 | public function getId(): int
62 | {
63 | return $this->id;
64 | }
65 |
66 | /**
67 | * @param int $id
68 | */
69 | public function setId(int $id)
70 | {
71 | $this->id = $id;
72 | }
73 |
74 | /**
75 | * @return string
76 | */
77 | public function getContent(): string
78 | {
79 | return $this->content;
80 | }
81 |
82 | /**
83 | * @param string $content
84 | */
85 | public function setContent(string $content)
86 | {
87 | $this->content = $content;
88 | }
89 |
90 | /**
91 | * @return User|null
92 | */
93 | public function getAuthor(): ?User
94 | {
95 | return $this->author;
96 | }
97 |
98 | /**
99 | * @param User|null $author
100 | */
101 | public function setAuthor(User $author = null)
102 | {
103 | $this->author = $author;
104 | }
105 |
106 | /**
107 | * {@inheritdoc}
108 | */
109 | public function jsonSerialize()
110 | {
111 | return [
112 | 'id' => $this->id,
113 | 'content' => $this->content,
114 | 'author' => $this->author,
115 | 'createdAt' => $this->createdAt instanceof \DateTimeInterface ? $this->createdAt->format(\DateTime::ATOM) : null,
116 | 'updatedAt' => $this->updatedAt instanceof \DateTimeInterface ? $this->updatedAt->format(\DateTime::ATOM) : null,
117 | ];
118 | }
119 | }
120 |
--------------------------------------------------------------------------------
/src/Model/Forum.php:
--------------------------------------------------------------------------------
1 |
13 | */
14 | class Forum implements \JsonSerializable
15 | {
16 | use TimestampableTrait;
17 |
18 | /**
19 | * @Ivory\Type("int")
20 | * @Jms\Type("integer")
21 | * @TSantos\Type("integer")
22 | *
23 | * @var int
24 | */
25 | private $id;
26 |
27 | /**
28 | * @Ivory\Type("string")
29 | * @Jms\Type("string")
30 | * @TSantos\Type("string")
31 | *
32 | * @var string
33 | */
34 | private $name;
35 |
36 | /**
37 | * @Ivory\Type("PhpSerializers\Benchmarks\Model\Category")
38 | * @Jms\Type("PhpSerializers\Benchmarks\Model\Category")
39 | * @TSantos\Type("PhpSerializers\Benchmarks\Model\Category")
40 | *
41 | * @var Category
42 | */
43 | private $category;
44 |
45 | /**
46 | * @Ivory\Type("array")
47 | * @Jms\Type("array")
48 | * @TSantos\Type("PhpSerializers\Benchmarks\Model\Thread[]")
49 | *
50 | * @var Thread[]
51 | */
52 | private $threads;
53 |
54 | /**
55 | * @param int $id
56 | * @param string $name
57 | * @param Category|null $category
58 | * @param Thread[] $threads
59 | */
60 | public function __construct(int $id, string $name, Category $category = null, array $threads = [])
61 | {
62 | $this->setId($id);
63 | $this->setName($name);
64 | $this->setThreads($threads);
65 | $this->initializeTimestampable();
66 | }
67 |
68 | /**
69 | * @return int
70 | */
71 | public function getId(): int
72 | {
73 | return $this->id;
74 | }
75 |
76 | /**
77 | * @param int $id
78 | */
79 | public function setId(int $id)
80 | {
81 | $this->id = $id;
82 | }
83 |
84 | /**
85 | * @return string
86 | */
87 | public function getName(): string
88 | {
89 | return $this->name;
90 | }
91 |
92 | /**
93 | * @param string $name
94 | */
95 | public function setName(string $name)
96 | {
97 | $this->name = $name;
98 | }
99 |
100 | /**
101 | * @return Category
102 | */
103 | public function getCategory(): Category
104 | {
105 | return $this->category;
106 | }
107 |
108 | /**
109 | * @param Category|null $category
110 | */
111 | public function setCategory(Category $category = null)
112 | {
113 | $this->category = $category;
114 | }
115 |
116 | /**
117 | * @return Thread[]
118 | */
119 | public function getThreads(): array
120 | {
121 | return $this->threads;
122 | }
123 |
124 | /**
125 | * @param Thread[] $threads
126 | */
127 | public function setThreads(array $threads)
128 | {
129 | $this->threads = $threads;
130 | }
131 |
132 | /**
133 | * @param Thread $thread
134 | */
135 | public function addThread(Thread $thread)
136 | {
137 | $this->threads[] = $thread;
138 | }
139 |
140 | /**
141 | * {@inheritdoc}
142 | */
143 | public function jsonSerialize()
144 | {
145 | return [
146 | 'id' => $this->id,
147 | 'name' => $this->name,
148 | 'category' => $this->category,
149 | 'threads' => $this->threads,
150 | 'createdAt' => $this->createdAt instanceof \DateTimeInterface ? $this->createdAt->format(\DateTime::ATOM) : null,
151 | 'updatedAt' => $this->updatedAt instanceof \DateTimeInterface ? $this->updatedAt->format(\DateTime::ATOM) : null,
152 | ];
153 | }
154 | }
155 |
--------------------------------------------------------------------------------
/src/Model/Thread.php:
--------------------------------------------------------------------------------
1 |
13 | */
14 | class Thread implements \JsonSerializable
15 | {
16 | use TimestampableTrait;
17 |
18 | /**
19 | * @Ivory\Type("int")
20 | * @Jms\Type("integer")
21 | * @TSantos\Type("integer")
22 | *
23 | * @var int
24 | */
25 | private $id;
26 |
27 | /**
28 | * @Ivory\Type("string")
29 | * @Jms\Type("string")
30 | * @TSantos\Type("string")
31 | *
32 | * @var string
33 | */
34 | private $title;
35 |
36 | /**
37 | * @Ivory\Type("string")
38 | * @Jms\Type("string")
39 | * @TSantos\Type("string")
40 | *
41 | * @var string
42 | */
43 | private $description;
44 |
45 | /**
46 | * @Ivory\Type("float")
47 | * @Jms\Type("float")
48 | * @TSantos\Type("float")
49 | *
50 | * @var float
51 | */
52 | private $popularity;
53 |
54 | /**
55 | * @Ivory\Type("array")
56 | * @Jms\Type("array")
57 | * @TSantos\Type("PhpSerializers\Benchmarks\Model\Comment[]")
58 | *
59 | * @var Comment[]
60 | */
61 | private $comments;
62 |
63 | /**
64 | * @param int $id
65 | * @param string $title
66 | * @param string $description
67 | * @param float $popularity
68 | * @param Comment[] $comments
69 | */
70 | public function __construct(int $id, string $title, string $description, float $popularity, array $comments = [])
71 | {
72 | $this->setId($id);
73 | $this->setTitle($title);
74 | $this->setDescription($description);
75 | $this->setPopularity($popularity);
76 | $this->setComments($comments);
77 | $this->initializeTimestampable();
78 | }
79 |
80 | /**
81 | * @return int
82 | */
83 | public function getId(): int
84 | {
85 | return $this->id;
86 | }
87 |
88 | /**
89 | * @param int $id
90 | */
91 | public function setId(int $id)
92 | {
93 | $this->id = $id;
94 | }
95 |
96 | /**
97 | * @return string
98 | */
99 | public function getTitle(): string
100 | {
101 | return $this->title;
102 | }
103 |
104 | /**
105 | * @param string $title
106 | */
107 | public function setTitle(string $title)
108 | {
109 | $this->title = $title;
110 | }
111 |
112 | /**
113 | * @return string
114 | */
115 | public function getDescription(): string
116 | {
117 | return $this->description;
118 | }
119 |
120 | /**
121 | * @param string $description
122 | */
123 | public function setDescription(string $description)
124 | {
125 | $this->description = $description;
126 | }
127 |
128 | /**
129 | * @return float
130 | */
131 | public function getPopularity(): float
132 | {
133 | return $this->popularity;
134 | }
135 |
136 | /**
137 | * @param float $popularity
138 | */
139 | public function setPopularity(float $popularity)
140 | {
141 | $this->popularity = $popularity;
142 | }
143 |
144 | /**
145 | * @return Comment[]
146 | */
147 | public function getComments(): array
148 | {
149 | return $this->comments;
150 | }
151 |
152 | /**
153 | * @param Comment[] $comments
154 | */
155 | public function setComments(array $comments)
156 | {
157 | $this->comments = $comments;
158 | }
159 |
160 | /**
161 | * @param Comment $comment
162 | */
163 | public function addComment(Comment $comment)
164 | {
165 | $this->comments[] = $comment;
166 | }
167 |
168 | /**
169 | * {@inheritdoc}
170 | */
171 | public function jsonSerialize()
172 | {
173 | return [
174 | 'id' => $this->id,
175 | 'title' => $this->title,
176 | 'description' => $this->description,
177 | 'popularity' => $this->popularity,
178 | 'comments' => $this->comments,
179 | 'createdAt' => $this->createdAt instanceof \DateTimeInterface ? $this->createdAt->format(\DateTime::ATOM) : null,
180 | 'updatedAt' => $this->updatedAt instanceof \DateTimeInterface ? $this->updatedAt->format(\DateTime::ATOM) : null,
181 | ];
182 | }
183 | }
184 |
--------------------------------------------------------------------------------
/src/Model/TimestampableTrait.php:
--------------------------------------------------------------------------------
1 |
9 | */
10 | trait TimestampableTrait
11 | {
12 | /**
13 | * @Ivory\Type("DateTimeImmutable")
14 | *
15 | * @var \DateTimeImmutable
16 | */
17 | private $createdAt;
18 |
19 | /**
20 | * @Ivory\Type("DateTime")
21 | *
22 | * @var \DateTime|null
23 | */
24 | private $updatedAt;
25 |
26 | /**
27 | * @return \DateTimeImmutable
28 | */
29 | public function getCreatedAt(): \DateTimeImmutable
30 | {
31 | return $this->createdAt;
32 | }
33 |
34 | /**
35 | * @param \DateTimeImmutable $createdAt
36 | */
37 | public function setCreatedAt(\DateTimeImmutable $createdAt)
38 | {
39 | $this->createdAt = $createdAt;
40 | }
41 |
42 | /**
43 | * @return \DateTime|null
44 | */
45 | public function getUpdatedAt(): ?\DateTime
46 | {
47 | return $this->updatedAt;
48 | }
49 |
50 | /**
51 | * @param \DateTime $updatedAt
52 | */
53 | public function setUpdatedAt(\DateTime $updatedAt)
54 | {
55 | $this->updatedAt = $updatedAt;
56 | }
57 |
58 | private function initializeTimestampable()
59 | {
60 | $this->createdAt = new \DateTimeImmutable();
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/Model/User.php:
--------------------------------------------------------------------------------
1 |
13 | */
14 | class User implements \JsonSerializable
15 | {
16 | use TimestampableTrait;
17 |
18 | /**
19 | * @Ivory\Type("int")
20 | * @Jms\Type("integer")
21 | * @TSantos\Type("integer")
22 | *
23 | * @var int
24 | */
25 | private $id;
26 |
27 | /**
28 | * @Ivory\Type("string")
29 | * @Jms\Type("string")
30 | * @TSantos\Type("string")
31 | *
32 | * @var string
33 | */
34 | private $firstname;
35 |
36 | /**
37 | * @Ivory\Type("string")
38 | * @Jms\Type("string")
39 | * @TSantos\Type("string")
40 | *
41 | * @var string
42 | */
43 | private $lastname;
44 |
45 | /**
46 | * @Ivory\Type("bool")
47 | * @Jms\Type("boolean")
48 | * @TSantos\Type("boolean")
49 | *
50 | * @var bool
51 | */
52 | private $newsletter;
53 |
54 |
55 | /**
56 | * {@inheritdoc}
57 | */
58 | public function jsonSerialize()
59 | {
60 | return [
61 | 'id' => $this->id,
62 | 'firstname' => $this->firstname,
63 | 'lastname' => $this->lastname,
64 | 'newsletter' => $this->newsletter,
65 | 'createdAt' => $this->createdAt instanceof \DateTimeInterface ? $this->createdAt->format(\DateTime::ATOM) : null,
66 | 'updatedAt' => $this->updatedAt instanceof \DateTimeInterface ? $this->updatedAt->format(\DateTime::ATOM) : null,
67 | ];
68 | }
69 | }
70 |
--------------------------------------------------------------------------------