Laravel выбор моделей на основе отношений - PullRequest
0 голосов
/ 10 марта 2020

Я работаю над библиотечным приложением и хочу создать функцию, с помощью которой пользователь может сдать книгу в аренду клиенту. Однако я хочу, чтобы книги, сданные в аренду прямо сейчас, не отображались в поле выбора при аренде другой книги. Я просмотрел несколько статей по этому поводу, но не смог найти решение, поэтому буду рад любой помощи. Идея состоит в том, что когда в книге установлен атрибут «maxreturndate», она не будет отображаться.

CheckedOutController:

    <?php

    namespace App\Http\Controllers;

    use Illuminate\Http\Request;
    use App\CheckedOut;
    use App\Book;
    use App\Reader;



    class CheckedOutController extends Controller
    {
        /**
         * Display a listing of the resource.
         *
         * @return \Illuminate\Http\Response
         */
        public function index()
        {
            $checkedOuts = CheckedOut::with(['book', 'reader'])->get();

            return view('checkedouts/index', compact('checkedOuts'));
        }

        /**
         * Show the form for creating a new resource.
         *
         * @return \Illuminate\Http\Response
         */
        public function create()
        {
            $books = Book::all();
            $readers = Reader::all();

            return view('checkedouts/create', compact('books','readers'));
        }

        /**
         * Store a newly created resource in storage.
         *
         * @param  \Illuminate\Http\Request  $request
         * @return \Illuminate\Http\Response
         */
        public function store(Request $request)
        {
            $validatedData = $request->validate([
                'book_id' => 'required',
                'reader_id' => 'required',
                'maxreturndate' => 'required|date',
                'returndate' => 'nullable',
                ]);

                $checkedOut = CheckedOut::create($validatedData);

                return redirect('checkedouts')->with('success', 'Buch wurde erfolgreich verliehen!');
        }

        /**
         * Display the specified resource.
         *
         * @param  int  $id
         * @return \Illuminate\Http\Response
         */
        public function show($id)
        {
            //
        }

        /**
         * Show the form for editing the specified resource.
         *
         * @param  int  $id
         * @return \Illuminate\Http\Response
         */
        public function edit($id)
        {
            //
        }

        /**
         * Update the specified resource in storage.
         *
         * @param  \Illuminate\Http\Request  $request
         * @param  int  $id
         * @return \Illuminate\Http\Response
         */
        public function update(Request $request, $id)
        {
            //
        }

        /**
         * Remove the specified resource from storage.
         *
         * @param  int  $id
         * @return \Illuminate\Http\Response
         */
        public function destroy($id)
        {
            //
        }
    }

index. клинок. php

@extends('layout')


@section('title')
<title>Alle ausgeliehen Bücher</title>
@section('content')
<style>
  .uper {
    margin-top: 40px;
  }
</style>
<div class="uper">
  @if(session()->get('success'))
  <div class="alert alert-success">
    {{ session()->get('success') }}
  </div><br />
  @endif

  <table class="table table-hover">
    <thead>
      <tr>
        <td>ID</td>
        <td>Titel</td>
        <td>Verliehen an</td>
        <td>Verleihdatum</td>
        <td>Fällig am</td>
        <td>Zurückgebracht am</td>
        <td colspan="2">Funktionen</td>
      </tr>
    </thead>
    <tbody>
      @foreach($checkedOuts as $checkedOut)
      <tr>
        <td>{{$checkedOut->id}}</td>
        <td>{{$checkedOut->book->title}}</td>
        <td>{{$checkedOut->reader->name}}</td>
        <td>{{$checkedOut->created_at}}</td>
        <td >{{$checkedOut->maxreturndate}}</td>
        <td>{{$checkedOut->returndate}}</td>
        <td></td>

        <td><a href="{{ route('checkedouts.edit', $checkedOut->id)}}" class="btn btn-primary">Bearbeiten</a></td>
        <td><a href="{{ route('checkedouts.show', $checkedOut->id)}}" class="btn btn-primary">Anzeigen</a></td>
        <td>
          <form action="{{ route('checkedouts.destroy', $checkedOut->id)}}" method="post">
            @csrf
            @method('DELETE')
            <button class="btn btn-danger" type="submit">Löschen</button>
          </form>
        </td>
      </tr>
      @endforeach
    </tbody>
  </table>
  <div>
    @endsection

Миграции:

<?php

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

class CreateCheckedOutsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('checked_outs', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->bigInteger('book_id')->unsigned();
            $table->foreign('book_id')->references('id')->on('books')->onDelete('cascade');
            $table->bigInteger('reader_id')->unsigned();
            $table->foreign('reader_id')->references('id')->on('readers')->onDelete('cascade');
            $table->date('maxreturndate');
            $table->date('returndate')->nullable();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('checked_outs');
    }
}

