Mam dwa kontrolery SubmitPerformanceController
i PrintReportController
.
W PrintReportController
mam metodę o nazwie getPrintReport
.
Jak uzyskać dostęp do tej metody w SubmitPerformanceController
?
Możesz uzyskać dostęp do metody kontrolera w następujący sposób:
app('App\Http\Controllers\PrintReportController')->getPrintReport();
To zadziała, ale jest złe pod względem organizacji kodu (pamiętaj, aby użyć odpowiedniej przestrzeni nazw PrintReportController
)
Możesz rozszerzyć, PrintReportController
więc SubmitPerformanceController
będzie dziedziczyć tę metodę
class SubmitPerformanceController extends PrintReportController {
// ....
}
Ale to również odziedziczy wszystkie inne metody z PrintReportController
.
Najlepszym podejściem będzie utworzenie trait
(np. In app/Traits
), zaimplementowanie tam logiki i poinformowanie kontrolerów, aby z niej korzystali:
trait PrintReport {
public function getPrintReport() {
// .....
}
}
Powiedz swoim kontrolerom, aby użyli tej cechy:
class PrintReportController extends Controller {
use PrintReport;
}
class SubmitPerformanceController extends Controller {
use PrintReport;
}
Oba rozwiązania sprawiają, SubmitPerformanceController
że getPrintReport
metoda ma , więc możesz wywołać ją z $this->getPrintReport();
poziomu kontrolera lub bezpośrednio jako trasę (jeśli zmapowałeś ją w routes.php
)
Możesz przeczytać więcej o cechach tutaj .
app('App\Http\Controllers\PrintReportController')->getPrintReport();
można przekształcić wapp(PrintReportController::class')->getPrintReport()
. Czyste rozwiązanie dla mnie.Jeśli potrzebujesz tej metody w innym kontrolerze, oznacza to, że musisz ją wyodrębnić i umożliwić jej ponowne użycie. Przenieś tę implementację do klasy usług (ReportingService lub podobnej) i wstrzyknij ją do kontrolerów.
Przykład:
Zrób to samo dla innych kontrolerów, w których potrzebujesz tej implementacji. Sięganie po metody kontrolera z innych kontrolerów to zapach kodu.
źródło
Services
folder, jeśli projekt nie jest duży, albo folder funkcji,Reporting
jeśli jest to większy projekt i używaFolders By Feature
struktury.Metoda zgodna z Laravel 5
Uwaga: to nie zaktualizuje adresu URL strony.
Lepiej jest zamiast tego wywołać trasę i pozwolić jej wywołać kontroler.
źródło
Nie powinieneś. To anty-wzór. Jeśli masz metodę w jednym kontrolerze, do której chcesz uzyskać dostęp w innym kontrolerze, to jest to znak, który musisz ponownie uwzględnić.
Rozważ ponowne uwzględnienie metody w klasie usługi, którą można następnie utworzyć na wielu kontrolerach. Jeśli więc chcesz oferować raporty drukowania dla wielu modeli, możesz zrobić coś takiego:
źródło
źródło
Po pierwsze, żądanie metody kontrolera od innego kontrolera jest ZŁE. Spowoduje to wiele ukrytych problemów w cyklu życia Laravel.
Zresztą istnieje wiele rozwiązań, jak to zrobić. Możesz wybrać jeden z tych różnych sposobów.
Przypadek 1) Jeśli chcesz zadzwonić na podstawie klas
Sposób 1) Prosty sposób
Ale w ten sposób nie możesz dodać żadnych parametrów ani uwierzytelnienia .
Sposób 2) Podziel logikę kontrolera na usługi.
Możesz dodać dowolne parametry i coś z tym. Najlepsze rozwiązanie dla Twojego życia programistycznego. Możesz
Repository
zamiast tego zrobićService
.Przypadek 2) Jeśli chcesz dzwonić na podstawie tras
Sposób 1) Użyj
MakesHttpRequests
cechy używanej w testowaniu jednostkowym aplikacji.Polecam to, jeśli masz szczególny powód do tworzenia tego serwera proxy, możesz użyć dowolnych parametrów i niestandardowych nagłówków . Także to będzie wewnętrzna prośba w laravel. (Fałszywe żądanie HTTP) Więcej informacji na temat
call
metody można znaleźć tutaj .Jednak nie jest to również „dobre” rozwiązanie.
Sposób 2) Użyj klienta guzzlehttp
Myślę, że to najstraszniejsze rozwiązanie. Możesz także użyć dowolnych parametrów i niestandardowych nagłówków . Ale oznaczałoby to wykonanie dodatkowego zewnętrznego żądania http. Dlatego serwer WWW HTTP musi być uruchomiony.
Wreszcie używam sposobu 1 przypadku 2. Potrzebuję parametrów i
źródło
źródło
Możesz użyć metody statycznej w PrintReportController, a następnie wywołać ją z SubmitPerformanceController w ten sposób;
źródło
To podejście działa również z tą samą hierarchią plików kontrolera:
źródło
Tutaj cecha w pełni emuluje działający kontroler przez router laravel (w tym wsparcie dla oprogramowania pośredniego i wstrzykiwania zależności). Testowany tylko z wersją 5.4
Następnie po prostu dodaj go do swojej klasy i uruchom kontroler. Należy pamiętać, że iniekcja zależności zostanie przypisana do bieżącej trasy.
źródło
app()->make(......)
jest równe,app(......)
więc jest krótsze.Możesz uzyskać dostęp do kontrolera, tworząc jego instancję i wywołując doAction: (wstaw
use Illuminate\Support\Facades\App;
przed deklaracją klasy kontrolera)Zwróć również uwagę, że robiąc to, nie wykonasz żadnego oprogramowania pośredniego zadeklarowanego na tym kontrolerze.
źródło
Późna odpowiedź, ale szukałem tego od jakiegoś czasu. Jest to teraz możliwe w bardzo prosty sposób.
Bez parametrów
Z parametrami
Dokumenty: https://laravel.com/docs/5.6/responses#redirecting-controller-actions
W wersji 5.0 wymagało to całej ścieżki, teraz jest znacznie prostsze.
źródło