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

Como desabilitar botão caso usuário já tenha feito o cadastro ?

Meu problema é tratamento se o usuário tenha feito cadastro o botão deve ficar inativo e se o adm deletar o registro o botão volta ao normal, o jeito que eu fiz ele retornou esse erro.

Undefined column: 7 ERROR: column renovacao.matricula_id does not exist LINE 1: select * from "renovacao" where "renovacao"."matricula_id" =... ^ (SQL: select * from "renovacao" where "renovacao"."matricula_id" = 1 and "renovacao"."matricula_id" is not null limit 1)

-- Model Matricula

<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Matricula extends Model
{
    protected $table = 'matricula';
    protected $fillable = ['user_id','nomealuno','nomedopai'];
    public function user() {
        return $this->belongsTo('App\User');
    }    
    public function renovacao() {
        return $this->hasOne('App\Renovacao'); // Aqui tentei até colocar o hasMany só que o erro continuava
    } 
}

--Model Renovacao

<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Renovacao extends Model
{
    protected $table = 'renovacao';
    protected $fillable = ['nomerespo','nomealuno','status'];

  public function matricula() {
        return $this->belongsTo('App\Matricula');
    }
}

--Controller

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\User;
use App\Renovacao;
use App\Matricula;
use Illuminate\Support\Facades\Auth;
use App\Http\Requests\RenovacaoRequest;
class RenovacaoController extends Controller
{
//  Pega o user_id do usuário logado e joga no formulário os dados cadastrado 
    public function listardados(){
        $matricula = Matricula::where('user_id', Auth::id())->get();

        //dd($matricula);
        return view('dashboard.renovacao.teste', compact( 'matricula'));
    }

//Função que salva os dados do form na tabela renovação
    public function store(RenovacaoRequest $request){
     $user = Auth()->user();
    $dados = $request->get('rematricula');
    foreach ($dados as $key => $dado) {
        Renovacao::create($dado);
    }
        return view('dashboard.renovacao.confirmacao', compact ('renovacao'));
    }
}

--form

<form class="form-horizontal " id="regForm" action="{{route('renovacao.store')}}" method="POST">
            <div class="card-panel white">
                <h4 class="center">Solicitar Renovação</h4>
                <div class="row"></div>
                {{ csrf_field()}}

                <div class="row">
                    @if($matricula->count())
                        <right>
                            <a>**Dados Cadastrados**</a>
                        </right>
                        <div class="row"></div>
                        <div class="row"></div>
                        @foreach($matricula as $matric)

                            <div class="row">
                                <div class="col s6 m6">
                                <div class="input-field {{$errors->has('') ? 'has-error' : ''}} ">
                                    <label for="produto">Nome do Pai:</label>
                                    <input type="text" class="form-control" name="rematricula[{{ $loop->index}}][nomerespo]" value="{{ $matric->nomedopai }}">
                                </div>
                                </div>

                                <div class="col s6 m6">
                                <div class="input-field {{$errors->has('') ? 'has-error' : ''}} ">
                                    <label for="produto">Nome do Aluno(a):</label>
                                    <input type="text" class="form-control" name="rematricula[{{ $loop->index}}][nomealuno]" value="{{ $matric->nomealuno }}">
                                </div>
                                </div>
                            </div>
                        @endforeach
                        <div class = "row">
                            <div class="col s12">

                                <a title="Voltar Para Página Principal" class="btn orange darken-4 btn-info left " href="/admin">Voltar
                                    <i class="material-icons left">arrow_back_ios</i>
                                </a>
                                @if(empty($matric->renovacao()->first())) // O erro apareceu nessa linha
                                    <button type="submit" class="btn orange darken-4 btn-info right">Confirmar
                                        <i class="material-icons left">save</i>
                                    </button>
                                @else
                                    <button type="submit" disabled class="btn orange darken-4 btn-info right">Inscrito
                                            <i class="material-icons left">confirmation_number</i>
                                    </button>
                                @endif
                            </div>
                        </div>
                    @else
                        <div class="row"></div>
                        <div class="row"></div>
                        <p> Desculpe! Página Indisponivel, Você não tem cadastro nessa instituição, Procure a secretaria e faça sua Matrícula </p>
                        <div class="row"></div>
                        <a title="Voltar Para Página Principal" class="btn orange darken-4 btn-info left " href="/admin">Voltar
                                    <i class="material-icons left">arrow_back_ios</i>
                        </a>
                    @endif
                </div>
            </div>    
        </form>
23 respostas

Oi Elyton, tudo bom?

Perdão pela demora na resposta

O erro:

Undefined column: 7 ERROR: column renovacao.matricula_id does not exist 

