2016-11-06 92 views
5

W następującym Laravel 5 Model powinien być metoda findByIdAndCourseOrFail statyczne?Czy niestandardowa metoda wyszukiwania w modelu Laravel powinna być statyczna?

class Section extends Model { 

    //should this method be static? 
    public function findByIdAndCourseOrFail($id, $courseId) 
    { 

     $result = $this->where('id', $id)->where('course_id', $courseId)->first(); 

     if (!is_null($result)) 
     { 
      return $result; 
     } 

     throw (new ModelNotFoundException())->setModel(Section::class); 

    } 


    } 

Z kontrolera:

class SectionsController extends Controller { 

protected $sections; 

public function __construct(Section $section) 
{ 

    $this->sections = $section; 

} 

public function foo($id, $courseId) //illustration only 
{ 
    $section = $this->sections->findOrFail($id); 

    $section = $this->sections->findByIdAndCourseOrFail($id, $courseId); 
    //would need to be non-static 

    $section = Section::findByIdAndCourseOrFail($id, $courseId); 
    //weird when compared with find above 
} 

Z jednej strony, nie jesteśmy działając na przykład sekcja [uwaga]. Z drugiej strony, w kontrolerze z autododatkowym wtryskiem przez Laravel's service container działalibyśmy na instancji: $sections = $this->sections-> findByIdAndCourseOrFail(7,3);, a mój IDE (PhpStorm) skrzeczałby, jeśli Static.

[Uwaga]: ten komentarz może być nieporozumieniem w działaniu modeli Laravel. Dla mnie, oczekiwałbym, że będzie to metoda klasy, a więc statyczna, w przeciwieństwie do instancji, która powróciłaby metoda find.

+0

Dobrze, '$ this' nie jest dostępny metoda statyczna. – Xorifelse

+0

Oczywiście, jeśli metoda zmieni się na statyczną, '$ this->' zostanie zmienione na 'self ::' – Gazzer

+0

Ale wtedy 'gdzie()' i 'first()' również wymagają zmiany, a może wtedy cały "model", jeśli są tam zdefiniowane metody. – Xorifelse

Odpowiedz

1

Nie jestem pewien, czy zamierzam użyć takiego rozwiązania w postaci local scopes. Ale to działa na mnie na laravel 5.2:

public function scopeFindByIdAndCourseOrFail($query, $id, $courseId) 
{ 
    $result = $query->where('id', $id)->where('course_id', $courseId)->first(); 

    if (!is_null($result)) 
    { 
     return $result; 
    } 

    throw (new ModelNotFoundException())->setModel(Section::class); 
} 

W regulatorze można go używać w obie strony:

$section = Section::findByIdAndCourseOrFail($id, $courseId); 

Albo

$model = new Section(); 
$section = $model->findByIdAndCourseOrFail($id, $courseId); 
+0

To rzeczywiście jest właściwe podejście. Patrząc głębiej w kod źródłowy, żadna z metod modeli nie jest w rzeczywistości statyczna. model :: find() jest cukrem syntaktycznym, więc używanie skal, które zachowują te same cechy, jest właściwym podejściem. – Gazzer

1
class Section extends Model { 


public static function findByIdAndCourseOrFail($id, $courseId) 
{ 

    $result = self::where('id', $id)->where('course_id', $courseId)->first(); 

    if (!is_null($result)) 
    { 
     return $result; 
    } 

    throw (new ModelNotFoundException())->setModel(Section::class); 

} 


} 
class Section extends Model { 


public static function findByIdAndCourseOrFail($id, $courseId) 
{ 

    $result = self::where('id', $id)->where('course_id', $courseId)->first(); 

    if (!is_null($result)) 
    { 
     return $result; 
    } 

    throw (new ModelNotFoundException())->setModel(Section::class); 

} 


} 
+1

Pytanie nie dotyczy tego, jak uczynić metodę statyczną. bądź statyczny, czy też nie ... – Gazzer

+0

cóż, w tym przypadku ... powinien być statyczny, ma dla mnie więcej sensu, wywołujesz tę metodę statycznie, więc zwraca ci model. – Sherif

+0

Jeśli masz już model lub jego instancję, nie byłoby sensu wywoływać go na znajdźcie tego numeru. – Sherif

1

Osobiście zrobiłbym to statyczną metodą, nie jestem pewien, czy istnieje "poprawna" odpowiedź, jak można zrobić. Sposób, w jaki je oddzielałem, jest taki, że jeśli robię coś dla instancji modelu, to robię normalną publiczną funkcję. Jeśli robię coś do kolekcji, używam statycznego. Na przykład:

$person = new Person(); 
$person->setAdmin(true); 
$person->save(); 

// OR 

$admins = Person::getAdmins(); 

w pierwszym przykładzie mamy konkretną instancję Person i jesteśmy manipulowania, cały kod byłoby po prostu manipulowanie tej konkretnej instancji. W drugim przykładzie działamy na całą kolekcję Person i chcemy, aby zwrócono kolekcję obiektów.

W twoim przypadku trzeba by zainicjować instancję Section tak, aby móc korzystać z non-statycznej metody publiczne, tak:

$section = new Section(); 
$foundSection = $section->findByIdAndCourseOrFail(7,3); 

Więc $section staje się tymczasową zmienną, która nie jest używana . Z drugiej strony, jeśli zrobisz to statycznie, możesz to nazwać, nie musząc tego robić.

$section = Section::findByIdAndCourseOrFail(7,3); 

Mam nadzieję, że ma to sens.

+0

Dziękuję za tę odpowiedź. Odnośnie: "W twoim przypadku musiałbyś zainicjować instancję Sekcji tylko po to, by móc użyć twojej niestatycznej metody publicznej, jak ta". W rzeczywistości tak nie jest. W kontrolerze używam odbicia, a instancja jest automatycznie wstrzykiwana do konstruktora. 'public function __construct (Section $ sections) {$ this-> sections = $ sections}' iw tym przypadku static ma mniej sensu, chociaż generalnie pracuję zgodnie z logiką, którą wykonujesz, stąd pytanie! – Gazzer

+1

Niezależnie od tego nie sądzę, bym zrobił wyjątek tylko w tej sprawie. A co, jeśli musisz użyć tej funkcji gdzie indziej w innym czasie? Trzymałbym się twoich standardów. – Pitchinnate

+0

Nie sądzę, że robi to wyjątek. Automatyczne wtryskiwanie z kontenera usługi jest szeroko stosowane, a sama metoda 'find()' nie jest wywoływana statycznie, a uczynienie jej statyczną niweluje zalety wtrysku, ponieważ wykonywałbym wywołania 'find()' z instancją, ale nie moje wywołania 'findByCustom()', które wyglądałyby dziwnie! – Gazzer