2016-01-14 9 views
5

FragePHP Type Hinting Implementierung der abstrakten Methode - Repository Pattern

Ist es möglich, Zeile Code-Vervollständigung innerhalb PhpStorm mit einem Modell/Repository-Muster zu bekommen?

Mein Setup

ich Laravel verwende und das Repository-Muster zur Durchführung der in einem Laracasts Video beschrieben.

Der Kodex

Hier ist ein einfaches Beispiel, wie Modelle innerhalb Laravel arbeiten und wie es scheint unmöglich, Code-Vervollständigung zu erhalten für Modellattribute.

Dieser Code funktioniert und druckt "billy" aus, wie es sollte, jedoch ist das Attribut $ name nicht typisiert und wird in PhpStorm nicht mit Code vervollständigt. Der Typhinweis priorisiert den übergeordneten Attributdefinitionstyp und nicht das Kind, was mir seltsam vorkommt.

<?php 

// Models 
abstract class Model { 
    public $sqlTableName; 

    public function findFromDatabase($id) 
    { 
     $model = new $this; 

     // This would be grabbed using table name and $id 
     $fakeDatabaseRow = ['name' => 'billy', 'job' => 'engineer']; 

     foreach ($fakeDatabaseRow as $column => $value) { 
      $model->$column = $value; 
     } 

     return $model; 
    } 
} 

class User extends Model { 
    public $name; 
    public $job; 

    public $sqlTableName = 'users'; 
} 

// Repositories 
abstract class RepositoryBase { 
    /** 
    * @var Model 
    */ 
    public $model; 

    public function find($id) 
    { 
     $this->model = $this->model->findFromDatabase(1); 

     return $this->model; 
    } 
} 

class UserRepository extends RepositoryBase { 
    /** 
    * @var User 
    */ 
    public $model; 

    public function __construct(User $model) 
    { 
     $this->model = $model; 
    } 
} 

// Run 
$model = new User(); 

$userRepository = new UserRepository($model); 

echo $userRepository->find(1)->name; 

eine hässliche Fix

Der einzige tatsächlich Code-Vervollständigung zu bekommen scheint das Kind Funktion mit einem neuen PHP-doc Block neu zu definieren zu sein:

class UserRepository extends RepositoryBase { 
    /** 
    * @var User 
    */ 
    public $model; 

    public function __construct(User $model) 
    { 
     $this->model = $model; 
    } 

    // I need to replace this function for every different repository 
    // even though they are all the same 
    /** 
    * @param $id 
    * @return User 
    */ 
    public function find($id) 
    { 
     return parent::find($id); 
    } 
} 

Ich habe jedoch Hunderte von Modellen, Repositories und Repository-Funktionen. Es wäre eine gewaltige Aufgabe, alle Funktionen in jeder Implementierung neu zu schreiben.

Gibt es eine Möglichkeit, PhpStorm dazu zu bringen, die Typhinweisdeklaration des Kinds statt der Eltern zu verwenden, ohne die Methode erneut deklarieren zu müssen?

+0

Probieren Sie @ @ Methode in PHPDoc für die Klasse. – LazyOne

+0

@LazyOne - Das funktioniert, wenn ich '@method User find ($ id)' zum UserRepository Docblock hinzufüge. Das bedeutet aber immer noch, dass ich dies für jedes Repository und für jede Funktion, die ein Modell zurückgibt, tun müsste. – magnito

+0

'¯ \\ _ (ツ) _/¯' 1) zumindest du deklarierst es nicht neu 2) Ich kenne keinen anderen Weg 3) vielleicht kann das Laravel Support-Plugin dies tun (falls du es noch nicht installiert hast)) – LazyOne

Antwort

2

Ich konnte in dem Kontext, in dem ich diese Frage ursprünglich eingab, keine Lösung finden, um richtige Typenhinweis mit Modell und Repositories zu erhalten.


Lösung Compromised

Nach weiteren von Repository-Studium und mvc php Muster, die ich zu dem Schluss gekommen, mehr spezifische und detaillierte Repository-Funktionen zu verwenden.


The Wrong Way

Zum Beispiel habe ich in meinem Controller/Logik-Klassen wie diese Repository Basisfunktionen wurde mit:

$users = 
    $userRepository->where('created_at', '<', '2016-01-18 19:21:20')->where(
      'permission_level', 
      'admin' 
     )->orderBy('created_at')->get('id'); 

$posts = 
    $postRepository->where('posted_on', '<', '2016-01-18 19:21:20') 
     ->where('content', '!=', 'null') 
     ->chunk(
      function ($posts) { 
       // do things 
      } 
     ); 

Der richtige Weg

Jetzt

ich separate Datenbank Logikfunktionen Code für alle meine Bedürfnisse innerhalb der spezifischen Repositories, so meine Hauptklassen/Controller am Ende wie folgt aussehen:

$users = $userRepository->getAdminIdsCreatedBeforeDate('2016-01-18 19:21:20'); 
$posts = $postRepository->chunkFilledPostsBeforeDate('2016-01-18 19:21:20', function() {}); 

Auf diese Weise alle Datenbanklogik auf die bewegt spezifisches Repository und ich kann Tipp geben, es ist zurückgegebene Modelle. Diese Methodik führt auch zu einem saubereren Code, der einfacher zu lesen ist, und trennt Ihre Kernlogik von Eloquent.

0

Mit dem Schlüsselwort abstract kann die Implementierung einer Methode ausgelagert werden.

abstract class Model { 
    abstract public function find($id); 
} 

, die jedes Objekt erstreckt Modell zwingt, um diese Funktion zu implementieren.

Ich hoffe, dass das Sinn macht.