Indica que a coluna matricula_id ainda não existe na tabela renovacao.

Você chegou a executar alguma migration/comando para atualizar a base de dados após criar o relacionamento entre a classe Renovacao e Matricula?

Parece que o relacionamento está ok mas a base ainda não está refletindo as classes, se não a coluna existiria.

Atualizando a base o erro deve deixar de acontecer =)

Sim, eu migrei as tabelas depois das alterações e não deu efeito nenhum, e deveria colocar alguma coisa na migration renovação? Eu usei esse comando: php artisan migrate:fresh para migrar as tabelas novamente

Oi Elyton, em relação as migrations automaticas acho que é isso mesmo. Parece que o mapeamento não cria as chaves primárias.

De qualquer forma, ORMs são feitos pra ajudar a gente mas parte do trabalho ainda temos que fazer.

No caso do eloquent acho que vale a pena criar esse campo matricula_id lá na propria tabela. Algo como:

ALTER TABLE renovacao ADD matricula_id INT DEFAULT NULL

ALTER TABLE renovacao ADD CONSTRAINT FK_136416C2BC21F742 FOREIGN KEY (matricula_id) REFERENCES matricula (id)

o primeiro comando adiciona a coluna o segundo cria uma chave estrangeira relacionando os dois. Acho que pro ORM só o primeiro já resolve mas é sempre bom garantir a segurança no banco também =)

Outro possível problema é que ao criar a renovação (que é o lado recessivo do relacionamento) não chamando explicitamente o associate. Algo como:

...
// aqui estamos dizendo explicitamente que a matricula está relacionada a renovacao
$matricula->renovacao()->associate($renovacao);

$matricula->save();
...

Essa abordagem está disponível na própria documentação do framework então eu seguiria nela antes de mexer na estrutura da tabela (além de fazer um backup dos dados caso sejam importantes) =)

Se você quiser, compartilha seu código aqui com a gente em um git. Assim eu consigo simular seu problema na minha máquina no mesmo cenário e te dizer o que está acontecendo exatamente

Abraço

Aqui está o código fonte, ver se vai funcionar no seu pc

https://github.com/ElytonSilva/SiteSigamRR

Oi Elyton, tudo bom?

Dei uma investigada aqui no seu projeto e parece que o problema era o relacionamento entre a classe Matricula e a classe Renovacao (que não existia).

Fiz o relacionamento entre Matricula e Renovacao, rodei as migrations e fiz a verificação na view. Deixei um pull request lá no seu git.

Da uma olhada nos pontos de alteração e qualquer dúvida é só falar.

Abraço

Ele está dando esse erro quando vou migrar as tabelas

PHP Fatal error:  Cannot declare class RelacionamentoRenovacaoMatricula, because the name is already in use in C:\Users\Elyton\Desktop\p\SiteSigamRR\database\migrations\2018_12_16_101802_relacionamento_renovacao_matricula.php on line 33

  Cannot declare class RelacionamentoRenovacaoMatricula, because the name is already in use

E quando vou mudar nome da classe pra tentar resolver ele vem com esse outro erro

In Connection.php line 664:

  SQLSTATE[42701]: Duplicate column: 7 ERROR:  column "matricula_id" of relation "renovacao" already exists (SQL: alt
  er table "renovacao" add column "matricula_id" integer not null)


In Connection.php line 458:

  SQLSTATE[42701]: Duplicate column: 7 ERROR:  column "matricula_id" of relation "renovacao" already exists

Agora nao sei se foi meu banco de dados que bugou de vez, quando você testou funcionou normalmente a migration ?

Opa, pelo erro parece que as colunas já existem. Tenta comentar as migrations e só executar. Compartilha aqui um dump do seu banco assim consigo testar a base também =)

Não deu certo o que vc sugeriu retorna isso " Class 'RelacionamentoRenovacaoMatricula' not found", tem hora que ele migra outra hora não isso dá agonia, e quando migra o campo renovacao_id nem aparece na tabela matricula

Oi Elyton, tem aquele dump da base?

Pode ser algum conflito com sujeira de banco. Eu subi a base aqui do zero, rodei as migrations apontei as classes e a partir disso o if na view já funcionou.

Tipo eu já deletei a base várias vezes, não sei vou ter que desinstalar o PostgreSQL, será que não pode ser a migration que está com mesmo nome eu notei isso nos arquivos que vc mandou

Oi Elyton

A instalação não deveria influenciar nesse sentido. Estamos apenas manipulando o banco pela conexão, isso não interfere na configuração da base em sí.

A migration força a criação do relacionamento, se deu conflito na query você pode comentar ela porque a tabela/coluna já existe.

