1
resposta

Erro ao criar turma

Quando executo meu arquivo "criar-turma.php", o erro abaixo ocorre:

PHP Fatal error:  Uncaught DomainException: ID é null in /home/alanfs/Documentos/projetos-dev/php-pdo/src/Domain/Model/Student.php:29
Stack trace:
#0 /home/alanfs/Documentos/projetos-dev/php-pdo/src/Infraestructure/Repository/PdoStudentRepository.php(56): Alura\Pdo\Domain\Model\Student->id()
#1 /home/alanfs/Documentos/projetos-dev/php-pdo/criar-turma.php(19): Alura\Pdo\Infraestructure\Repository\PdoStudentRepository->save()
#2 {main}
  thrown in /home/alanfs/Documentos/projetos-dev/php-pdo/src/Domain/Model/Student.php on line 29

Percebi que o problema é devido ao ID ser "null" quando tenta inserir pela exception que coloquei no código, mas não sei como resolver. Meus arquivos:

Student.php

<?php

namespace Alura\Pdo\Domain\Model;

class Student
{
    private ?int $id;
    private string $name;
    private \DateTimeInterface $birthDate;

    public function __construct(?int $id, string $name, \DateTimeInterface $birthDate)
    {
        $this->id = $id;
        $this->name = $name;
        $this->birthDate = $birthDate;
    }

    public function defineId(int $id): void
    {
        if (!is_null($this->id)) {
            throw new \DomainException('Você só pode definir o ID uma vez');
        }
        $this->id = $id;
    }

    public function id(): int
    {
        if (is_null($this->id)) {
            throw new \DomainException('ID é null');
        }
        return $this->id;
    }

    public function name(): string
    {
        return $this->name;
    }

  // Outros métodos
}

PdoStudentRepository.php

<?php

namespace Alura\Pdo\Infraestructure\Repository;

use PDO;
use Alura\Pdo\Domain\Model\Student;
use Alura\Pdo\Domain\Repository\StudentRepository;


class PdoStudentRepository implements StudentRepository
{
    private PDO $connection;
    public function __construct(PDO $connection)
    {
        $this->connection = $connection;
    }

    public function insert(Student $student): bool
    {
        var_dump($student);
        $insertQuery = 'INSERT INTO students (name, birth_date) VALUES (:name, :birth_date);';
        $stmt = $this->connection->prepare($insertQuery);

        $success = $stmt->execute([
            ':name' => $student->name(),
            ':birth_date' => $student->birthDate()->format('Y-m-d'),
        ]);

        if ($success) {
            $student->defineId($this->connection->lastInsertId());
        }

        return $success;
    }

    public function save(Student $student): bool
    {
        if ($student->id() === null) {
            return $this->insert($student);
        }
        return $this->update($student);
    }

    private function update(Student $student): bool
    {
        $updateQuery = 'UPDATE students SET name = :name, birth_date = :birth WHERE id = :id;';
        $stmt = $this->connection->prepare($updateQuery);
        $stmt->bindValue(':name', $student->name());
        $stmt->bindValue(':birth', $student->birthDate()->format('Y-m-d'));
        $stmt->bindValue(':id', $student->id());

        return $stmt->execute();
    }

// outras funções

    private function hydrateStudentList(\PDOStatement $stmt): array
    {
        $studentDataList = $stmt->fetchAll(PDO::FETCH_ASSOC);
        $studentList = [];

        foreach ($studentDataList as $studentData) {
            $studentList[] = new Student(
                $studentData['id'],
                $studentData['name'],
                new \DateTimeImmutable($studentData['birth_date'])
            );
        }

        return $studentList;
    }
}

criar-turma.php

<?php
use Alura\Pdo\Domain\Model\Student;
use Alura\Pdo\Infraestructure\Repository\PdoStudentRepository;
use Alura\Pdo\Infraestructure\Persistence\ConnectionCreator;

require_once 'vendor/autoload.php';

$connection = ConnectionCreator::createConnection();
$studentRepository = new PdoStudentRepository($connection);

// Inserir os alunos da turma
$connection->beginTransaction();

$studentA = new Student(
    null,
    'Nico Outback',
    new DateTimeImmutable('1987-07-07'),
);
$studentRepository->save($studentA);

$studentB = new Student(null, 'Alan Proist', new DateTimeImmutable('1985-05-31'));
$studentRepository->save($studentB);

$connection->commit();

Poderiam me ajudar a resolver?

1 resposta

Olá, Alan! Tudo bem?

O problema ocorre porque o método save da classe PdoStudentRepository está tentando acessar o ID do estudante antes de ele ser inserido no banco de dados. Quando o estudante é novo, o ID é null, e isso causa a exceção.

Para resolver isso, podemos ajustar o método save para verificar se o estudante já tem um ID antes de tentar acessar o método id(). Se o ID for null, ele deve chamar o método insert diretamente.

Vou sugerir algumas alterações no seu código:

PdoStudentRepository.php

Modifique o método save para não acessar o ID diretamente se ele for null:

public function save(Student $student): bool
{
    if (is_null($student->id())) {
        return $this->insert($student);
    }
    return $this->update($student);
}

Student.php

Certifique-se de que o método defineId esteja aceitando o ID como string, já que lastInsertId() retorna uma string:

public function defineId(string $id): void
{
    if (!is_null($this->id)) {
        throw new \DomainException('Você só pode definir o ID uma vez');
    }
    $this->id = (int) $id; // Converte para inteiro
}

criar-turma.php

Seu arquivo criar-turma.php parece estar correto, mas vamos garantir que a transação esteja sendo corretamente iniciada e finalizada:

<?php
use Alura\Pdo\Domain\Model\Student;
use Alura\Pdo\Infraestructure\Repository\PdoStudentRepository;
use Alura\Pdo\Infraestructure\Persistence\ConnectionCreator;

require_once 'vendor/autoload.php';

$connection = ConnectionCreator::createConnection();
$studentRepository = new PdoStudentRepository($connection);

$connection->beginTransaction();

try {
    $studentA = new Student(
        null,
        'Nico Outback',
        new DateTimeImmutable('1987-07-07')
    );
    $studentRepository->save($studentA);

    $studentB = new Student(null, 'Alan Proist', new DateTimeImmutable('1985-05-31'));
    $studentRepository->save($studentB);

    $connection->commit();
} catch (\Exception $e) {
    $connection->rollBack();
    echo "Falha ao criar a turma: " . $e->getMessage();
}

Com essas alterações, o método save deve funcionar corretamente, evitando a exceção quando o ID é null.

Espero ter ajudado e bons estudos!

Caso este post tenha lhe ajudado, por favor, marcar como solucionado ✓.