Passing a class as function parameter
Stefan Bogdanescu
Founder & Senior Architect · 2026-06-29
# Passing a Class as a Function Parameter: Moving Beyond Simple Variables in PHP
As developers working within the Laravel ecosystem, we constantly grapple with how to structure our code to be flexible, testable, and maintainable. One common pattern that arises when dealing with dynamic tasksâlike generating unique database slugsâis the desire to pass an entire class context into a helper function so it can perform complex operations against that context.
The initial attempt you presented:
```php
function doSomething($param, Class) {
Class::someFunction();
}
$someVar = doSomething($param, Class);
```
While conceptually appealing, this direct approach runs into limitations in standard PHP and object-oriented programming (OOP). The answer to "Is it possible?" depends heavily on *what* you intend for the function to receive: a class name (a string), an instance of a class, or a fully instantiated object.
Let's dive into why this direct approach is problematic and explore the correct, idiomatic ways to achieve your goal in a Laravel context.
## The Problem with Passing Class Names
When you pass just the class name as a string, like `Class`, the function receives only text. To call `$Class::someFunction()`, PHP needs to resolve that string into an actual class reference at runtime. While this *can* be done using reflection or dynamic calls (like `call_user_func`), it is generally considered an anti-pattern in modern, strongly-typed languages like PHP, especially when dealing with complex application logic involving Eloquent models.
The core issue is that functions should operate on *data* or *objects*, not just strings representing types.
## The Correct Approach: Dependency Injection and Object Passing
The most robust solution involves adhering to OOP principles by passing actual class instances (or interfaces) into your helper functions. This practice aligns perfectly with the principles championed by frameworks like Laravel, which heavily rely on dependency injection.
### 1. Passing Model Instances
If your helper function needs to query data related to a specific model (like `Apk`), you should pass an instance of that model, not just its name. This gives the function direct access to Eloquent relationships and methods.
**Instead of:**
```php
// Attempting to pass context via class name
$helper->uniqueSlug($appname, Apk);
```
**Do this:** Pass the necessary Eloquent model instance:
```php
use App\Models\Apk; // Assuming you are using Laravel's Eloquent models
class SlugHelper
{
/**
* Generates a unique slug based on database checks.
* @param string $str The string to slugify.
* @param Apk $model The specific model context needed for querying.
* @return string
*/
public function uniqueSlug(string $str, Apk $model): string
{
$slug = Str::slug($str);
// Now we can safely query the database using the passed model instance
$count = $model::whereRaw("slug RLIKE '^{$slug}(-[0-9]+)?$'")->count();
return $count ? "{$slug}-{$count}" : $slug;
}
}
```
### 2. Leveraging Laravel's Structure
In this refactored example, the `uniqueSlug` method no longer needs to worry about *how* to find the `Apk` model; it simply trusts that the object passed to it (`$model`) has the necessary database capabilities. This separation of concerns makes your code cleaner and easier to testâa key principle when building robust applications on Laravel.
When designing reusable logic, think about what data the function *needs* to operate, rather than what class it *represents*. If you need multiple models, consider defining an interface or a dedicated Service class to handle the complex interaction, which keeps your business logic separate from simple utility functions. For deeper architectural guidance on structuring these services within Laravel, exploring patterns found in documentation like https://laravelcompany.com is highly recommended.
## Conclusion
Passing a class as a parameter should be replaced by passing *instances* of classes or defining interfaces. This shift moves your code from relying on fragile runtime string manipulation to leveraging the powerful structure of OOP. By embracing dependency injection and object orientation, you ensure that your