Laravel - SELF:: usage in models

Stefan Bogdanescu

Founder & Senior Architect · 2026-06-29

Laravel Company
# Demystifying `self::` in Laravel Models: How Eloquent Knows Where to Look As developers working with Laravel and Eloquent, we frequently encounter scenarios where static methods on a Model seem to defy conventional object-oriented rules. The specific confusion surrounding `self::` when performing database queries—especially when you don't explicitly define a `$table`—is a common sticking point. Let’s dive into your scenario: having a model with only `$fillable` attributes, and using static methods like `self::where(...)` to query the database. How does Laravel resolve which table these methods are operating on? Is there an underlying mechanism we need to understand? ## The Context of Static Methods in Eloquent The short answer is that you are not misunderstanding how `self::` works; you are tapping into a deep, implicit feature of the Eloquent ORM. When you call a method using the scope resolution operator (`::`), you are operating on the *class itself*, rather than a specific *instance* of that class. In the context of an Eloquent Model, the static methods defined within it inherit the context of that model's relationship with the database table. ### The Implicit Table Association When you define a Model in Laravel, Eloquent automatically maps that class to a specific database table based on the naming convention (e.g., `App\Models\Game` maps to the `games` table). This association is established internally by the framework. When you execute a static query like this: ```php public static function gamesToday() { return self::where('status', self::STATUS_FINISHED) ->where('created_at', '>=', Carbon::today()) ->count(); } ``` The `self::` mechanism doesn't need an explicit `$table` property because the Model class itself *is* the reference point. Eloquent uses the fully qualified class name (or the convention derived from it) to determine the underlying table context for any query initiated from that static scope. This allows models to be highly reusable and concise, which is a core principle of good Object-Relational Mapping design. ## Why This Works: Model as a Static Container Think of the Model class as a static container or blueprint for the data in the database. Because Laravel enforces a strict convention between the Model's class name and the physical table name, any operation initiated via `self::` is automatically scoped to that defined relationship. This design choice simplifies model development significantly. Instead of needing boilerplate code to define relationships or manually specify tables within every static query, Eloquent provides this context implicitly. This pattern adheres to the philosophy of keeping models lean and focused on data representation, allowing developers to focus on business logic rather than ORM plumbing. For more details on how Eloquent manages these associations and conventions, reading up on the core principles outlined by the [Laravel documentation](https://laravelcompany.com) is always beneficial. ## Best Practices: When to Use Static vs. Instance Methods While using static methods for simple, global queries (like counting records across the board) is perfectly fine, it’s important to understand the trade-offs. ### 1. Static Methods (`self::`) Use static methods when the logic is purely related to the *entire collection* of that model type, and doesn't depend on any specific instance data. This is ideal for utility functions or class-level queries, as seen in your example: counting games today. ### 2. Instance Methods Use instance methods when the operation requires context from a specific record. For example, if you wanted to find all finished games for a specific user, you would use an instance method on a specific `Game` object: ```php $game = Game::find(1); // Example of an instance-based query (more complex context) $todayCount = $game->status === self::STATUS_FINISHED ? $game->created_at >= Carbon::today() : 0; ``` In summary, the mystery surrounding `self::` is solved by recognizing that Eloquent leverages class conventions to implicitly manage table context. It’s a powerful feature that allows for elegant and concise data access, letting you write clean code without needing to manually define every database relationship in your static methods. By understanding this underlying mechanism, you can write more robust and idiomatic Laravel code.