Por isso falei lá em cima pra vc comentar o conteudo da migration e rodar =)

Se você compartilhar aqui um dump da base eu posso verificar quais colunas já existem e deixar as queries certas na migration.

Eu fiz os testes aqui apaguei as antigas migration e criei a nova com nomes diferentes e com aquele esquema de relacionamento e agora migrou sem problema.

Como estou em outro pc ele mostra isso "Sorry, the page you are looking for could not be found.", enquanto outro pc funciona normalmente sabe o porque ?

O campo renovação_id fica vazio quando cadastra matricula, e quando cadastra as renovacao o campo matricula_id fica vazio tbm vc colocou como para nao cair nesse erro ?

Como faz esse tratamento nos controller matricula e renovacao para pegar o id

Porque na lógica quando cria matrícula o campo renovação_id na tabela ficaria vazio eu acho, e na tabela renovação o campo matrícula_id deveria ser armazenado quando usuário vai confirmar a renovação clicando no botão tipo como eu fiz quando vai criar uma nova matrícula quando vai salvar o user_id ele precisa informa o e-mail no formulário, só que não sei pegar o id da matrícula e salvar quando vai solicitar a renovação, só que não lembro como pegar esse id sem o uso de formulário kkk, como eu faço isso ?

Eu estava testando pegar o id da matricula e salvar no banco só que ele só pega um id da matricula e nao pega a outra o que eu estou fazendo de errado ?

 public function store(RenovacaoRequest $request){


        $user = Auth()->user();

        $dados = $request->get('rematricula');

        $dados = $request->all();

        $matricula = Matricula::where('renovacao_id', $request->matricula_id)->get();

        $dados['matricula_id'] = $matricula[0]->id;

        dd($dados);
        /*foreach ($dados as $key => $dado) {

            Renovacao::create($dado);
        }


        return view('dashboard.renovacao.confirmacao', compact ('renovacao'));*/
    }

Oi Elyton, tudo bom?

Fiz uma bateria de testes aqui. Desde o cadastro de um usuário novo, passando pela matricula e finalmente fazendo a rematricula.

O primeiro bug estava na coluna usuario_id, que não podia ser vazia e não existe mais na classe Renovacao. Por isso, criei uma migration para dropar essa coluna:

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class RelacionamentoRenovacaoMatricula extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('matricula', function (Blueprint $table) {
            $table->integer('renovacao_id')->nullable()->change();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('matricula', function (Blueprint $table) {
            //
        });
    }
}

O segundo bug estava no fato da coluna renovacao_id não poder ser vazia também. No nosso caso, como uma matricula nem sempre vai ter uma renovação, defini ela como nullable em outra migration:

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class RelacionamentoRenovacaoMatricula extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('matricula', function (Blueprint $table) {
            $table->integer('renovacao_id')->nullable()->change();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('matricula', function (Blueprint $table) {
            //
        });
    }
}

Com isso, desempedimos a criação de usuarios =)

O próximo passo era o seu segundo problema:

só que não sei pegar o id da matrícula e salvar quando vai solicitar a renovação

Pra isso, a gente tem que buscar no banco todas as matriculas do usuário logado, pegar essa matricula, criar a Renovacao com ela e a partir da renovação criada atualizar a matricula também. Assim as duas chaves ficam definidas. Algo como:

// RenovacaoController
public function store(RenovacaoRequest $request){

        /**
         * @var User $user
         */
        $user = Auth()->user();

        $dados = $request->get('rematricula');
    // aqui a gente já pega a matricula do usuario logado
        $matricula = Matricula::where("user_id","=",$user->id)->first();
    // aqui a gente cria a renovação com os dados do request
        $renovacao = new Renovacao($dados[0]);
    //faz a associação entre um e o outro
        $renovacao->matricula()->associate($matricula);
    // manda a renovação pro banco
        $renovacao->save();
    // define a renovação da matricula
        $matricula->renovacao_id = $renovacao->id;
    // atualiza a matricula no banco
        $matricula->save();


        return view('dashboard.renovacao.confirmacao', compact ('renovacao'));
    }

Com isso o ciclo de vida do seu aluno fica estável.

Lembrando que os próximos relacionamentos que forem surgindo vão te colocar em situações parecidas, o esquema é sempre o mesmo quando o framework não mapeia essas mudanças automaticamente.

Essa parte de relacionar classes é a mais difícil mesmo da modelagem de sistemas MVC, mas pegando o jeito e a particularidade do ORM acaba saindo mais tranquilo com o tempo =)

Ah, atualizei aquele git com os ajustes que eu comentei acima também.

Abraço.

