(Я исхожу из фона Visual Studio + Entity Framework и пытаюсь найти эквивалентную функциональность в Laravel + Eloquent)
В EF и Visual Studio мы добавляем новую модель в наше приложение и просто сообщаем ей о нашей существующей базе данных. Затем EF может создавать модели для моих таблиц с общедоступными свойствами столбцов. Это дает нам все преимущества IDE и компилятора, такие как Intellisense, обнаружение орфографических ошибок и т. д.
Недавно я заявил об изучении VS Code, Laravel и Eloquent. Просматривая все эти руководства и статьи, я не уверен, когда и как эти свойства генерируются в классах модели. Я просто попробовал команду artisan make:model, и она сгенерировала класс модели, но в нем нет свойств. Так,
Людям, ответившим на мой вопрос, большое спасибо. Кроме того, некоторые из опубликованных мной комментариев были связаны с моим незнанием подхода PHP (странный IMO) к доступу членов; Я только что узнал, что PHP не жалуется на несуществующие члены класса, а вместо этого генерирует их на лету (например, $post->NonExistingMember = SomeValue работает нормально; это даже не компилируется на большинстве других языков, которые я знаю). Для меня большой сюрприз. Я использовал C++, VB, C#, Java среди нескольких других языков и нигде не встречал такого поведения. Все эти языки сразу же выдают ошибку времени компиляции, говоря, что что-то вроде типа X не содержит члена с именем Y. Невозможно увидеть, как другой подход PHP сочетается с ООП.
Фактическая проблема, для которой я разместил этот вопрос, все еще остается нерешенной. Хотя я могу использовать Reliese / Laravel для генерации классов модели для моей базы данных, инструмент по-прежнему не генерирует члены классов для столбцов таблицы, поэтому я не получаю преимуществ автозаполнения. Я бы хотел услышать мнение экспертов, если это можно сделать (конечно, автоматически).
Теперь, когда я немного лучше понимаю среду Laravel, я решил поделиться своим опытом. Смотрите мой ответ ниже.
Может это поможет: Laravel: красноречивое начало работы. Но в основном да, вы пишете их от руки. Доступны пакеты, которые могут создавать модели из существующей базы данных.
@RafaelBoszko: Это попадает в самую точку (то есть в голову гвоздя :)). Спасибо.
Вы когда-нибудь решали эту проблему, чтобы получать преимущества автозаполнения? Я тоже родом из C# и привык к тому, что вещи немного более явные, а не «автоматические».
@LouiseEggleton: Я больше времени работал с Laravel. Основная проблема (или назовите это функцией) заключается в том, что класс не обязательно должен содержать член во время компиляции, потому что, так сказать, нет время компиляции. PHP интерпретирует код во время выполнения и на лету генерирует элементы. Таким образом, класс модели вообще не требует, чтобы у вас были какие-либо члены. Это очень не похоже на мир C#, где у нас есть строго типизированные модели (Entity или даже DataSets) с соответствием 1-1 между свойствами класса и базовыми столбцами таблицы. Все это означает, что в VS Code не будет типа автозаполнения для Laravel.
@LouiseEggleton: есть приятный маленький инструмент, который может создавать классы моделей из вашей базы данных (см. Комментарий Рафаэля выше), но даже этот инструмент генерирует DocBlocks (комментарии), а не фактические члены класса. Вы можете написать их от руки, если хотите, но поработав с ним какое-то время, я бы сказал, что в этом нет необходимости.
Спасибо @dotNet. Поскольку мне нравятся сильно типизированные модели, я могу писать их вручную. Мне нравится защитное кодирование. У меня обычно нет методов установки в C#, потому что я заставляю многие мои классы создавать экземпляры только через конструктор. например {получить; } нет. Поэтому я, вероятно, собираюсь сделать что-нибудь в PHP, например, создать общедоступные свойства и установить их через конструктор.
@LouiseEggleton: Вы упустили суть. В PHP нет защиты AFAIK от того, что вы пытаетесь предотвратить. Если вы наберете obj.Nmae = "Louise"; вместо obj.Name = "Louise";, PHP с радостью примет его и добавит нового члена Nmae в obj, независимо от того, являетесь ли вы установщиком или нет. (но прислушайтесь к моему совету с недоверием, потому что мой опыт работы с C# насчитывает около двух десятилетий, а опыт Laravel - менее года).
Но разве явные свойства не помогут по крайней мере с intellisense, а также не покажут намерение?
В JavaScript также отсутствует безопасность типов, но я по-прежнему ценю такие вещи, как intellisense, автозаполнение и линтеры, которые помогают восполнить их отсутствие.
@LouiseEggleton: Intellisense - это функция IDE, а не язык. Если есть lex. анализатор, который анализирует код PHP и предоставляет информацию о членах, это как раз то, что вам нужно для работы Intellisense. Есть несколько плагины, которые должны делать именно это, но мне было трудно заставить их работать с моими моделями. Они просто показывают все в раскрывающемся списке Intellisense вместо тех, которые продиктованы контекстом. LMK, если вы заставите их работать как C#.






Например, модель под названием 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',
];
Также вы можете добавить новые свойства в модель, используя Аксессоры
Спасибо. Можете ли вы включить в ответ определение своего класса модели?
Проверьте мой обновленный ответ, я надеюсь, что это то, о чем вы просили. Если вам нужно что-то еще, я могу обновить свой ответ.
Теперь вы близки к тому, о чем я прошу. Что такое $newPost->title в приведенном выше коде? В вашем классе нет такого свойства или общедоступной переменной. Даже если бы они были, как бы эта переменная отображалась в столбце базовой таблицы?
Заголовок - это столбец «заголовок» из вашей БД. Если вам нужно создать сообщение и добавить значение «заголовок», вам нужно добавить заголовок в массив «$ fillable».
По умолчанию, вероятно, у вас также есть «id», «created_at» и «updated_at», созданные Laravel, но в этом массиве вам нужно объявить только те свойства, которые вам нужно изменить.
Я очень запутался. Вы не объявили какое-либо свойство или переменную с именем title в классе Post. Зачем ему что-то возвращать для $this->title. Зачем это вообще компилируется? PHP должен сразу выдавать ошибку времени компиляции, говоря, что title не является членом класса Post.
Простите мое незнание. Я только что узнал, что PHP не жалуется на несуществующие члены класса, а вместо этого генерирует их на лету. Для меня большой сюрприз. Я использовал C++, VB, C#, Java среди нескольких других языков и нигде не встречал такого поведения. Все эти языки сразу же выдают ошибку времени компиляции, говоря, что что-то вроде типа X не содержит члена с именем Y. Невозможно увидеть, как другой подход PHP сочетается с ООП.
@dotNET Имейте в виду, что именно так это делает Laravel, используя «волшебные» методы PHP. Вы можете выполнять обычное ООП в PHP!
На самом деле вам не нужно указывать свойства. Все это делается 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.
Простите мое незнание. Я только что узнал, что PHP не жалуется на несуществующие члены класса, а вместо этого генерирует их на лету. Для меня большой сюрприз. Я использовал C++, VB, C#, Java среди нескольких других языков и нигде не встречал такого поведения. Все эти языки сразу выдают ошибку времени компиляции, говоря что-то вроде Type X does not contain a member named Y. Не вижу, как другой подход PHP сочетается с ООП.
Вам нужно добавить самостоятельно. Например
$fillable = ['firstname', 'email','username'];
$guarded = ['price'];
Я ищу добавление общедоступных свойств к своим столбцам, чтобы получить преимущества времени кода, такие как автозаполнение, обнаружение орфографической ошибки и т. д.
Я использую аннотации для объявления всех свойств автозаполнения (работает в 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.
Может быть, это может вам помочь: stackoverflow.com/questions/30560485/…