Back to Course |
PHP for Laravel Developers

Visibility: public/private/protected

When discussing OOP, we must touch the "visibility" topic, meaning the public/private/protected keywords before properties/methods. When to use which?

For example, when creating methods in Controllers, we're probably used to "blindly" type public function ...:

EveryControllerEver.php

public function index()
{
// ...
}
 
public function create()
{
// ...
}

Question: in what cases would we change the methods to private or protected?

First, let me tell you the theory.

  • public: property/method can be accessed from inside the class and all classes extending it and their objects
  • private: property/method can be accessed only inside the class same class but not in "children" classes
  • protected: property/method can be accessed within the class itself and by inheriting and parent classes but not in their objects

An example of an Eloquent model with a few properties:

app\Models\Task.php:

use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Relations\HasMany;
 
class Task extends Model
{
protected $fillable = ['name', 'description'];
 
public function documents(): HasMany
{
return $this->HasMany(Document::class);
}
 
public function shortDescription(): Attribute
{
return new Attribute(get: fn () => $this->getShortDescription($this->description));
}
 
private function getShortDescription($text): string
{
return substr($text, 0, 50) . '...';
}
}

Now, let's create a new object for the Task:

// Somewhere in Controller...
$task = new App\Models\Task();

Then, what properties or methods can we access? See below what will work and what will throw errors:

// This will work, because documents() is public
$task->documents()->create(...);
 
// This will throw an error because $fillable is protected
$fillables = $task->fillable;
 
// This will throw error because getShortDescription() is private
echo $task->getShortDescription($this->description);

So, generally, you create most of the properties/methods public, except for these cases:

  • private means that it's an "internal" property/method of that class, used in some other operations inside that class. In our example, getShortDescription() is used only in another method of the same class, nowhere else.
  • protected is more tricky and a bit hard to understand: it's used for internal purposes but with limited usage outside of the class: only by child classes, but not their objects.

Okay, so that's a theory. But now, in practice...


Hey, psssst, let me tell you a "controversial" secret.

In your Laravel projects, it's probably okay if you just define EVERYTHING as public. Nothing will break.

I know, I know, some developers would disagree because you need to protect some methods from being extended/overridden.

But that logic is more theoretical than practical. It's more suitable for general OOP cases inside of the framework or large applications where you have a big structure of classes extending each other.

In typical Laravel applications, where you have mostly just Controller/Model classes without a large hierarchy, you will likely not do any damage by just defining everything as public.

This idea can also be backed up by the PHP logic, as public is the default value. Quoting the docs: "Properties/methods declared without any explicit visibility keyword are defined as public".

The only exception I know of is Laravel Livewire. The way it works, all the public properties will be automatically passed to the server requests, which means they may be visible on the front end, which may be a security concern.