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

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

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

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

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

Модель

Модель в MVC v2 – это слой приложения, отвечающий за связь с предметной областью. В нём находится вся бизнес-логика приложения. Для простоты реализации, сюда часто включают механизмы для работы с базой данных.

Очень важно понимать, что модель, как слой, существует независимо от фреймворка, HTTP и веба в целом. Вся остальная система может обращаться к моделям, но модели не могут знать и не знают ничего про среду в которой они выполняются.

В том числе это значит, что мы можем работать с моделями вне фреймворка. В этом нам поможет Tinker. Одна из самых полезных возможностей Tinker – загрузить приложение и "поиграться" с моделями, поисследовать базу данных.

Текущая версия Tinker не умеет подтягивать изменения файлов в репл. Поэтому если вы что-то меняете в коде, с которым работаете в репле, придётся его перезапускать.

Выполним полный пример, создадим новую статью, наполним её данными и сохраним в базе:

php artisan tinker
Psy Shell v0.10.0 (PHP 7.3.11 — cli) by Justin Hileman
#
>>> $a = new App\Models\Article()
=> App\Models\Article {#2970}
# После того как объект модели создан, его можно наполнять данными через обычные свойства (на самом деле внутри используется `__set` и `__get`). Имена этих свойств, соответствуют именам в таблице.
>>> $a->name = 'my super article'
=> "my super article"
>>> $a->body = 'my content'
=> "my content"
>>> $a
=> App\Models\Article {#2970
     name: "my super article",
     body: "my content",
   }

Когда объект готов, его можно сохранить в базу данных. Для этого надо вызвать метод save():

>>> $a->save()
=> true
>>> $a
=> App\Models\Article {#2970
     name: "my super article",
     body: "my content",
     updated_at: "2020-03-21 19:17:08",
     created_at: "2020-03-21 19:17:08",
     id: 1,
   }

Этот метод делает запрос INSERT в базу данных. Затем он обновляет сам объект:

  • Внутрь записывается идентификатор статьи взятый из базы данных.
  • Заполняются поля created_at и updated_at. Если это новая запись, то значения этих полей совпадают.

Созданный объект можно тут же поменять:

>>> $a->name = 'another title'
=> "another title"
>>> $a
=> App\Models\Article {#2972
     id: "1",
     name: "another title",
     body: "my content",
     created_at: "2020-03-21 19:17:08",
     updated_at: "2020-03-21 19:17:08",
   }

Изменение свойств никак не затрагивает базу данных. Все это происходит только на уровне самого объекта. Если в этот момент закрыть консоль, то все изменения потеряются. Для сохранения нужно опять вызвать save(). Этот метод универсальный, он подходит как для создания новой сущности, так и для её обновления.

>>> $a->save()
=> true
>>> $a
=> App\Models\Article {#2972
     id: "1",
     name: "another title",
     body: "my content",
     created_at: "2020-03-21 19:17:08",
     updated_at: "2020-03-21 19:31:56",
   }

Метод save() выполняет запрос в базу только тогда, когда что-то поменялось. В этом случае обязательно меняется значение поля updated_at. Оно становится равным текущему времени.

Теперь предположим, что у нас нет переменной с текущей статьёй. Например, мы перезапустили консоль. Каким образом получить нужный объект? Делается это с помощью статических методов, которые появляются у каждой модели. Самый простой способ достать запись, сделать поиск по её идентификатору:

>>> $a = App\Models\Article::find(1)
=> App\Models\Article {#2980
     id: "1",
     name: "another title",
     body: "my content",
     created_at: "2020-03-21 19:17:08",
     updated_at: "2020-03-21 19:31:56",
   }

find ищет по первичному ключу и возвращает запись или null. Если ему передать массив ключей, то он вернет коллекцию, состоящую из записей по этим ключам. А если нужен поиск по полям, который вернёт коллекцию, для этого подходит метод where:

# У этого метода много интересных возможностей. Подробнее о них говорится в соответствующем курсе.
# Такой запрос извлечёт все статьи, у которых имя равно _another title_.
>>> $articles = App\Models\Article::where('name', 'another title')->get()
=> Illuminate\Database\Eloquent\Collection {#2973
     all: [
       App\Article {#2967
         id: "1",
         name: "another title",
         body: "my content",
         created_at: "2020-03-21 19:17:08",
         updated_at: "2020-03-21 19:31:56",
       },
     ],
   }

Кроме where, нам понадобятся два похожих метода:

  • Model::all() извлекает все записи из таблицы. Такой метод подходит только в некоторых ситуациях, в основном при работе со справочниками где немного данных. В остальных случаях он может выбрать в память слишком много записей, что породит ненужную нагрузку на сервер.
  • Model::paginate($page) – извлекает записи постранично. Основной метод, который используется в списках.

И последнее, что можно сделать с сущностью, это удалить её:

>>> $a->delete()
=> true
>>> Article::find(1)
=> null

Состав модели

В реальных проектах от десятков до тысяч (или десятков тысяч!) сущностей. При таких количествах, помнить из чего состоят модели – невозможно. Более того, в проект могут и будут приходить новые люди, которые не знают структуры моделей.

Узнать какие поля есть у модели можно несколькими способами. Ими придётся пользоваться регулярно:

  1. База данных. Всегда можно подключиться напрямую и посмотреть структуру таблицы. В разных базах данных это делается по разному.

  2. Laravel имеет встроенный механизм извлечения структуры таблицы. Он сам им пользуется для работы модели.

    <?php
    
    DB::getSchemaBuilder()->getColumnListing('имя таблицы');
    
  3. Пожалуй самый простой и распространённый способ — зайти в REPL, извлечь первую сущность нужной модели и распечатать её.

    >>> $u = \App\Models\User::first()
    >>> $u->toArray()
    
    string(29) "select * from "users" limit 1"
    => [
         "id" => 1,
         "email" => "streich.viva@example.net",
         "first_name" => "Tatum",
         "last_name" => "Hudson",
         "password" => "$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi",
         "created_at" => "2020-03-21 19:31:38",
         "updated_at" => "2020-03-21 19:31:38",
       ]
    

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

  1. Создайте 5 статей через репл. Они понадобятся при построении CRUD.

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

  1. Что такое протокол HTTPS, и как он защищает вас в интернете
  2. Как работает DNS
  3. Что такое веб-сервер?

<span class="translation_missing" title="translation missing: ru.web.courses.lessons.mentors.mentor_avatars">Mentor Avatars</span>

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

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

Для полного доступа к курсу нужна профессиональная подписка

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

Получить доступ
115
курсов
892
упражнения
2241
час теории
3196
тестов

Зарегистрироваться

или войти в аккаунт

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

  • 115 курсов, 2000+ часов теории
  • 800 практических заданий в браузере
  • 250 000 студентов

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

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

Логотип компании Альфа Банк
Логотип компании Rambler
Логотип компании Bookmate
Логотип компании Botmother

Есть вопрос или хотите участвовать в обсуждении?

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

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