Модели Laravel: где находятся свойства модели?

(Я исхожу из фона Visual Studio + Entity Framework и пытаюсь найти эквивалентную функциональность в Laravel + Eloquent)

В EF и Visual Studio мы добавляем новую модель в наше приложение и просто сообщаем ей о нашей существующей базе данных. Затем EF может создавать модели для моих таблиц с общедоступными свойствами столбцов. Это дает нам все преимущества IDE и компилятора, такие как Intellisense, обнаружение орфографических ошибок и т. д.

Недавно я заявил об изучении VS Code, Laravel и Eloquent. Просматривая все эти руководства и статьи, я не уверен, когда и как эти свойства генерируются в классах модели. Я просто попробовал команду artisan make:model, и она сгенерировала класс модели, но в нем нет свойств. Так,

  1. Должен ли я писать их от руки? (В самом деле?)
  2. Это будут только общедоступные переменные или стандартные свойства с геттером / сеттером (извините за мой менталитет .NET :))?
  3. Есть ли инструмент / расширение, которое могло бы исследовать мою базу данных и создавать модели со свойствами для их столбцов?

Обновлять

Людям, ответившим на мой вопрос, большое спасибо. Кроме того, некоторые из опубликованных мной комментариев были связаны с моим незнанием подхода PHP (странный IMO) к доступу членов; Я только что узнал, что PHP не жалуется на несуществующие члены класса, а вместо этого генерирует их на лету (например, $post->NonExistingMember = SomeValue работает нормально; это даже не компилируется на большинстве других языков, которые я знаю). Для меня большой сюрприз. Я использовал C++, VB, C#, Java среди нескольких других языков и нигде не встречал такого поведения. Все эти языки сразу же выдают ошибку времени компиляции, говоря, что что-то вроде типа X не содержит члена с именем Y. Невозможно увидеть, как другой подход PHP сочетается с ООП.

Фактическая проблема, для которой я разместил этот вопрос, все еще остается нерешенной. Хотя я могу использовать Reliese / Laravel для генерации классов модели для моей базы данных, инструмент по-прежнему не генерирует члены классов для столбцов таблицы, поэтому я не получаю преимуществ автозаполнения. Я бы хотел услышать мнение экспертов, если это можно сделать (конечно, автоматически).

Обновление 2

Теперь, когда я немного лучше понимаю среду Laravel, я решил поделиться своим опытом. Смотрите мой ответ ниже.

Может быть, это может вам помочь: stackoverflow.com/questions/30560485/…

Rafael 08.08.2018 13:33

Может это поможет: Laravel: красноречивое начало работы. Но в основном да, вы пишете их от руки. Доступны пакеты, которые могут создавать модели из существующей базы данных.

brombeer 08.08.2018 13:38

@RafaelBoszko: Это попадает в самую точку (то есть в голову гвоздя :)). Спасибо.

dotNET 08.08.2018 13:43

Вы когда-нибудь решали эту проблему, чтобы получать преимущества автозаполнения? Я тоже родом из C# и привык к тому, что вещи немного более явные, а не «автоматические».

Louise Eggleton 15.11.2019 13:49

@LouiseEggleton: Я больше времени работал с Laravel. Основная проблема (или назовите это функцией) заключается в том, что класс не обязательно должен содержать член во время компиляции, потому что, так сказать, нет время компиляции. PHP интерпретирует код во время выполнения и на лету генерирует элементы. Таким образом, класс модели вообще не требует, чтобы у вас были какие-либо члены. Это очень не похоже на мир C#, где у нас есть строго типизированные модели (Entity или даже DataSets) с соответствием 1-1 между свойствами класса и базовыми столбцами таблицы. Все это означает, что в VS Code не будет типа автозаполнения для Laravel.

dotNET 15.11.2019 18:24

@LouiseEggleton: есть приятный маленький инструмент, который может создавать классы моделей из вашей базы данных (см. Комментарий Рафаэля выше), но даже этот инструмент генерирует DocBlocks (комментарии), а не фактические члены класса. Вы можете написать их от руки, если хотите, но поработав с ним какое-то время, я бы сказал, что в этом нет необходимости.

dotNET 15.11.2019 18:28

Спасибо @dotNet. Поскольку мне нравятся сильно типизированные модели, я могу писать их вручную. Мне нравится защитное кодирование. У меня обычно нет методов установки в C#, потому что я заставляю многие мои классы создавать экземпляры только через конструктор. например {получить; } нет. Поэтому я, вероятно, собираюсь сделать что-нибудь в PHP, например, создать общедоступные свойства и установить их через конструктор.

Louise Eggleton 15.11.2019 18:35

