Skip to content
Advertisement

Call to a member function save() on null in Laravel test

I’m doing a Laravel course on Codecourse. So far I have a Category model:

class Category extends Model
{   
    protected $fillable = [
        'name',
        'slug',
        'order'
    ];

    public function scopeParents(Builder $builder){
        $builder->whereNull('parent_id');
    }

    public function scopeOrder(Builder $builder, $direction = 'asc'){
        $builder->orderBy('order', $direction);
    }

    public function children(){
        $this->hasMany(Category::class, 'parent_id', 'id');
    }
}

A factory:

$factory->define(Category::class, function (Faker $faker) {
    return [
        'name' => $name = $faker->unique()->name,
        'slug' => Str::slug($name)
    ];
});

And a test

public function test_it_has_many_children()
    {
        $category = factory(Category::class)->create();

        $category->children()->save(
            factory(Category::class)->create()
        );

        $this->assertInstanceOf(Category::class, $category->children->first());
    }

However, when I run the test, I get:

Call to a member function save() on null

  at tests/Unit/Models/Categories/CategoryTest.php:14
    10|     public function test_it_many_children()
    11|     {
    12|         $category = factory(Category::class)->create();
    13| 
  > 14|         $category->children()->save(
    15|             factory(Category::class)->create()
    16|         );
    17| 
    18|         $this->assertInstanceOf(Category::class, $category->children->first());

What gives? The course is a couple of years old so I think there’re a couple of differences between Laravel versions, but this seems a bit more fundamental.

Advertisement

Answer

You are missing a return in your relation method:

public function children()
{
    return $this->hasMany(Category::class, 'parent_id', 'id');
}
User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement