简体   繁体   中英

Add one to many in form - Backpack laravel

I'm using Backpack for Laravel to provide the backend area of my laravel website.

I'm having the following tables in my database structure:

在此输入图像描述

This is to add sets to a match, and add matches to a tournament.

These are my Models :

Tournament Model:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Backpack\CRUD\CrudTrait;

class Tournament extends Model
{
    use CrudTrait;

     /*
    |--------------------------------------------------------------------------
    | GLOBAL VARIABLES
    |--------------------------------------------------------------------------
    */

    protected $fillable = ['from', 'to', 'type', 'location', 'place'];

    /*
    |--------------------------------------------------------------------------
    | RELATIONS
    |--------------------------------------------------------------------------
    */

    public function matches()
    {
        return $this->hasMany('App\Models\Match');
    }
}

Match Model:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Backpack\CRUD\CrudTrait;

class Match extends Model
{
    use CrudTrait;

     /*
    |--------------------------------------------------------------------------
    | GLOBAL VARIABLES
    |--------------------------------------------------------------------------
    */

    protected $table = 'matches';

    protected $fillable = ['opponent'];

    /*
    |--------------------------------------------------------------------------
    | RELATIONS
    |--------------------------------------------------------------------------
    */

    public function sets()
    {
        return $this->hasMany('App\Models\Set');
    }
}

Set Model:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
use Backpack\CRUD\CrudTrait;

class Set extends Model
{
    use CrudTrait;

     /*
    |--------------------------------------------------------------------------
    | GLOBAL VARIABLES
    |--------------------------------------------------------------------------
    */

    protected $fillable = ['self', 'opponent', 'index'];

    public function match()
    {
        return $this->belongsTo('App\Models\Match');
    }
}

Now I would like to have the following when I create a Tournament in backend:

在此输入图像描述

I can already set from, to, type, location and place. But now I would like the possibility to add a match and add sets to that match. This all on one page.

But I'm a bit stuck on how to do this. Can someone help me on my way?

I would recommend to all do in multiple steps. Create a tournament, go to tournament view, add matches. Go to a match view, add sets. Wayyyy easier than what you want to do. But hey, it's your application and you want to do in one go.

There are going to be some restrictions like you can only submit one match at a time, to avoid mixing your sets. Unless you want to use javascript and automatically name your matches and sets.

In your models (Match & Set) add foreign keys in the $fillable array. We might need them.

So when you submit the form, you create the tournament

public function save(Request $request)
{
    $tournament = Tournament::create([
        ...
    ]);

    $match = Match::create([
        'tournament_id' => $tournament->id,
        ...
    ]);

    $match->sets()->saveMany([
        new Set(['self' => $request->set1_self, ...]), //foreign key auto inserted
        new Set(['self' => $request->set2_self, ...]),
        new Set(['self' => $request->set3_self, ...]),
    ]);
}

This means in your form, you have to name your sets input like

<input name="set1_self"/>
<input name="set1_opponent"/>

And so on.

Now if you want to make multiple matches at the same time, you will have to find a way to name your inputs like

<input name="match1_set1_self" />
<input name="match1_set2_self" />

And so on.

Since you want to make everything in one page. You can build a mini SPA just to add tournaments, matches & sets. The page won't change/reload.

Okay so the best is what @EddyTheDove mentioned,

$match->sets()->saveMany([
    new Set(['self' => $request->set1_self, ...]);
    new Set(['self' => $request->set2_self, ...]);
    new Set(['self' => $request->set3_self, ...]);
]);

But it should be done at once via Ajax, And vue.js will be also awesome. Ajax call to create a new tournament, Along fetch all the matches in the same call and attach the selected matches, Again Ajax request to add the matches to the tournament which was created in the earlier Ajax call.

Send the match info in a request to controller via ajax, Where the above code will save it. For more sets, Duplicate the a set html but don't forget the input names. Provide some code that we can play with.

You will need to have part of your logic in JavaScript. In your example, when you click the 'Add another match' button you will manipulate the HTML DOM and duplicate the 'Add Match' box.

After filling the whole form, it will get submitted to the server.

The server then needs to:

  1. Create a new Tournament object and save it.

  2. Loop through submitted matches and create new Matches objects and link them to the previously created tournament. Loop through submitted sets and link them to the created match.

I think you should design it in such a way that the tournament is created first before the add match/set form is shown. It is still possible to have them all in one form though by applying Ajax or Vue.js etc.

  1. After a new tournament is added successfully, hide the form and display the new tournament info along with the add new match form.

  2. When the new match is added successfully, clear the new match form and load the new match info.

Note: I wonder how you plan to allow the opponent to be added though.

Cheers!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM