itstrueimryan's avatar

Static properties on a Model class

I'm trying to create a standard index() method for most of my controllers that combines search, pagination, and sorting into one retrieve all listings functionality. I'm using a trait for those controllers which contains an index method, and that method uses some static properties defined on the associated model to know which columns to search and so on. For example, my User.php contains:

   /**
     * @var array
     */
    public static $searchableColumns = [
        'name',
        'username',
        'title',
        'email'
    ];

    /**
     * @var array
     */
    public static $searchableRelations = [
        'groups' => ['searchOn' => 'name']
    ];

    /**
     * @var string
     */
    public static $defaultOrderBy = 'name';

My issue is that...this just doesn't feel right. Every other property on the class is a protected instance variable, e..g:

protected $fillable = [
        'username',
        'email',
        ...
];

Is declaring static properties on a Model bad practice? If so, where should I define something like this?

0 likes
1 reply
Talinon's avatar

@itstrueimryan

The reason people frown upon public static properties is because it breaks the fundamental concept of encapsulation. When you define a public static property, you're basically just creating a global namespaced variable that can be accessed (or even more concerning, mutated) from anywhere within your app.

When I create a public static property/method, I always ask myself whether or not it makes sense to call a method/property on a class when I haven't instantiated an object. There are times when it does make sense.

In your case, it is likely fine - since you're not dealing with a specific object, but most likely using Eloquent to retrieve a collection of models.

I've done something similar to this in regards to table sorting/filtering/pagination. The first thing I analyzed was how many places within my app I'd need to access the public properties. Once I realized I'd only need to access the public static properties within a single area of the app, I decided to instead declare the properties within the controller. My reasoning was that the controller is what is responsible for deciding what information to gather, so might as well declare it there. Your trait could reference the properties on itself rather than reference properties on outside classes.

You could take this a step further and have the controller implement a contract that ensures that methods are defined that would be used as setters for the properties - but that is totally up to you on how complex you want to make this.

Please or to participate in this conversation.