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
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.
You can try Laravel plug-in for PhpStorm and you need to specifically activate it in your project settings.
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 !
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. :)
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
Or add to \Illuminate\Database\Eloquent\Model
PHPDoc
/**
* @mixin \Eloquent
*/
abstract class Model implements ArrayAccess, Arrayable, Jsonable, JsonSerializable, QueueableEntity, UrlRoutable
...
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.