Зарегистрируйтесь для доступа к 15+ бесплатным курсам по программированию с тренажером

Массовое присвоение PHP: Eloquent (ORM)

В предыдущем уроке мы устанавливали свойства модели через сеттеры:

<?php

$user = new App\Models\User();
$user->email = 'user@email.com';
$user->first_name = 'Pedro';

Но это не единственный способ установки свойств. Как правило, в веб-разработке модели создаются после заполнения формы пользователем сайта. Данные этой формы приходят на сервер в виде ассоциативного массива. Eloquent, как и большинство ORM, позволяет сразу передать этот массив в конструктор, вместо индивидуальной установки каждого свойства. Такой подход называется "массовым присвоением" (mass-assignment):

<?php

// Обычно это данные пришедшие из формы
$params = ['email' => 'user@email.com', 'first_name' => 'Pedro'];
$user = new App\Models\User($params);
$user->save();

Но если выполнить такой подход в лоб, то он завершится с ошибкой: Add [email] to fillable property to allow mass assignment on [App/Models/User]. Чтобы понять почему так происходит, надо немного поговорить о безопасности.

Формы никогда не содержат всех полей. В каждой модели обязательно есть, по крайней мере, одно поле (id), которое нельзя давать менять. Обычно их больше, например различные поля, определяющие состояние, количество денег, какие-то внутренние характеристики, которые можно менять только изнутри системы.

Но достаточно ли просто не указывать их в форме? Будет ли это безопасно? Не будет. Веб — это HTTP, а значит любой человек, всегда может послать форму в нужный обработчик добавив туда всё, что угодно. Это автоматически означает, что передача данных пачкой в конструктор может привести к очень нежелательным эффектам. Например, к изменению уровня доступа в систему:

<?php

// Предположим, что в базе есть поле admin,
// установив которое, можно получить доступ к административной части приложения.
$params = ['email' => 'user@email.com', 'first_name' => 'Pedro', 'admin' => true];
$user = new App\Models\User($params);
$user->save();

Во избежание подобных ситуаций, Eloquent контролирует то, что принимается на вход при массовом присвоении. Делается это с помощью свойства $fillable внутри модели:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    // Белый список. Здесь описываются допустимые поля.
    protected $fillable = ['email', 'first_name', 'last_name'];
}

Теперь указанные поля могут использоваться в конструкторе:

<?php

$params = ['email' => 'user@email.com', 'first_name' => 'Pedro', 'last_name' => 'Alexandro'];
$user = new App\Models\User($params);
$user->save(); // Все пройдёт успешно

Массовое присвоение немного отличается если мы говорим про обновление сущности. Конструктор использовать не получится, сущность уже создана. Для массового обновления полей создан метод fill:

<?php

$user = App\Models\User::find($id);
// Только обновление, без сохранения
// Этот метод так же ориентируется на свойство $fillable
$user->fill(['first_name' => 'Mike', 'email' => 'lala@email.com']);
$user->save();

Откровенно говоря, контроль входных данных это не уровень моделей. Об этом должен заботиться тот слой, который использует модели. Но жизнь сложная штука. Подобные решения принимаются разработчиками фреймворков для упрощения работы. Иначе повышается порог входа. С другой стороны, подобные вещи выходят боком для опытных разработчиков. Что если нам нужно иметь разные наборы полей для разных форм? Eloquent ничего не сможет сделать, потому что набор полей зашивается жёстко внутри модели


Самостоятельная работа

  1. Заполните $fillable у User если оно не заполнено.
  2. Создайте пользователя используя mass-assignment.
  3. Обновите любого пользователя используя mass-assignment.

Дополнительные материалы

  1. Mass Assigment

Аватары экспертов Хекслета

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты.

Ошибки, сложный материал, вопросы >
Нашли опечатку или неточность?

Выделите текст, нажмите ctrl + enter и отправьте его нам. В течение нескольких дней мы исправим ошибку или улучшим формулировку.

Что-то не получается или материал кажется сложным?

Загляните в раздел «Обсуждение»:

  • задайте вопрос. Вы быстрее справитесь с трудностями и прокачаете навык постановки правильных вопросов, что пригодится и в учёбе, и в работе программистом;
  • расскажите о своих впечатлениях. Если курс слишком сложный, подробный отзыв поможет нам сделать его лучше;
  • изучите вопросы других учеников и ответы на них. Это база знаний, которой можно и нужно пользоваться.

Об обучении на Хекслете

Для полного доступа к курсу нужен базовый план

Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
900
упражнений
2000+
часов теории
3200
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно.

  • 130 курсов, 2000+ часов теории
  • 900 практических заданий в браузере
  • 360 000 студентов
Даю согласие на обработку персональных данных, соглашаюсь с «Политикой конфиденциальности» и «Условиями оказания услуг»

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff
Рекомендуемые программы

С нуля до разработчика. Возвращаем деньги, если не удалось найти работу.

Иконка программы PHP-разработчик
Профессия
Разработка веб-приложений на Laravel
25 мая 10 месяцев

Используйте Хекслет по максимуму!

  • Задавайте вопросы по уроку
  • Проверяйте знания в квизах
  • Проходите практику прямо в браузере
  • Отслеживайте свой прогресс

Зарегистрируйтесь или войдите в свой аккаунт

Даю согласие на обработку персональных данных, соглашаюсь с «Политикой конфиденциальности» и «Условиями оказания услуг»