Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is $post->comments()->create() more expensive than Comment::create() in Laravel?

Tags:

sql

php

laravel

In Laravel PHP Framework, when you have, let's say, a relationship between two tables e.g. one post can have one or multiple comments, you can create the comments of the post these ways:

// Option 1
$post->comments()->create(['text' => 'Greate article...']);

or

// Option 2
Comment::create([
    'post_id' => 1,
    'text' => 'Greate article...',
]);

Of course, it depends on the cases. Below are my cases.

  • For both options, the Post ID 1 has already been validated in the form request whether the post with the ID 1 does exist or not.
  • For some reasons, I already need to retrieve the post from the database first, thus I already have the post model.

In these above cases, is the Option 1 more expensive than the Option 2?

like image 984
O Connor Avatar asked Nov 30 '25 03:11

O Connor


1 Answers

You can test the queries your application makes by listening to the queries using DB::listen().

I have setup the following as a test:

Migrations:

Schema::create('posts', function (Blueprint $table) {
    $table->bigIncrements('id');
    $table->string('title');
    $table->string('content');
    $table->timestamps();
});

Schema::create('comments', function (Blueprint $table) {
    $table->bigIncrements('id');
    $table->unsignedBigInteger('post_id');
    $table->string('text');
    $table->timestamps();
});

Models:

class Post extends Model
{
    protected $guarded = [];
    
    public function comments()
    {
        return $this->hasMany(Comment::class);
    }
}

class Comment extends Model
{
    protected $guarded = [];
    
    public function post()
    {
        return $this->belongsTo(Post::class);
    }
}

Test:

$post = Post::create([
    'title' => 'Hello World',
    'content' => 'Here I am!',
]);

$queries = collect();

DB::listen(function ($query) use ($queries) {
    $queries->push($query->time);
});

for ($i = 1; $i <= 3000; $i += 1) {
    Comment::create([
        'post_id' => $post->id,
        'text' => 'Facade '.$i,
    ]);
    
    $post->comments()->create([
        'text' => 'Relation '.$i,
    ]);
}

$totalTime = [0, 0];

foreach ($queries as $idx => $time) {
    $totalTime[$idx%2] += $time;
}

return [
    'facade' => $totalTime[0],
    'relation' => $totalTime[1],
];

This outputs:

array:2 [▼
  "facade" => 1861.3
  "relation" => 1919.9
]

So you can see the relation way of create is actually approximately 3% slower in my test scenario.

I have prepared this implode if you want to experiment further.

like image 162
Kurt Friars Avatar answered Dec 02 '25 18:12

Kurt Friars



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!