create.blade. php

@extends('layout')


@section('title')
<title>Buch verleihen</title>
@section('stylesheets')
<script src="http://code.jquery.com/jquery-3.4.1.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/select2@4.0.13/dist/js/select2.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/select2@4.0.13/dist/css/select2.min.css" rel="stylesheet" />


@endsection
@section('content')
<style>
    .uper {
        margin-top: 40px;
    }
</style>
<div class="card uper">
    <div class="card-header">
        Buch verleihen
    </div>
    <div class="card-body">
        <form method="post" action="{{ route('checkedouts.store') }}">
            <div class="form-group">
                @csrf
                <label for="book_id">Buch:</label>
                <select name="book_id" class="form-control select2-single <!-- @error('book_id') is-invalid @enderror -->">
                    @foreach ($books as $book)
                    <option value="{{ $book->id }}">{{ $book->title }}</option>
                    @endforeach
                </select>
                @error('book_id')
                <div class="alert alert-danger">{{ $message }}</div>
                @enderror
            </div>

            <div class="form-group">
                <label for="reader_id">Verleihen an:</label>
                <select name="reader_id" class="form-control select2-single <!-- @error('reader_id') is-invalid @enderror -->">
                    @foreach ($readers as $reader)
                    <option value="{{ $reader->id }}">{{ $reader->name }}</option>
                    @endforeach
                </select>
                @error('reader_id')
                <div class="alert alert-danger">{{ $message }}</div>
                @enderror
            </div>

            <div class="form-group">
                <label for="maxreturndate">Zurückbringen bis:</label>
                <input type="date" class="form-control" name="maxreturndate" />
                @error('name')
                <div class="alert alert-danger">{{ $message }}</div>
                @enderror
            </div>

            <button type="submit" class="btn btn-primary">Verleihen</button>
        </form>
    </div>
</div>
<script type="text/javascript">
    $(".select2-single").select2();
</script>

@endsection

Отношения между 3 моделями:

Книга:

public function checkedOut(){
    return $this->hasOne(CheckedOut::class);
}

Читатель:

public function checkedOut()
    {
        return $this->belongsTo(CheckedOut::class);
    }

CheckedOut:

public function book(){
    return $this->belongsTo(Book::class);

}

public function reader(){
    return $this->belongsTo(Reader::class);

}

Ответы [ 2 ]

0 голосов
/ 11 марта 2020

когда в книге установлен атрибут maxreturndate, она не будет отображаться

Поскольку вы не указали в своей миграции, я предполагаю, что у вас есть maxreturndate Обнуляемое поле в вашей таблице books, тогда вы сможете просто создать локальную область , когда захотите свой список "не арендованных" книг.

Вот пример создания области видимости notRented:

// in your Book model define the local scope
public function scopeNotRented($query){
    return $query->whereNotNull('maxreturndate');
}

// in the create method of your controller
public function create()
{
    $books = Book::notRented()->get();
    $readers = Reader::all();

    return view('checkedouts/create', compact('books','readers'));
}
0 голосов
/ 10 марта 2020

Я предлагаю настроить Books и Readers с отношением "многие ко многим" . Теперь ваши модели могут выглядеть следующим образом:

<?php
namespace App;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\Pivot;

class Book extends Model
{
    public function readers()
    {
        return $this
            ->belongsToMany(\App\Reader::class, 'checked_outs')
            ->using(\App\Checkout::class)
            ->withPivot(['returndate', 'maxreturndate']);
    }
}

class Reader extends Model
{
    public function books()
    {
        return $this
            ->belongsToMany(\App\Book::class, 'checked_outs')
            ->using(\App\Checkout::class)
            ->withPivot(['returndate', 'maxreturndate']);
    }
}

class Checkout extends Pivot
{
    // this should be named `book_reader` but we override it here
    $table = "checked_outs";

    $dates = [
        "maxreturndate",
        "returndate",
    ];
}

Я создал сводную модель , которая не нужна, но позволяет вам работать непосредственно с сводной таблицей и создавать дополнительные приписывает даты автоматически. Полезно ли это - вопрос мнения. Вам следует переименовать таблицу checked_outs в book_reader, что является соглашением об именах, которое Laravel ожидает для сводной таблицы.

Получить книги, которые не были извлечены, достаточно просто: используя doesntHave метод , чтобы проверить отсутствие связи.

public function create()
{
    $books = Book::doesntHave("readers")->get();
    $readers = Reader::all();

    return view('checkedouts/create', compact('books','readers'));
}

И «проверка» книги может выглядеть так:

public function store(Request $request)
{
    $reader = Reader::find($request->reader_id);
    $reader
        ->books()
        ->attach(
            $request->book_id,
            ["returndate" => Carbon\Carbon::now()->addDays(7)]
        );
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...