Разбираемся с protected , $fillable и #[Fillable] в Laravel
Если вы изучаете Laravel, вы могли заметитькое-что необычное в новых моделях Laravel:
#[Fillable(['name', 'email', 'password'])]
#[Hidden(['password', 'remember_token'])]
class User extends Authenticatable
{
//
}Если вы изучали традиционный подход в Laravel, вы можете задаться вопросом:
Что стало с
protected $fillableиprotected $hidden?
И что более важно:
Является ли
#[Fillable]свойством? Можно ли сделать егоprotected?
Чтобы полностью в этом разобраться, нам нужно разделить три концепции PHP:
- Свойства (Properties)
- Область видимости (Visibility)
- Атрибуты (Attributes)
Давайте начнём с самого начала.
1. Что такое свойство в PHP?
Свойство — это, по сути, переменная, принадлежащая классу или объекту.
Например:
class User
{
public $name;
public $email;
}Здесь $name и $email — это свойства класса User .
Мы можем создать объект:
$user = new User();
$user->name = "Aditya";
$user->email = "aditya@example.com";Теперь объект содержит данные:
User object
│
├── name → "Aditya"
└── email → "aditya@example.com"Так что когда вы видите:
$user->namename — это свойство, принадлежащее объекту $user .
2. Свойства имеют область видимости
PHP позволяет нам контролировать, кто может получать доступ к свойству.
Существует три основных модификатора видимости:
public
protected
privateНапример:
class User
{
public $name;
protected $email;
private $password;
}У этих трёх свойств разные правила доступа.
public
К публичному свойству можно обратиться откуда угодно.
$user = new User();
$user->name = "Aditya";
echo $user->name;Это работает, потому что $name — публичное свойство.
protected
К защищённому свойству можно обратиться внутри самого класса и в его классах-потомках.
class User
{
protected $email;
}Вы не можете напрямую обратиться к нему извне:
$user = new User();
$user->email = "aditya@example.com";Это приведёт к ошибке доступа, так как $email имеет модификатор protected.
private
К приватному свойству можно обратиться только из того класса, в котором оно объявлено.
class User
{
private $password;
}Вне класса:
$user->password = "secret";так сделать нельзя.
3. Что означает protected $fillable ?
Теперь давайте посмотрим на Laravel.
Традиционная модель User в Laravel может содержать:
class User extends Authenticatable
{
protected $fillable = [
'name',
'email',
'password',
];
}Давайте разберём это по частям.
protected— это модификатор видимости.
$fillable— это имя свойства.
[
'name',
'email',
'password'
]— это значение, хранящееся в этом свойстве.
Таким образом:
protected $fillable = [
'name',
'email',
'password',
];означает:
Создать защищённое свойство с именем
$fillable, содержащее эти три значения.
4. Зачем Laravel нужен $fillable ?
Laravel использует $fillable для контроля массового заполнения (mass assignment).
Например:
$user = User::create([
'name' => 'Aditya',
'email' => 'aditya@example.com',
'password' => 'secret',
]);Laravel должен знать, какие поля разрешено заполнять таким способом.
Для этого и нужен $fillable :
protected $fillable = [
'name',
'email',
'password',
];Он говорит Laravel:
Эти атрибуты разрешены для массового заполнения.
Это важный механизм безопасности, предотвращающий произвольное изменение пользователями чувствительных полей в базе данных.
5. Так что же такое #[Fillable(...)] ?
Теперь перейдём к более новому синтаксису:
#[Fillable(['name', 'email', 'password'])]Это выглядит похоже на $fillable , но принципиально отличается от него.
Это не свойство.
Это атрибут PHP.
PHP представил атрибуты в версии PHP 8.
Синтаксис #[] обозначает атрибут:
#[SomeAttribute]Атрибут можно представить как метаданные или дополнительные инструкции, прикреплённые к PHP-коду.
Например:
#[Fillable(['name', 'email', 'password'])]
class User extends Authenticatable
{
}Атрибут Fillable прикреплён к классу User .
Laravel затем может считать эту информацию и использовать её для конфигурации модели.
6. Почему нельзя написать protected #[Fillable(...)] ?
Именно здесь разница становится существенной.
Вы можете подумать:
protected #[Fillable(...)]Но атрибуты PHP работают иначе.
Почему?
Потому что:
protected $fillable;— это объявление свойства.
В то время как:
#[Fillable(...)]— это атрибут.
Это разные языковые конструкции.
Представьте это так:
protected $fillable
│ │
│ └── Property
│
└── VisibilityВ то время как:
#[Fillable(...)]
│
└── Attribute / MetadataК самому атрибуту не привязан модификатор protected .
7. Атрибуты можно вешать на свойства
Вот здесь начинается самое интересное.
Атрибуты PHP на самом деле можно прикрепить к разным элементам кода, включая свойства.
Например:
class User
{
#[SomeAttribute]
public string $name;
}Здесь:
public string $name;всё ещё является свойством.
А:
#[SomeAttribute]— это метаданные, прикреплённые к этому свойству.
Таким образом, эти концепции могут сосуществовать:
class User
{
#[SomeAttribute]
protected string $name;
}Здесь:
protected→ область видимости$name→ свойствоstring→ тип свойства#[SomeAttribute]→ атрибут
8. Простая ментальная модель
Представьте автомобиль.
Свойства описывают то, что есть у автомобиля:
class Car
{
public string $color;
protected int $speed;
}У автомобиля есть:
color
speedЭто свойства.
Область видимости говорит нам, кто может получить к ним доступ:
public → everyone
protected → class + children
private → class onlyТеперь представьте, что вы наклеиваете на машину шильдик:
#[Electric]
class Car
{
}#[Electric] не является свойством вроде $color .
Это метаданные, сообщающие PHP или фреймворку информацию о классе.
9. Традиционный Laravel против Laravel на атрибутах
Традиционный Laravel:
class User extends Authenticatable
{
protected $fillable = [
'name',
'email',
'password',
]; protected $hidden = [
'password',
'remember_token',
];
}Здесь у нас есть два свойства:
$fillable
$hiddenОба они являются protected.
При подходе с использованием атрибутов:
#[Fillable(['name', 'email', 'password'])]
#[Hidden(['password', 'remember_token'])]
class User extends Authenticatable
{
}Теперь у нас нет свойств $fillable и $hidden , прописанных в классе.
Вместо этого мы прикрепляем атрибуты Laravel к классу.
10. Не путайте $fillable с Fillable
Эта крошечная разница чрезвычайно важна.
$fillable
protected $fillable = [
'name',
'email',
];$fillable — это свойство.
Fillable
#[Fillable([
'name',
'email',
])]Fillable — это класс атрибута.
Заметьте разницу:
$fillable
↑
Propertyпротив:
Fillable
↑
AttributeСимвол $ — полезная подсказка, указывающая на то, что вы имеете дело с переменной или свойством.
11. Как насчёт методов?
Та же концепция применима и к методам.
Метод — это действие:
class User
{
public function login()
{
// ...
}
}Вы также можете прикрепить атрибут к методу:
class User
{
#[SomeAttribute]
public function login()
{
// ...
}
}Здесь:
publicуправляет видимостью.
login()— сам метод.
#[SomeAttribute]— метаданные, прикреплённые к методу.
И снова: это разные концепции.
12. Три вещи, которые стоит запомнить
Читая код на PHP/Laravel, мысленно разделяйте следующее:
Свойство (Property)
protected $fillable;Свойство хранит данные, принадлежащие объекту.
Область видимости (Visibility)
public
protected
privateОбласть видимости определяет, кто имеет доступ к свойству или методу.
Атрибут (Attribute)
#[Fillable(...)]Атрибут предоставляет метаданные/инструкции, которые могут считывать PHP или фреймворк.
13. Финальный пример
Собрём всё вместе:
#[Fillable(['name', 'email', 'password'])]
#[Hidden(['password', 'remember_token'])]
class User extends Authenticatable
{
protected string $email;
private string $password;
public function login()
{
// Login logic
}
}Теперь определим каждую часть:
#[Fillable(...)]
↓
Attribute
#[Hidden(...)]
↓
Attribute
protected string $email
│ │ │
│ │ └── Property
│ └────────── Type
└──────────────────── Visibility
private string $password
│ │ │
│ │ └── Property
│ └────────── Type
└────────────────── Visibility
public function login()
│ │
│ └── Method
└───────── VisibilityКак только вы поймёте это различие, новый синтаксис Laravel станет гораздо понятнее.
Золотое правило
Каждый раз, когда вы видите:
public
protected
privateдумайте:
Кому разрешён доступ к этому?
Каждый раз, когда вы видите:
$somethingвнутри класса, думайте:
Скорее всего, это свойство.
Каждый раз, когда вы видите:
#[Something(...)]думайте:
Это атрибут — метаданные/инструкции, прикреплённые к PHP-коду.
Эти три концепции связаны, но они не взаимозаменяемы.
Понимание этого различия — одна из тех баз PHP, которая значительно облегчает чтение современного кода на Laravel.
Комментарии (0)
Пока нет комментариев — будьте первым.