İki denetleyicim var SubmitPerformanceController
ve PrintReportController
.
İçinde PrintReportController
bir yöntem var getPrintReport
.
Bu yönteme nasıl erişilir SubmitPerformanceController
?
İki denetleyicim var SubmitPerformanceController
ve PrintReportController
.
İçinde PrintReportController
bir yöntem var getPrintReport
.
Bu yönteme nasıl erişilir SubmitPerformanceController
?
Yanıtlar:
Denetleyici yönteminize şu şekilde erişebilirsiniz:
app('App\Http\Controllers\PrintReportController')->getPrintReport();
Bu işe yarayacak, ancak kod organizasyonu açısından kötü (sizin için doğru ad alanını kullanmayı unutmayın PrintReportController
)
Sen uzatabilirsiniz PrintReportController
böylece SubmitPerformanceController
bu yöntemi devralır
class SubmitPerformanceController extends PrintReportController {
// ....
}
Ancak bu, diğer tüm yöntemleri de miras alacaktır PrintReportController
.
En iyi yaklaşım bir trait
(ör. app/Traits
İçinde) oluşturmak , mantığı oraya uygulamak ve denetleyicilerinize bunu kullanmasını söylemek olacaktır:
trait PrintReport {
public function getPrintReport() {
// .....
}
}
Denetleyicilerinize bu özelliği kullanmasını söyleyin:
class PrintReportController extends Controller {
use PrintReport;
}
class SubmitPerformanceController extends Controller {
use PrintReport;
}
Her iki çözüm de yapmak SubmitPerformanceController
zorunda getPrintReport
olan arayabilirsin böylece yöntemi $this->getPrintReport();
kontrolörü içinde veya doğrudan bir yol olarak gelen (sen eşledikten eğer routes.php
)
Özellikler hakkında daha fazla bilgiyi buradan edinebilirsiniz .
app('App\Http\Controllers\PrintReportController')->getPrintReport();
dönüşebilir app(PrintReportController::class')->getPrintReport()
. Benim için temiz çözüm.
Bu yönteme başka bir denetleyicide ihtiyacınız varsa, bunu soyutlamanız ve yeniden kullanılabilir hale getirmeniz gerekir. Bu uygulamayı bir hizmet sınıfına (ReportingService veya benzeri bir şey) taşıyın ve denetleyicilerinize enjekte edin.
Misal:
class ReportingService
{
public function getPrintReport()
{
// your implementation here.
}
}
// don't forget to import ReportingService at the top (use Path\To\Class)
class SubmitPerformanceController extends Controller
{
protected $reportingService;
public function __construct(ReportingService $reportingService)
{
$this->reportingService = $reportingService;
}
public function reports()
{
// call the method
$this->reportingService->getPrintReport();
// rest of the code here
}
}
Bu uygulamaya ihtiyaç duyduğunuz diğer denetleyiciler için de aynısını yapın. Diğer denetleyicilerden denetleyici yöntemlerine ulaşmak bir kod kokusudur.
Services
Proje büyük değilse bir klasör ya da Reporting
daha büyük bir proje ve Folders By Feature
yapı kullanıyorsa çağrılan bir özellik klasörü .
Bir Denetleyiciyi başka bir Denetleyiciden çağırmanız önerilmez, ancak herhangi bir nedenle yapmanız gerekirse, bunu yapabilirsiniz:
Laravel 5 uyumlu yöntem
return \App::call('bla\bla\ControllerName@functionName');
Not: bu sayfanın URL'sini güncellemez.
Bunun yerine Rotayı aramak ve denetleyiciyi aramasına izin vermek daha iyidir.
return \Redirect::route('route-name-here');
Yapmamalısın. Bu bir anti-desen. Bir denetleyicide, başka bir denetleyicide erişmeniz gereken bir yönteminiz varsa, bu, yeniden faktörleştirmeniz gereken bir işarettir.
Yöntemi, birden çok denetleyicide başlatabileceğiniz bir hizmet sınıfına yeniden çarpanlara ayırmayı düşünün. Dolayısıyla, birden fazla model için baskı raporları sunmanız gerekiyorsa, bunun gibi bir şey yapabilirsiniz:
class ExampleController extends Controller
{
public function printReport()
{
$report = new PrintReport($itemToReportOn);
return $report->render();
}
}
\App::call('App\Http\Controllers\MyController@getFoo')
Her şeyden önce, başka bir denetleyiciden bir denetleyici yöntemi istemek EVIL'dir. Bu Laravel'in yaşam döngüsünde birçok gizli soruna neden olacaktır.
Her neyse, bunu yapmak için birçok çözüm var. Bu çeşitli yollardan birini seçebilirsiniz.
Ancak bu şekilde herhangi bir parametre veya kimlik doğrulama ekleyemezsiniz .
app(\App\Http\Controllers\PrintReportContoller::class)->getPrintReport();
Sen herhangi bir parametre ve bir şeyler ekleyebilir bununla. Programlama hayatınız için en iyi çözüm. Bunun Repository
yerine yapabilirsiniz Service
.
class PrintReportService
{
...
public function getPrintReport() {
return ...
}
}
class PrintReportController extends Controller
{
...
public function getPrintReport() {
return (new PrintReportService)->getPrintReport();
}
}
class SubmitPerformanceController
{
...
public function getSomethingProxy() {
...
$a = (new PrintReportService)->getPrintReport();
...
return ...
}
}
MakesHttpRequests
Uygulama Birimi Testinde kullanılan özelliği kullanın .Bu proxy'yi oluşturmak için özel bir nedeniniz varsa , herhangi bir parametre ve özel üstbilgi kullanabilirsiniz . Ayrıca bu laravel'de dahili bir istek olacaktır. (Sahte HTTP İsteği) Buradacall
yöntem için daha fazla ayrıntı görebilirsiniz .
class SubmitPerformanceController extends \App\Http\Controllers\Controller
{
use \Illuminate\Foundation\Testing\Concerns\MakesHttpRequests;
protected $baseUrl = null;
protected $app = null;
function __construct()
{
// Require if you want to use MakesHttpRequests
$this->baseUrl = request()->getSchemeAndHttpHost();
$this->app = app();
}
public function getSomethingProxy() {
...
$a = $this->call('GET', '/printer/report')->getContent();
...
return ...
}
}
Ancak bu da 'iyi' bir çözüm değildir.
Bu bence en korkunç çözüm. Sen herhangi bir parametre ve özel başlıklarını kullanabilirsiniz da. Ancak bu harici bir ek http isteği yapar. Bu nedenle HTTP Web sunucusu çalışıyor olmalıdır.
$client = new Client([
'base_uri' => request()->getSchemeAndhttpHost(),
'headers' => request()->header()
]);
$a = $client->get('/performance/submit')->getBody()->getContents()
Son olarak Vaka 2'nin 1. Yolu'nu kullanıyorum. Parametrelere ve
namespace App\Http\Controllers;
//call the controller you want to use its methods
use App\Http\Controllers\AdminController;
use Illuminate\Http\Request;
use App\Http\Requests;
class MealController extends Controller
{
public function try_call( AdminController $admin){
return $admin->index();
}
}
PrintReportController içinde statik bir yöntem kullanabilir ve SubmitPerformanceController'dan bu şekilde çağırabilirsiniz;
namespace App\Http\Controllers;
class PrintReportController extends Controller
{
public static function getPrintReport()
{
return "Printing report";
}
}
namespace App\Http\Controllers;
use App\Http\Controllers\PrintReportController;
class SubmitPerformanceController extends Controller
{
public function index()
{
echo PrintReportController::getPrintReport();
}
}
Burada özellik, laravel yönlendirici tarafından çalışan denetleyiciyi tamamen öykünür (orta ağ desteği ve bağımlılık enjeksiyonu dahil). Yalnızca 5.4 sürümü ile test edilmiştir
<?php
namespace App\Traits;
use Illuminate\Pipeline\Pipeline;
use Illuminate\Routing\ControllerDispatcher;
use Illuminate\Routing\MiddlewareNameResolver;
use Illuminate\Routing\SortedMiddleware;
trait RunsAnotherController
{
public function runController($controller, $method = 'index')
{
$middleware = $this->gatherControllerMiddleware($controller, $method);
$middleware = $this->sortMiddleware($middleware);
return $response = (new Pipeline(app()))
->send(request())
->through($middleware)
->then(function ($request) use ($controller, $method) {
return app('router')->prepareResponse(
$request, (new ControllerDispatcher(app()))->dispatch(
app('router')->current(), $controller, $method
)
);
});
}
protected function gatherControllerMiddleware($controller, $method)
{
return collect($this->controllerMidlleware($controller, $method))->map(function ($name) {
return (array)MiddlewareNameResolver::resolve($name, app('router')->getMiddleware(), app('router')->getMiddlewareGroups());
})->flatten();
}
protected function controllerMidlleware($controller, $method)
{
return ControllerDispatcher::getMiddleware(
$controller, $method
);
}
protected function sortMiddleware($middleware)
{
return (new SortedMiddleware(app('router')->middlewarePriority, $middleware))->all();
}
}
Daha sonra sınıfınıza ekleyin ve denetleyiciyi çalıştırın. Bağımlılık enjeksiyonunun geçerli rotanıza atanacağını unutmayın.
class CustomController extends Controller {
use RunsAnotherController;
public function someAction()
{
$controller = app()->make('App\Http\Controllers\AnotherController');
return $this->runController($controller, 'doSomething');
}
}
app()->make(......)
eşit app(......)
olduğu ve daha kısa olduğu göz önünde bulundurun .
Denetleyiciyi başlatarak ve doAction'ı çağırarak erişebilirsiniz: ( use Illuminate\Support\Facades\App;
denetleyici sınıfı bildiriminden önce koyun )
$controller = App::make('\App\Http\Controllers\YouControllerName');
$data = $controller->callAction('controller_method', $parameters);
Bunu yaparak, o denetleyicide bildirilen herhangi bir ara yazılımı yürütmeyeceğinizi de unutmayın.
Geç cevap, ama bir süredir bunu arıyorum. Bu artık çok basit bir şekilde mümkün.
Parametresiz
return redirect()->action('HomeController@index');
Parametrelerle
return redirect()->action('UserController@profile', ['id' => 1]);
Dokümanlar: https://laravel.com/docs/5.6/responses#redirecting-controller-actions
5.0'a dönünce tüm yolu gerektiriyordu, şimdi çok daha basit.