Solucionado (ver solução)
Solucionado
(ver solução)
8
respostas

erro ao tentar vincular um aluno ao curso

Quando tento vincular o aluno a um curso, recebo essa mensagem de erro, já tentei varias formas de resolver mas não consigo, alguem poderia me ajudar???

php commands/vincular-aluno-curso.php 1 1
PHP Fatal error:  Uncaught Error: Call to a member function contains() on null in /home/carlos/Área de Trabalho/doctrine/src/Entity/Aluno.php:80
Stack trace:
#0 /home/carlos/Área de Trabalho/doctrine/src/Entity/Curso.php(61): Alura\Doctrine\Entity\Aluno->addCurso(Object(Alura\Doctrine\Entity\Curso))
#1 /home/carlos/Área de Trabalho/doctrine/commands/vincular-aluno-curso.php(19): Alura\Doctrine\Entity\Curso->addAluno(Object(Alura\Doctrine\Entity\Aluno))
#2 {main}
  thrown in /home/carlos/Área de Trabalho/doctrine/src/Entity/Aluno.php on line 80

este é meu codigo de adicionar curso:

public function addCurso(Curso $curso): self
    {
        if($this->cursos->contains($curso)){
            return $this;
        }

        $this->cursos->add($curso);
        $curso->addAluno($this);

        return $this;
    }
8 respostas

Olá Carlos, já tentou dar um var_dump nos objetos recuperados do banco? Talvez eles estejam vindo com o valor nulo e caso seja esse o motivo não existe dados vinculados ao id que você está passando para o script.

Já verifiquei os objetos, todos estão preenchidos... Não consegui encontrar uma solução até agora.

Ponha todo seu código aqui para visualizarmos porque o problema não é na função de adicionar aluno, ela está correta.

esse é todo o meu codigo da entidade aluno:

<?php

namespace Alura\Doctrine\Entity;

use Alura\Doctrine\Entity\Curso;
use Alura\Doctrine\Entity\Telefone;
use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\ArrayCollection;

/**
 * @Entity
 */
class Aluno
{
    /**
     * @Id
     * @GeneratedValue
     * @Column(type="integer")
     */
    private $id;

    /**
     * @column(type="string")
     */
    private $nome;

    /**
     * @OneToMany(targetEntity="Telefone", mappedBy="aluno", cascade={"remove","persist"})
     */
    private $telefones;

    /**
     * ManyToMany(targetEntity="Curso", mappedBy="alunos")
     */
    private $cursos;

    public function __construct(){
        $this->telefones = new ArrayCollection();
        $this->cursos = new ArrayCollection();
    }

    public function toArray() : array
    {
        return[
            "id" -> $this->id,
            "nome" -> $this->nome
        ];
    }

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

    public function setNome(string $nome) : self
    {
        $this->nome = $nome;
        return $this;
    }

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

    public function addTelefone(Telefone $telefone): self
    {
        $this->telefones->add($telefone);
        $telefone->setAluno($this);
        return $this;
    }

    public function getTelefones(): Collection
    {
        return $this->telefones;
    }

    public function addCurso(Curso $curso): self
    {
        if($this->cursos->contains($curso)){
            return $this;
        }

        $this->cursos->add($curso);
        $curso->addAluno($this);

        return $this;
    }

    public function getCursos(): Collection
    {
        return $this->cursos;
    }

}

esse é todo meu codigo da entidade curso:

<?php

namespace Alura\Doctrine\Entity;

use Alura\Doctrine\Entity\Aluno;
use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\ArrayCollection;

/**
 * @Entity
 */
class Curso 
{
    /**
     * @Id
     * @GeneratedValue
     * @Column(type="integer")
     */
    private $id;

    /**
     * @Column(type="string")
     */
    private $nome;

    /**
     * @ManyToMany(targetEntity="Aluno", inversedBy="cursos")
     */
    private $alunos;

    public function __construct(){
        $this->alunos = new ArrayCollection();
    }

    /* --------------------------------------------------------- */

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

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

    public function setNome($nome): self
    {
        $this->nome = $nome;

        return $this;
    }

    public function addAluno(Aluno $aluno): self
    {
        if($this->alunos->contains($aluno)){
            return $this;
        }

        $this->alunos->add($aluno);
        $aluno->addCurso($this);

        return $this;
    }

    public function getAlunos(): Collection
    {
        return $this->alunos;
    }
}

e esse é o meu command de vincular aluno ao curso:

<?php

use Alura\Doctrine\Entity\Aluno;
use Alura\Doctrine\Entity\Curso;
use Alura\Doctrine\Helper\EntityManagerFactory;

require_once __DIR__ . '/../vendor/autoload.php';

$entityManagerFactory = new EntityManagerFactory();
$entityManager = $entityManagerFactory->getEntityManager();

$id_aluno = $argv[1];
$id_curso = $argv[2];

$aluno = $entityManager->find(Aluno::class, $id_aluno);
echo "aluno: " . $aluno->getNome();
echo "\n";
$curso = $entityManager->find(Curso::class, $id_curso);
echo "curso: " . $curso->getNome();
echo "\n";

$curso->addAluno($aluno);

$entityManager->flush();

solução!

Oi Carlos, acho que encontrei o seu erro: Em sua classe aluno a annotation @ManyToMany está faltando o simbolo de @. Ela está assim :

`/**

 * ManyToMany(targetEntity="Curso", mappedBy="alunos")
 */` 

Enquanto deveria estar dessa forma:

`/**

 * @ManyToMany(targetEntity="Curso", mappedBy="alunos")
 */`

Ajeite esse erro e realize todo processo novamente de criação da migration.

Muito obrigado meu mano, foi de grande ajuda s2

Valeu. Só uma dica rápida e um pouco boba até mas que pode deixar seu código um pouco mais limpo: classes que compartilham o mesmo namespace você não precisa usar o use para usa-lás.

Por exemplo, em sua classe Aluno você não precisa declarar "use Alura\Doctrine\Entity\Curso" por que Curso e Aluno já possuem o mesmo namespace declarado =)

nossa, não sabia dessa. muito obrigado mano, vou dar uma limpada no meu código!!

Quer mergulhar em tecnologia e aprendizagem?

Receba a newsletter que o nosso CEO escreve pessoalmente, com insights do mercado de trabalho, ciência e desenvolvimento de software