nilportugues / sql-repository

[PHP 7] SQL Repository implementation
http://nilportugues.com
MIT License
36 stars 3 forks source link

Nullable objects #24

Open flavioheleno opened 7 years ago

flavioheleno commented 7 years ago

Is there a way to have nullable objects on the mapping?

For example an entity that has a "update_at" field that is only set once the entity is updated but not when it is created.

If it is not currently possible, what would be the recommended way for implementing it? (I'm happy to implement it)


Entity.php

<?php

namespace NilPortugues\Tests\Foundation;

use DateTime;
use NilPortugues\Foundation\Domain\Model\Repository\Contracts\Identity;

class Entity implements Identity {
    protected $id;
    protected $createdAt;
    protected $updatedAt;

    public function __construct(?int $id, DateTime $createdAt, ?DateTime $updatedAt) {
        $this->id        = $id;
        $this->createdAt = $createdAt;
        $this->updatedAt = $updatedAt;
    }

    public function id() : ?int {
        return $this->id;
    }

    public function createdAt() : DateTime {
        return $this->createdAt;
    }

    public function updatedAt() : ?DateTime {
        return $this->updatedAt;
    }

    public function __toString() {
        return (string) $this->id();
    }
}

EntityMapping.php

<?php

namespace NilPortugues\Tests\Foundation;

use DateTime;
use NilPortugues\Foundation\Domain\Model\Repository\Contracts\Mapping;

class EntityMapping implements Mapping {
    public function identity() : string {
        return 'id';
    }

    public function name() : string {
        return 'entities';
    }

    public function map() : array {
        return [
            'id'             => 'id',
            'createdAt.date' => 'created_at',
            'updatedAt.date' => 'updated_at'
        ];
    }

    public function fromArray(array $data) : Entity {
        return new Entity(
            $data['id'],
            new DateTime($data['created_at']),
            empty($data['updated_at']) ? null : new DateTime($data['updated_at'])
        );
    }

    public function autoGenerateId() : bool {
        return true;
    }
}

EntityRepository.php

<?php

namespace NilPortugues\Tests\Foundation;

use NilPortugues\Foundation\Infrastructure\Model\Repository\Sql\SqlRepository;
use NilPortugues\Foundation\Infrastructure\Model\Repository\Sql\SqlRepositoryHydrator;

class EntityRepository extends SqlRepository {
    use SqlRepositoryHydrator;
}

EntityTest.php

<?php

namespace NilPortugues\Tests\Foundation;

use DateTime;
use PDO;
use PHPUnit_Framework_TestCase;

class EntityTest extends PHPUnit_Framework_TestCase {
    private $pdo;
    private $repository;

    public function setUp() {
        $this->pdo = new PDO('pgsql:host=localhost;port=5432;dbname=testdb', 'test', 'test');
        $this->pdo->exec('
            CREATE TABLE IF NOT EXISTS entities (
                id SERIAL PRIMARY KEY,
                created_at TIMESTAMP NOT NULL,
                updated_at TIMESTAMP
            )
        ');
        unset($this->pdo);
        $this->pdo = new PDO('pgsql:host=localhost;port=5432;dbname=testdb', 'test', 'test');
        $this->repository = new EntityRepository($this->pdo, new EntityMapping());
    }

    public function testNullable() {
        $entity = new Entity(
            null,
            new DateTime(),
            null
        );
        $newEntity = $this->repository->add($entity);

        $this->assertNotNull($newEntity);
        $this->assertEquals(1, $newEntity->id());
        $this->assertNotNull($newEntity->createdAt());
        $this->assertNull($newEntity->updatedAt());
    }

    public function tearDown() {
        $this->pdo->exec('DROP TABLE entities');
    }
}

Output

PHPUnit 4.8.35 by Sebastian Bergmann and contributors.

Runtime:    PHP 7.1.2
Configuration:  /Users/flavio/php/sql-repository/phpunit.xml.dist
Warning:    The Xdebug extension is not loaded
        No code coverage will be generated.

E

Time: 165 ms, Memory: 4.00MB

There was 1 error:

1) NilPortugues\Tests\Foundation\EntityTest::testNullable
RuntimeException: Column updatedAt.date not mapped for class NilPortugues\Tests\Foundation\Entity.
flavioheleno commented 5 years ago

@nilportugues any hint on this old issue? I just ran into it again today.. :-)