Bom fiz as alterações cadastro de renovação não está salvando se o usuário tiver 2 matricula só está salvando um, o botão inativo(caso tenha renovação) está ok, só notei esse erro quando vou deletar a renovação ou matricula

Foreign key violation: 7 ERROR: update or delete on table "renovacao" violates foreign key constraint "matricula_renovacao_id_foreign" on table "matricula" DETAIL: Key (id)=(1) is still referenced from table "matricula". (SQL: delete from "renovacao" where "id" = 1)

-- Função que deleta renovação

 public function renovacaoDestroy($id)
    {
        Renovacao::find($id)->delete();
        return redirect()->route('relatorio.renovacao.lista');
    }

Função que deleta Matricula

public function destroy($id)
    {
        Matricula::find($id)->delete();
        return redirect()->route('matricula.lista');
    }
solução!

Opa, o erro de chave estrangeira:

Foreign key violation: 7 ERROR: update or delete on table "renovacao" violates foreign key constraint "matricula_renovacao_id_foreign" on table "matricula" DETAIL: Key (id)=(1) is still referenced from table "matricula". (SQL: delete from "renovacao" where "id" = 1)

significa que existe um relacionamento entre a tabela renovacao e a trabela matricula atravez da coluna matricula_renovacao_id_foreign. Isso significa que pra excluir uma matricula, você precisa excluir também as renovacoes dela =)

Existe uma forma de configurar essa remoção em cascata. Ou seja, quando você excluir a matricula as renvoações dela também são excluidas. Esse procedimento a gente chama de cascade delete e cada banco tem sua sintaxe para configurar, não costuma ser muito traumático.

A questão agora é que não está salvando a renovação caso tenha 2 matricula qual seria a solução? ele está persistindo nesse erro depois que você indicou usar o novo código no store...

Tem 2 matricula cadastrada : https://prnt.sc/m1hq7q

Fazendo um dd ele retorna que salvou apenas uma matricula: https://prnt.sc/m1hqti

Cliquei em solução sem querer kkkkk, pode tirar ?

Mas não deveria excluir apenas o id ? porque ele apaga os dados da tabela matricula e não apenas o id ?

Opa, não consigo tirar. Consigo trocar depois quando realmente for resolvido =)

Mas não deveria excluir apenas o id ? porque ele apaga os dados da tabela matricula e não apenas o id ?

No modelo relacional excluir uma chave primária (id) representa uma instância única. No caso, excluir o id, que é a chave primária, implica em excluir a instância toda.

Assim como no modelo orientado a objetos, a gente usa uma referência para representar um objeto.

A questão agora é que não está salvando a renovação caso tenha 2 matricula qual seria a solução? ele está persistindo nesse erro depois que você indicou usar o novo código no store...

Qual erro exatamente? Os dois prints em anexo não tem nenhum stack trace, só a tela e o dump =)

A remoção em cascata funcionou? O problema com a chave estrangeira foi solucionado?

Não é exatamente um erro é um bug eu acho, ele não consegue capturar os outros dados que tem no form no primeiro print mostra todos os dados no segundo print ele mostra que só salvou apenas uma matricula na tabela renovação , sobre cascade ele meio que funcionou mas deveria ter colocado nas 2 tabelas que faz o relacionamento ?

Outro ponto, depois que eu fiz essas alterações quando eu vou apagar uma renovação ele apaga a matricula associada também isso nem deveria acontecer ele deveria apagar apenas a renovacao e não a matricula junto...

-- Relacionamento matricula_renovacao

<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class RelacionamentoRenovacaoMatricula extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('matricula', function (Blueprint $table) {
            $table->integer('renovacao_id')->unsigned();
            $table->foreign('renovacao_id')->references('id')->on('renovacao')->onDelete('cascade');
        });
    }
    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('matricula', function (Blueprint $table) {
            //
        });
    }
}

-- Relacionamento renovacao_matricula

<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class RelacionamentoRenovacaoMatricula extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('renovacao', function (Blueprint $table) {
            $table->integer('matricula_id')->unsigned();
            $table->foreign('matricula_id')->references('id')->on('matricula')->onDelete('cascade');
        });
    }
    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('renovacao', function (Blueprint $table) {
            //
        });
    }
}

Queria resolver primeiro p problema do cadastro das renovações que não salva se user logado tiver 2 ou 3 matricula...

Nesse caso eu fiz o teste cadastrando 2 matricula: https://prnt.sc/m1hq7q

No botão que vai confirmar o cadastro de renovação eu coloquei o dd($renovacao) e o resultado mostra que ele está salvando uma matricula na tabela renovação e não as 2 como mostra no print anterior não sei se você conseguiu entender: https://prnt.sc/m1hqti