Duplicate system on two forms

2020-05-06 13:17发布

问题:

My project is to create a small driving school for motorbike.

I have 4 tables: Former, Training, Revision, Motorbike

My functions create() and store() work for my 4 forms.

However, I have a big problem ... If, my motorbike is in revision on03/09/2019 to 05/09/2019 for the motorbike000001

and that I encode in my form training a booking on 03/09/2019 with as motorbike number000001; Normally the motorbike is unavailable, how can I handle that?

Is it possible to create a duplicate system for the forms revision ->training or the inverse training ->revision

In my Controller Revision I have this:

public function index()
    {
        $revisions = Revision::oldest()->paginate(5);
        return view('admin.revisions.index', compact('revisions'))
          ->with('i', (request()->input('page',1) -1)*5);
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()            
    {

        $motorbikes = Motorbike::all();
        return view('admin.revisions.create', compact('motorbikes','revisions'));
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {

        $date_revision_start = $request->get('date_revision_start');
        $date_revision_end = $request->get('date_revision_end');
        $hour_start = $request->get('hour_start');
        $hour_end = $request->get('hour_end');
        $garage = $request->get('garage');
        $fk_motorbike = $request->get('fk_motorbike');

        $conflict = Revision::where('fk_motorbike', $request->get('fk_motorbike'))->whereDate('date_revision_start', "<=" , $date_revision_start)
            ->whereDate('date_revision_end', ">=", $date_revision_start)
            ->first();

        $conflict2 = Revision::where('fk_motorbike', $request->get('fk_motorbike'))->whereDate('date_revision_start', "<=" , $date_revision_end)->whereDate('date_revision_end', ">=", $date_revision_end)->first();



        if(isset($conflict2) || isset($conflict)){
            return redirect()->route('revisions.index')
             ->with('error', 'duplicate');
        }

       else{
        Revision::create($request->all());
            return redirect()->route('revisions.index')
                ->with('success', 'new data created successfully');
        }

    }

And for the Controller Training

public function index()
    {
        $trainings = Training::oldest()->paginate(5);
        return view('admin.trainings.index', compact('trainings'));
                with('i', (request()->input('page', 1) -1) *5);
    }



    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {   
        $motorbikes = Motorbike::all();
        $formers = Former::all();
        return view('admin.trainings.create', compact('motorbikes','formers','trainings'));
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        $request->validate([
                'date_seance' => 'required',
                'hour_start' => 'required',
                'hour_end' => 'required',
                'fk_motorbike' => 'required',
                'fk_former' => 'required'


        ]);


       $exists = Training::where('date_seance', $request->get('date_seance'))->where('hour_start', $request->get('hour_start'))->where('hour_end', $request->get('hour_end'))->where('fk_motorbike', $request->get('fk_motorbike'))->count();

       if (!$exists){
            Training::create($request->all());
            return redirect()->route('trainings.index')
                ->with('success', 'Add');
        }

        else{
            return redirect()->route('trainings.index')
                ->with('error', 'Duplicate ');

        } 


    }

Could you help me please, because I'm still a beginner in Laravel and I want to solve this problem.

Thanks in advance

Edit

 $date_start = $request->get('date_seance'); 
       $fk_motorbike = $request->get('fk_motorbike');

       $hour_start = $request->get('hour_start');
       $hour_end = $request->get('hour_end');

        $conflictRevision = Revision::where('fk_motorbike', $fk_motorbike)
            ->whereDate('date_revision_start', "<=" , $date_start)
            ->whereDate('date_revision_end', ">=", $date_start)
            ->where('hour_start', "<=" , $hour_start)
            ->where('hour_end', "<=" , $hour_end)
            ->first();

        $conflictTraining = Training::where('fk_motorbike', $fk_motorbike)
            ->whereDate('date_seance', "=" , $date_start)
            ->where('hour_start', "<=" , $hour_start)
            ->where('hour_end', "<=" , $hour_end)
            ->first();

        if(isset($conflictTraining) || isset($conflictRevision)){
            return redirect()->route('trainings.index')
                 ->with('error', 'Duplicate ');
        }

        else{
            Training::create($request->all());
                return redirect()->route('trainings.index')
                    ->with('success', 'Add');
    }

回答1:

This is possible, and you have almost got what you need already. You can model the training duplicate code after the duplicate revision code and add a very similar revision duplicate code to get your answer.

I am going to explain in detail and repeat myself codewise, but hopefully this will be easier to understand. You can compress this code once it makes sense to you. Not the least of which would be to make the duplicate code for revision a separate method within your Controller Revision, so that both Controller Revision and Controller Training can draw from it. But that's later - for now let's get it working.

On your Controller Training, remove the $exists stuff for now. First we need to make sure there is no revision at the same time as the user wants to apply training for the motorbike. In this case, though, there is only one date for Training in your model, so only one $conflict check for the revision:

$date_start = $request->get('date_seance'); // I assume your form field for training is date_seance
$fk_motorbike = $request->get('fk_motorbike');

// NOTE: the $date_start MAY need to be converted to a Carbon instance if it doesn't work - same as before

$conflictRevision = Revision::where('fk_motorbike', $fk_motorbike)
        ->whereDate('date_revision_start', "<=" , $date_start)
        ->whereDate('date_revision_end', ">=", $date_start)
        ->first();

Now we need to check to see if there is a conflict for training. We can use the same PHP variables already assigned, just change the model we are querying. I assume seance is ONE day per your model:

$conflictTraining = Training::where('fk_motorbike', $fk_motorbike)
        ->whereDate('date_seance', "=" , $date_start)
        ->first();

And then it is a very similar if-check to the one we used in the revision check:

if(isset($conflictTraining) || isset($conflictRevision)){
     return redirect()->route('trainings.index')
            ->with('error', 'Duplicate ');
else{
     Training::create($request->all());
        return redirect()->route('trainings.index')
            ->with('success', 'Add');
}


回答2:

The easiest way is making use of a query scope in the Training model. I'll assume that a motorbike is the whole day unavailable when in revision.

public function scopeAvailable($query) 
{
    return $query->whereNotBetween('trainings.date_sceance', [
        'revisions.date_revision_start' => function($q) {
             return $q->where('trainings.fk_motorbike', '=', 'revisions.fk_motorbike');
        },
        'revisions.date_revision_end' => function($q) {
             return $q->where('trainings.fk_motorbike', '=', 'revisions.fk_motorbike');
        }]
    );
}

I haven't test this code. It is possible it won't give what you expect, in other words, my proposition is wrong. Using the scope would be

$exists = Training::where('date_seance', $request->get('date_seance'))->available()->count();