DarkSpirit's avatar

Callback Function

I have watched a few videos (https://www.youtube.com/watch?v=p0IjbWICdEM and https://www.youtube.com/watch?v=gFJsBQIqpto) about the callback function on Youtube, but I cannot relate them to this one.

Could anyone please elaborate or briefly explain how it works here? Thanks.

HomeController.php from Social Network with PHP: Showing statuses on the timeline (26/37)

class HomeController extends Controller {

    public function index() {

        if (Auth::check()) {

            $statuses = Status::where(function($query) {
                return $query->where('user_id', Auth::user()->id)
                    ->orWhereIn('user_id', Auth::user()->friends()->lists('id'));
            })
            ->orderBy('created_at', 'desc')
            ->get();

            return view('timeline.index')->with('statuses', $statuses);
        }

        return view('home');
    }
}
0 likes
5 replies
willvincent's avatar

Basically, if the user is logged in (Auth::check()), statuses are loaded where the status' user id matches the current user, or where the status' user id is that of one of the current user's friends. Ordered with newest first. Those are then passed to the timeline view.

If the user is not logged in, the 'home' view is displayed.

$statuses = Status::where(function($query) {
                return $query->where('user_id', Auth::user()->id)
                    ->orWhereIn('user_id', Auth::user()->friends()->lists('id'));
            })
            ->orderBy('created_at', 'desc')
            ->get();

translates to, essentially, this query:

SELECT * FROM statuses WHERE user_id = 1 OR user_id IN (2, 3, 4, 5, 6) ORDER BY created_at DESC

Assuming the current user's ID is 1, and their friends user ids are 2-6.

DarkSpirit's avatar

It makes a bit sense to me now, but what about this line Status::where(function($query)? How does it work?

This is the Status.php

<?php

class Status extends Model {

    protected $table = 'statuses';

    protected $fillable = [
        'body'
    ];

    public function user() {

        return $this->belongsTo('Chatty\Models\User', 'user_id');
    }
}
jusahah87's avatar
Level 5

@DarkSpirit It simply works by user's code passing callback function into Eloquent's where method. Inside the callback the query object can be modified ($query->where('user_id', Auth::user()->id)) and then returned. Its just all about decorating (or extending) given database query with additional constraints. When you've finally decorated it enough you do the actual query and get the results.

If you are perhaps wondering why Status.php does not have method called where, its because where lives higher on the inheritance chain. Status extends Model so probably where lives inside Model.php (or even higher up).

One of the key things to note is that here callback function is invoked synchronously. If you have experience with languages like Javascript, well... in Javascript a callback function can be invoked either synchronously or asynchronously. Important to know the difference between these two ways to use a callback function.

1 like
willvincent's avatar

where is not part of Model, it's part of query builder.

1 like
jusahah87's avatar

@willvincent True. After quick checkup it seems where is part of conceptual inheritance tree but not the actual one. Instead the call is intercepted by a magic method and then rerouted to query Builder.

Pretty nice, Mr. Otwell, pretty nice...

1 like

Please or to participate in this conversation.