he estado trabajando en una app web tipo encuesta por medio de estapas - preguntas - respuestas, ahora mismo ya tengo la parte de guardar las respuestas de cada pregunta y las preguntas en su respectiva etapa, pero en el momento de actualizar o eliminar una etapa, queda actualizada con la ultima informacion, pero por ejemplo si elimine un pregunta, no aparece visualmente, pero en la base de datos queda la pregunta con sus respuestas ocupando espacio
Describo en img cual es el problema
Tengo 2 preguntas en la etapa, como se puede ver, si elimino una, tendria que quedarme como muestro en la Imagen de abajo, pero no es asi, siempre me muestra las misma, si agrego obviamente si me lo agrega, no se como eliminar esa relacion en la base de datos para que se actualize
EstapasEdit.blade.php
@extends('layouts.layout')
@section('content')
<form action="/dashboard/formulario/stages/{{ $stage->id }}" method="post">
@method('put')
<h2>ETAPA</h2>
<label>Titulo</label>
<input required type="text" name="title" value="{{ $stage->title }}">
<label>Descripcion</label>
<input required type="text" name="description" value="{{ $stage->description }}">
<h2>PREGUNTAS</h2>
<table>
<tbody>
@foreach($questions as $question)
<tr>
<td><input required name="questions[{{ $question->id }}]" type="text" value="{{ $question->title }}" ><td/>
<td>
<select name="types[{{ $question->id }}]" id="">
@foreach($types as $type)
@if($type->name == $question->type->name)
<option selected value="{{ $type->id }}">{{ @strtoupper($type->name) }}</option>
@else
<option value="{{ $type->id }}">{{ @strtoupper($type->name) }}</option>
@endif
@endforeach
</select>
</td>
<td>
<fieldset>
<legend>Respuestas</legend>
@foreach($question->answers as $answer)
@if($question->type->name == App\Type::OPCIONES['U'])
<input required name="answers[{{ $question->id }}][{{ $answer->id }}]" type="text" value="{{ $answer->title }}">
@elseif($question->type->name == App\Type::OPCIONES['C'])
<input required name="answers[{{ $question->id }}][{{ $answer->id }}]" type="text" value="{{ $answer->title }}">
@elseif($question->type->name == App\Type::OPCIONES['M'])
<input required name="answers[{{ $question->id }}][{{ $answer->id }}]" type="text" value="{{ $answer->title }}">
@endif
@endforeach
</fieldset>
<a href="">Agregar</a>
</td>
</tr>
@endforeach
</tbody>
</table>
<input class="btn btn-primary" type="submit" value="Guardar">
</form>
@endsection
Modelo Etapa
class Stage extends Model
{
protected $fillable = [
'id',
'title',
'description'
];
public function questions(){
return $this->hasMany('App\Question');
}
}
Modelo Pregunta
class Question extends Model
{
protected $table = 'questions';
protected $fillable = [
'id',
'title',
'stage_id',
'type_id',
];
public function stage() {
return $this->belongsTo('App\Stage');
}
public function type(){
return $this->belongsTo('App\Type');
}
public function answers(){
return $this->hasMany('App\Answer');
}
}
Modelo Respuesta
class Answer extends Model
{
public function __construct(array $attributes = ['title'])
{
parent::__construct($attributes);
}
protected $table = 'answers';
protected $fillable = [
'title',
'question_id'
];
public function question() {
return $this->belongsTo('App\Question');
}
public static function create(array $array) {
$answers = [];
return $answers;
}
}
Parte del controlador que actualiza
public function update(Request $request, Stage $stage)
{
$rules = [
'title' => 'max:150|string|unique:stages',
'description' => 'max:250|string'
];
$stage = Stage::findOrFail($stage)->first();
if ($request->get('title') != $stage->title ||
$request->get('description') != $stage->description) {
$this->validate($request, $rules);
$stage->title = $request->get('title');
$stage->description = $request->get('description');
$stage->save();
}
/*--------- SE RECORRE TODAS LAS PREGUNTAS ---------*/
foreach ($request->get('questions') as $id_q => $question) {
$question_test = new Question([
'id' => $id_q,
'title' => $question
]);
$type = Type::findOrFail($request->get('types')[$id_q]);
/*--------- SE ACTUALIZA LOS DATOS DE LA PREGUNTA ---------*/
$question_test->stage()->associate($stage);
$question_test->type()->associate($type);
if ($question_test->title == '') {
/*TODO: AGREGAR ENVIO DE ERROR*/
}
$question_test = Question::updateOrCreate([
'id' => $question_test->id
],[
'title' => $question_test->title,
'stage_id' => $question_test->stage_id,
'type_id' => $question_test->type_id
]);
/*--------- SE ACTUALIZA LOS RESPUESTAS DE LA PREGUNTA ---------*/
foreach ($request->get('answers') as $key => $answers) {
if ($id_q == $key) {
foreach ($answers as $id_a => $answer) {
if ($answer == '') {
/*TODO: AGREGAR ENVIO DE ERROR*/
}
$question_test->answers()->updateOrCreate([
'id' => $id_a
],[
'title' => $answer
]);
}
}
}
}
return redirect('/dashboard/formulario/stages');
}
Migraciones
Etapas
class CreateStagesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('stages', function (Blueprint $table) {
$table->increments('id');
$table->string('title');
$table->text('description');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('stages');
}
}
Preguntas
class CreateQuestionsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('questions', function (Blueprint $table) {
$table->increments('id');
$table->string('title');
$table->unsignedInteger('stage_id');
$table->unsignedInteger('type_id');
$table->timestamps();
$table->foreign('stage_id')->references('id')->on('stages');
$table->foreign('type_id')->references('id')->on('types');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('questions', function (Blueprint $table) {
$table->dropForeign('questions_type_id_foreign');
$table->dropForeign('questions_stage_id_foreign');
});
Schema::dropIfExists('questions');
}
}
Respuestas
class CreateAnswersTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('answers', function (Blueprint $table) {
$table->increments('id');
$table->string('title');
$table->unsignedInteger('question_id');
$table->timestamps();
$table->foreign('question_id')->references('id')->on('questions');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('answers', function (Blueprint $table) {
$table->dropForeign('answers_question_id_foreign');
});
Schema::dropIfExists('answers');
}
}
eliminar
elimina una pregunta? Pero lo hace medianteJavaScript
y solo la remueve visualmente, es decir, no envía ninguna consulta al backend, es así? Tu problema es que el eliminar la pregunta desde el formulario NO la elimina de la base de datos? Confirmá eso y publicá los archivos de migraciones o la estructura de la DB por lo que te preguntaron de las claves foráneas.