@LouiseEggleton: Вы упустили суть. В PHP нет защиты AFAIK от того, что вы пытаетесь предотвратить. Если вы наберете obj.Nmae = "Louise"; вместо obj.Name = "Louise";, PHP с радостью примет его и добавит нового члена Nmae в obj, независимо от того, являетесь ли вы установщиком или нет. (но прислушайтесь к моему совету с недоверием, потому что мой опыт работы с C# насчитывает около двух десятилетий, а опыт Laravel - менее года).

dotNET 15.11.2019 18:47

Но разве явные свойства не помогут по крайней мере с intellisense, а также не покажут намерение?

Louise Eggleton 15.11.2019 18:54

В JavaScript также отсутствует безопасность типов, но я по-прежнему ценю такие вещи, как intellisense, автозаполнение и линтеры, которые помогают восполнить их отсутствие.

Louise Eggleton 15.11.2019 19:08

@LouiseEggleton: Intellisense - это функция IDE, а не язык. Если есть lex. анализатор, который анализирует код PHP и предоставляет информацию о членах, это как раз то, что вам нужно для работы Intellisense. Есть несколько плагины, которые должны делать именно это, но мне было трудно заставить их работать с моими моделями. Они просто показывают все в раскрывающемся списке Intellisense вместо тех, которые продиктованы контекстом. LMK, если вы заставите их работать как C#.

dotNET 16.11.2019 06:37
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
14
11
7 532
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

  1. К сожалению, да, вам нужно написать их вручную, но только если вам нужно обновить значение этих свойств, контрольная точка 2 (массив $ fillable)
  2. Вам нужно объявить свойства, которые можно заполнить:

Например, модель под названием Post для таблицы базы данных «posts», которая имеет 2 столбца «title» и «body»:  

namespace App;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{

 //not mandatory to declare the table name, Laravel will find it using reflection if you follow the naming standard
 protected $table = 'posts'; //not mandatory

 protected $fillable = ['title','body'];
}

В контроллере:

$newPost = new Post;
$newPost->title = 'A new title';
$newPost->body = 'A new body';
$newPost->save(); //only at this point the db is modified

Или вы можете скрыть их, если вы вернете свойства в массиве или в ответе JSON (в Коллекции также будут отображаться скрытые):

protected $hidden = [
 'title',
];

Также вы можете добавить новые свойства в модель, используя Аксессоры

  1. Я так не думаю, вы можете установить некоторые плагины Laravel VS Code, чтобы облегчить себе жизнь (например, фрагменты Blade) Вы можете проверить эта статья.

Спасибо. Можете ли вы включить в ответ определение своего класса модели?

dotNET 08.08.2018 14:07

Проверьте мой обновленный ответ, я надеюсь, что это то, о чем вы просили. Если вам нужно что-то еще, я могу обновить свой ответ.

NicuVlad 08.08.2018 14:16

Теперь вы близки к тому, о чем я прошу. Что такое $newPost->title в приведенном выше коде? В вашем классе нет такого свойства или общедоступной переменной. Даже если бы они были, как бы эта переменная отображалась в столбце базовой таблицы?

dotNET 08.08.2018 14:29

Заголовок - это столбец «заголовок» из вашей БД. Если вам нужно создать сообщение и добавить значение «заголовок», вам нужно добавить заголовок в массив «$ fillable».

NicuVlad 08.08.2018 14:33

По умолчанию, вероятно, у вас также есть «id», «created_at» и «updated_at», созданные Laravel, но в этом массиве вам нужно объявить только те свойства, которые вам нужно изменить.

NicuVlad 08.08.2018 14:36

Я очень запутался. Вы не объявили какое-либо свойство или переменную с именем title в классе Post. Зачем ему что-то возвращать для $this->title. Зачем это вообще компилируется? PHP должен сразу выдавать ошибку времени компиляции, говоря, что title не является членом класса Post.

dotNET 08.08.2018 19:44

Простите мое незнание. Я только что узнал, что PHP не жалуется на несуществующие члены класса, а вместо этого генерирует их на лету. Для меня большой сюрприз. Я использовал C++, VB, C#, Java среди нескольких других языков и нигде не встречал такого поведения. Все эти языки сразу же выдают ошибку времени компиляции, говоря, что что-то вроде типа X не содержит члена с именем Y. Невозможно увидеть, как другой подход PHP сочетается с ООП.

dotNET 08.08.2018 20:23

@dotNET Имейте в виду, что именно так это делает Laravel, используя «волшебные» методы PHP. Вы можете выполнять обычное ООП в PHP!

Charles Wood 05.08.2020 01:41

На самом деле вам не нужно указывать свойства. Все это делается laravel автоматически. Когда вы создаете модель, laravel использует множественное число (и у него действительно хорошая система для этого: сообщение становится сообщениями, активность становится действиями и т. д.) Имени класса для доступа к таблице. Таким образом, вы можете работать с пустой моделью без установки свойства $ table или $ fillable / $ guarded.

// use only, if your table name differs from the models classname
$table = 'users_options'; // when you want to name your model 'Vote' but the table is called 'users_options' for instance.

// use fillable and guarded only to specify mass-assignment columns
$fillable = [whatever, ...];
$guarded = [whatever, ...];

вы можете получить доступ к свойствам, когда захотите:

class Post extends Model
{

}

// would do sth like this: select name from posts where id = 1;
// without specifying anything in the model
$name = Post::find(1)->name;

Я очень запутался. Вы не объявили какое-либо свойство или переменную с именем name в классе Post. Зачем ему что-то возвращать для Post::find(1)->name. Зачем это вообще компилируется? PHP должен сразу выдавать ошибку времени компиляции, говоря, что name не является членом класса Post.

dotNET 08.08.2018 19:46

Простите мое незнание. Я только что узнал, что PHP не жалуется на несуществующие члены класса, а вместо этого генерирует их на лету. Для меня большой сюрприз. Я использовал C++, VB, C#, Java среди нескольких других языков и нигде не встречал такого поведения. Все эти языки сразу выдают ошибку времени компиляции, говоря что-то вроде Type X does not contain a member named Y. Не вижу, как другой подход PHP сочетается с ООП.

dotNET 08.08.2018 20:21

Вам нужно добавить самостоятельно. Например

$fillable = ['firstname', 'email','username'];
$guarded = ['price'];

Я ищу добавление общедоступных свойств к своим столбцам, чтобы получить преимущества времени кода, такие как автозаполнение, обнаружение орфографической ошибки и т. д.

dotNET 08.08.2018 19:48

Я использую аннотации для объявления всех свойств автозаполнения (работает в PHPStorm, не уверен в других IDE).

/**
 * @property $id
 * @property $microsoft_id
 * @property $name
 * @property $qualification
 * @property $company
 */
class ShopTenant extends Model
{
    public $connection = 'shop';
    public $table = 'tenants';
    protected $guarded = ['id'];
}

Вы можете использовать что-то вроде этого, чтобы получить список всех столбцов таблицы, а затем вставить / отформатировать этот список в свои аннотации:

SELECT *
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = N'tenants';
Ответ принят как подходящий

Теперь, когда я провел некоторое время с Laravel, Eloquent и PHP в целом, я поделюсь несколькими вещами в надежде, что они помогут другим начинающим.

PHP - это динамический язык, и его код компилируется на лету (в отличие от C# и VB.NET). Классам вашей модели не нужно явно определять члены, чтобы они были доступны / назначались, поэтому, пока они расширяют Model (встроенный класс в Laravel Eloquent), вы можете назначать значения несуществующим членам, которые имеют то же имя, что и столбец базовой таблицы базы данных, и Eloquent сохранит его в базе данных для вас. Так, например, если у вас есть таблица posts в вашей базе данных, в которой есть столбец с именем body, вы можете написать следующий код для создания новой записи в вашей базе данных:

$p = new Post;
$p->body = 'Some stuff';
$p->save();

Конечно, в вашем проекте должен быть класс Post, который расширяется от Model, но вам не нужно определять член body внутри этого класса. Это может показаться странным для людей из мира .NET, но именно так работают динамические языки.

Что касается автоматического создания моделей, Laravel включает встроенные команды (php artisan make:model), которые могут генерировать их за вас.

Наконец, для intellisense и автозаполнения используйте тот же инструмент, который используется самим Laravel, то есть DocBlocks. Это особый тип комментариев в PHP, с помощью которых вы можете документировать элементы кода. Таким образом, вы можете добавить DocBlocks ко всем классам вашей модели, содержащим имена и типы свойств. К счастью для всех, в VS Code есть очень удобное расширение, которое может делать это автоматически. Установите его с помощью следующей команды:

composer require --dev barryvdh/laravel-ide-helper

Теперь выполните следующую команду, чтобы сгенерировать DocBlocks для всех классов вашей модели (очевидно, вы уже должны были сгенерировать свою базу данных и модели до этого):

php artisan ide-helper:models --dir='app'

Расширение получит структуру вашей базы данных и внедрит DocBlocks во все ваши модели, что будет выглядеть примерно так:

/**
 * App\User
 *
 * @property int $id
 * @property string $name
 * @property \Illuminate\Support\Carbon|null $created_at
 * @property \Illuminate\Support\Carbon|null $updated_at
 * @method static \Illuminate\Database\Eloquent\Builder|\App\User whereCreatedAt($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\User whereId($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\User whereName($value)
 * @method static \Illuminate\Database\Eloquent\Builder|\App\Exam whereUpdatedAt($value)
 * @mixin \Eloquent
 */
class User extends Model
{
}

VS Code теперь покажет вам имена полей таблицы в свойствах модели, как это (посмотрите, как intellisense вызывает член name из наших DocBlocks, когда мы вводим na...):

Обратите внимание, что у меня также установлен Intelephense в моем VS Code, хотя я не уверен, требуется ли это для работы функции автозаполнения.

Вам не нужно определять свойства, но вы действительно определяете свойства не должен. Их определение нарушает предположения Eloquent. Это вариант дизайна, который я не понимаю, но, что еще более досадно, он не упоминается на страницах документации Laravel.

aross 06.10.2020 17:19

Другие вопросы по теме