简体   繁体   中英

Method Illuminate\Database\Eloquent\Collection::books does not exist.(laravel)

I am beginner of laravel, I want to store a book to books database, but after click button, it shows "Method Illuminate\Database\Eloquent\Collection::books does not exist." What am I missing? here are my codes.

BookController

public function create()
{
    return view('books.create');
}

public function store(Request $request)
{
    $this->validate($request, [
        'book' => 'required|max:255',
        'category' => 'required',
        'quantity' => 'required|numeric',
        'price'=>'required|numeric',
        'info'=>'required'
    ]);
    //$request->user()->member()->books()->create([
    $member=auth()->user()->member()->get();
    $member->books()->create([
        'book' => $request->book,
        'category' => $request->category,
        'quantity' => $request->quantity,
        'price'=>$request->price,
        'info'=>$request->info
    ]);

    return redirect('shops')->with('success', 'successful');
}

books.create

<form action="{{route('books.store')}}" method="POST" role="form">

        @csrf
        @method('POST')
        <div class="form-group">
            <label for="book">name:</label>
            <input id="book" name="book" class="form-control" placeholder="enter book name">
        </div>
        <div class="form-group">
            <label for="category">category:</label>
            <input id="category" name="category" class="form-control" placeholder="enter category">
        </div>
        <div class="form-group">
            <label for="quantity">quantity:</label>
            <input id="quantity" name="quantity" class="form-control" placeholder="enter quantity">
        </div>
        <div class="form-group">
            <label for="price">price:</label>
            <input id="price" name="price" class="form-control" placeholder="enter price">
        </div>
        <div class="form-group">
            <label for="info">info:</label>
            <textarea id="info" name="info" class="form-control" rows="10" placeholder="enter info"></textarea>
        </div>
        <button type="submit" class="btn-sm btn-primary">create</button>
    </form>

User and Member is one to one relation, and Book belongs to one Member

Book Model

public function member()
{
    return $this->belongsTo(Member::class);
}
protected $fillable = ['book','category','quantity','price','info'];

Member Model

public function books()
{
    return $this->hasMany(Book::class);
}

public function user()
{
    return $this->belongsTo(User::class);
}

User Model

 public function member()
{
    return $this->hasOne(Member::class);
}

books,user and member migration

books migration

public function up()
{
    Schema::create('books', function (Blueprint $table) {
        $table->increments('id');
        $table->unsignedInteger('member_id');
        $table->foreign('member_id')->references('id')->on('members')->onDelete('cascade');
        $table->string('name');
        $table->integer('quantity');
        $table->integer('price');
        $table->string('path');
        $table->string('info');
        $table->string('category');
        $table->timestamps();
    });
}

member migration

public function up()
{
    Schema::create('members', function (Blueprint $table) {
        $table->increments('id');
        $table->unsignedbigInteger('user_id');
        $table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
        $table->string('sex');
        $table->string('email');
        $table->string('address');
        $table->string('tel');
        $table->timestamps();
    });
}

user migration

public function up()
{
    Schema::create('users', function (Blueprint $table) {
        $table->id();
        $table->string('name');
        $table->string('email')->unique();
        $table->timestamp('email_verified_at')->nullable();
        $table->string('password');
        $table->rememberToken();
        $table->foreignId('current_team_id')->nullable();
        $table->text('profile_photo_path')->nullable();
        $table->timestamps();
    });
}

You are receiving a Collection from this chain of calls:

$member = auth()->user()->member()->get();

get is going to always return a Collection when called on a relationship method. If you want a single model you can call first instead:

$member = auth()->user()->member()->first();

Though first could return null so you may need to check that.

Another method to access the result of this relationship would be to use the dynamic property for the relationship member :

$member = auth()->user()->member;

Since that relationship is defined as a HasOne it knows to load it for a single result or null .

Assuming $member isn't null at this point you should be fine with the rest how it is.

$member=auth()->user()->member()->get(); returns a collection not an object of Member class. Use $member=auth()->user()->member()->first(); or $member=auth()->user()->member;

Try this


public function store(Request $request)
{
    $this->validate($request, [
        'book' => 'required|max:255',
        'category' => 'required',
        'quantity' => 'required|numeric',
        'price'=>'required|numeric',
        'info'=>'required'
    ]);
    
    $member=auth()->user()->member;
    if($member){
        $member->books()->create([
            'book' => $request->book,
            'category' => $request->category,
            'quantity' => $request->quantity,
            'price'=>$request->price,
            'info'=>$request->info
        ]);
    

        return redirect('shops')->with('success', 'successful');
    }

    //Member is not found, return with error
    return redirect()->back()->with('error', 'Member not found');
}

That error is due to the fact that this call $member=auth()->user()->member()->get(); . It's supposed to return a Collection of Member .

So when you try to call books on a collection hold by the variable member It' won't succeed as Illuminate\Support\Collection Class doesn't define a method books you have to loop trought that collection by using a foreach loop or a each or map method from Collection .

$member->each(function($member){
    $member->books()->create([
        //
    ]);
});

Or has you have already define in User Model that user will always have a single Member by using hasOne method.

So you can use auth()->user()->member()->first(); which return a single instance of type Member on which you call books method but with that you have to be sure that the Authenticated use has already one member which is attached to him to avoid any error. even though that is the case you can always check if variable $member is not null with an if statement

$member = auth()->user()->member()->first();
if($member){
    // here you can have access to `books`
    $member->books()->create([
        //...
    ]);        
}

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