Reputation: 8159
So I'm just starting off with Laravel (using v5) and Eloquent. I'm working on getting some basic APIs up and running and noticing that a lot of working methods don't show up in PhpStorm's code hinting
So I have this model:
namespace Project\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
class User extends Model
implements AuthenticatableContract, CanResetPasswordContract {
}
And in one of my controllers I try to do
User::query()->orderBy('id', 'desc');
User::query()
creates a Eloquent Builder
object and orderBy()
behave properly and without error. However, PhpStorm does not show orderBy()
(or take()
, skip()
, and I'm sure others) when I type User::query()->
and gives warnings when I actually do use it.
I am using Laravel IDE Helper which has helped immensely with bringing code hints to the Facades, but not to the models/builders it would seem.
Does anyone have a solution to this?
Upvotes: 37
Views: 39915
Reputation: 334
This really helped me (laravel-ide-helper):
composer require --dev barryvdh/laravel-ide-helper -W
then :
php artisan ide-helper:eloquent
This really helps :
Using version ^2.13 for barryvdh/laravel-ide-helper
PS C:\Users\anonym\Documents\Github\laravel\elearny_app_web> php artisan ide-helper:eloquent
Unexpected no document on Illuminate\Database\Eloquent\Model
Wrote expected docblock to C:\Users\anonym\Documents\Github\laravel\elearny_app_web\vendor\laravel\framework\src\Illuminate\Database\Eloquent\Model.php
PS C:\Users\anonym\Documents\Github\laravel\elearny_app_web>
Upvotes: 0
Reputation: 467
Verified on Laravel 8, just added @mixin Builder to Illuminate\Database\Eloquent\Model.php annotation solved it.
// Illuminate\Database\Eloquent\Model.php
/**
* @mixin Builder
*/
abstract class Model
Upvotes: 0
Reputation: 377
Just import Eloquent Builder in your Model class and add mixin:
use Illuminate\Database\Eloquent\Builder;
/** @mixin Builder */
To cover all the models at once — add the mixin to the src/Illuminate/Database/Eloquent/Model.php
)
Upvotes: 8
Reputation: 358
Add in model PHPDoc@mixin
/**
* Class News
* @property int $id
* @property string $created_at
* @property string $updated_at
* @mixin \Eloquent
* @package App
*/
class News extends Model
{
}
In PHPStorm works
Upvotes: 22
Reputation: 2087
If you're using BarryVHD's Laravel IDE Helper package, run:
php artisan ide-helper:eloquent
This will write /** @mixin \Eloquent */
into the vendor\laravel\framework\src\Illuminate\Database\Eloquent\Model.php
file.
Upvotes: 7
Reputation: 381
I wanted to have some kind of explicit "casting" when interacting with the query builder. Example...
$user = User::query()->findOrFail($id);
$user->myUserSpecialMethod(); // <-- IDE syntax error
Since all my models are extending my custom base Model which in turn extends Eloquent, I've ended up creating this method in my custom base model:
/**
* Explicit type-hinting
*
* @return static
*/
static public function hint(BaseModel $model)
{
return $model;
}
This way, it solves the IDE invalid error and helps me:
$user = User::hint(User::query()->findOrFail($id));
$user->myUserSpecialMethod(); // <-- all OK !
Please note that this is not OOP type casting. It is only a hint to help the IDE. In my example, the returned Model
was already a User
. If I woud use this method on a derived class like SuperUser
, only the IDE will be fooled...
An nice alternative also is to put meta information directly over the assignment statement:
/** @var User $user */
$user = User::query()->findOrFail($id);
$user->myUserSpecialMethod(); // <-- all OK !
Or next to it...
$user = User::query()->findOrFail($id); /** @var User $user */
$user->myUserSpecialMethod(); // <-- all OK !
Upvotes: 2
Reputation: 2349
A little late but I recently had the same problem so I thought I would put a note down:
This is because Database\Eloquent\Model.php
has a query()
function which returns \Illuminate\Database\Eloquent\Builder
and the Eloquent\Builder
has a line:
use Illuminate\Database\Query\Builder as QueryBuilder;
Then it uses 'magic' __call methods to call to functions in Query\Builder
. (look for __call
method in Eloquent\Builder
)
See: http://php.net/manual/en/language.oop5.overloading.php#object.call
__call() is triggered when invoking inaccessible methods in an object context.
So, indeed the method you are calling is inaccessible :) There is not much that the IDE can do.
There are workarounds like using @method tags but it is unmaintainable. An alternative is to use @mixin (but this is not standards based). See: https://github.com/laravel/framework/issues/7558
I think this all be resolved when they get rid of all the magic calls in the Laravel code and use PHP 'traits' instead. See last message here. :)
Upvotes: 5
Reputation: 1656
For future Googlers, and perhaps OP as well if you are still sticking to Laravel.
The laravel-ide-helper package solves this issue for you quite elegantly, with what I believe is a relatively new feature; generated model PHPDocs.
You can generate a separate file for all PHPDocs with this command:
php artisan ide-helper:models
The generated metadata will look something like this for each class:
namespace App {
/**
* App\Post
*
* @property integer $id
* @property integer $author_id
* @property string $title
* @property string $text
* @property \Carbon\Carbon $created_at
* @property \Carbon\Carbon $updated_at
* @property-read \User $author
* @property-read \Illuminate\Database\Eloquent\Collection|\Comment[] $comments
*/
class Post {}
}
This caused issues for me in PHPStorm however, where the software was complaining about multiple class definitions. Luckily an option is readily available for writing directly to the model files:
php artisan ide-helper:models -W
There are a few more options and settings available if you need to tweak the behavior, but this is the gist of it.
Upvotes: 95
Reputation: 5793
You can try Laravel plug-in for PhpStorm and you need to specifically activate it in your project settings.
Upvotes: 5