web-dev-qa-db-fra.com

Eloquent ORM Code Hinting dans PhpStorm

Je commence donc avec Laravel (avec v5) et Eloquent. Je travaille sur la mise en place d'API de base et je constate que beaucoup de méthodes de travail n'apparaissent pas dans l'indication de code de PhpStorm.

J'ai donc ce modèle:

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 {
}

Et dans un de mes contrôleurs j'essaie de faire

User::query()->orderBy('id', 'desc');

User::query() crée un objet Eloquent Builder et orderBy() se comportent correctement et sans erreur. Cependant, PhpStorm n'affiche pas orderBy() (ou take(), skip() et je suis sûr que d'autres) lorsque je tape User::query()-> et donne des avertissements lorsque je l'utilise réellement.

J'utilise Laravel IDE Helper qui a énormément aidé à apporter des conseils de code aux façades, mais pas aux modèles/constructeurs, semble-t-il.

Est-ce que quelqu'un a une solution à cela?

16
Josh Janusch

Pour les futurs Googlers, et peut-être aussi OP si vous restez fidèle à Laravel.

Le paquet laravel-ide-helper résout ce problème pour vous de manière assez élégante, avec ce que je pense être une fonctionnalité relativement nouvelle; modèle généré PHPDocs.

Vous pouvez générer un fichier séparé pour tous les PHPDocs avec cette commande:

php artisan ide-helper:models

Les métadonnées générées ressemblent à ceci pour chaque classe:

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 {}
}

Cependant, cela me posait problème dans PHPStorm, où le logiciel se plaignait de plusieurs définitions de classe. Heureusement, une option est disponible pour écrire directement dans les fichiers de modèle:

php artisan ide-helper:models -W

Il existe encore quelques options et paramètres disponibles si vous devez modifier le comportement, mais c’est l’essentiel.

47
Erik Johansson

Un peu tard, mais j'ai eu récemment le même problème, alors j'ai pensé mettre une note:

En effet, Database\Eloquent\Model.php a une fonction query() qui renvoie \Illuminate\Database\Eloquent\Builder et le Eloquent\Builder a une ligne:

use Illuminate\Database\Query\Builder as QueryBuilder;

Ensuite, il utilise des méthodes 'magiques' __call pour appeler des fonctions dans Query\Builder. (cherchez la méthode __call dans Eloquent\Builder)

Voir: http://php.net/manual/fr/language.oop5.overloading.php#object.call

__call () est déclenché lors de l'appel de méthodes inaccessibles dans un contexte d'objet.

La méthode que vous appelez est donc inaccessible :) Il n'y a pas grand chose que le IDE puisse faire.

Il existe des solutions de contournement telles que l’utilisation de balises @method, mais cela n’est pas maintenable. Une alternative consiste à utiliser @mixin (mais ce n'est pas basé sur des normes) ... Voir: https://github.com/laravel/framework/issues/7558

Je pense que tout cela sera résolu quand ils se débarrasseront de tous les appels magiques dans le code Laravel et utiliseront PHP 'traits' à la place. Voir le dernier message ici. :)

3
Evren Yurtesen

Ajouter dans le modèle PHPDoc@mixin

/**
 * Class News
 * @property int $id
 * @property string $created_at
 * @property string $updated_at
 * @mixin \Eloquent
 * @package App
 */
class News extends Model
{

}

Dans PHPStorm works

Ou ajouter à \Illuminate\Database\Eloquent\Model

PHPDoc

/**
  * @mixin \Eloquent
  */
abstract class Model implements ArrayAccess, Arrayable, Jsonable, JsonSerializable, QueueableEntity, UrlRoutable
...
3

Vous pouvez essayer Laravel plug-in pour PhpStorm et vous devez l'activer spécifiquement dans les paramètres de votre projet.

3
motto

Je voulais avoir une sorte de "casting" explicite lors de l'interaction avec le constructeur de requêtes. Exemple...

$user = User::query()->findOrFail($id);
$user->myUserSpecialMethod(); // <-- IDE syntax error

Puisque tous mes modèles étendent ma base personnalisée Modèle qui à son tour étend Eloquent, j'ai fini par créer cette méthode dans mon modèle de base personnalisé:

/**
 * Explicit type-hinting
 *
 * @return static
 */
static public function hint(BaseModel $model)
{
    return $model;
}

De cette façon, il résout l'erreur non valide IDE et m'aide à:

$user = User::hint(User::query()->findOrFail($id));
$user->myUserSpecialMethod(); // <-- all OK !

Veuillez noter qu'il ne s'agit pas d'un transtypage de type OOP. Ce n'est qu'un indice pour aider l'IDE. Dans mon exemple, la Model renvoyée était déjà une User. Si je souhaite utiliser cette méthode sur une classe dérivée telle que SuperUser, seul le IDE sera trompé ...

Une alternative intéressante est également de mettre des méta-informations directement sur la déclaration de mission:

/** @var User $user */
$user = User::query()->findOrFail($id);
$user->myUserSpecialMethod(); // <-- all OK !

Ou à côté ...

$user = User::query()->findOrFail($id); /** @var User $user */
$user->myUserSpecialMethod(); // <-- all OK !
0
Isometriq