phplaravel-7one-to-one

LARAVEL 7 One to One Relationship Dropdown list only display items with no relationship


I'm using Laravel 7 and creating a dropdown list where the book should only display items that do not relate to the student because I'm creating a one on one relationship. How am I going to do that?

Create View

<div class="form-group">
     <div class="col-md-6 col-sm-6 col-xs-12">
    <label class="control-label col-md-3 col-sm-3 col-xs-12" for="book">Book <span class="required">*</span></label>

    
        <select class="form-select" style="color: #41A7A5" aria-label="Default select example" name="book">
        <option value="">Select Book</option>
           @foreach ($books as $book)
           @if($book->students->book_id == $book->id)
           <option name="book" value="{{$book->id}}">{{$book->name}}</option>  
           
           @endif
           @endforeach
        </select>
     </div>
   </div>

Student Controller - Create

 public function create(){
  $students = Student::query()->with('books')->latest();
     $books = Book::all();
    return view('students.create',compact('students','books'));
 }

Book Model

class Book extends Model{


protected $fillable = [
    'name','description' 
 ];
 
 public function students(): HasOne
 {
     return $this->hasOne(Student::class, 'book_id', 'id');
 }}

Student Model

class Student extends Model
{
    protected $fillable = [
    'book_id','name' 
 ];

 public function books(){
    return $this->belongsTo(Book::class, 'book_id');
}}

Solution

  • Rather than using the all() function, on your Book model, you could filter out the books that have a related student using the doesntHave() function.

    This function take a relation as a parameter and returns all the models that does not have any related model for that relation.

    Please note that since we've added a condition to the query, we need to use get() rather than all().

     public function create(){
        $students = Student::query()->with('books')->latest();
        
        // retrieve all the book without a student related to it
        $books = Book::doesntHave('students')->get();
    
        return view('students.create',compact('students','books'));
     }
    

    As a side note, since you re creating a 0,1 <-> 0,1 relation between the Student and the Book model, you might want to rename the respective relations for book and student. Otherwise, it might get confusing when comming back to the code later.