私は2つのコントローラSubmitPerformanceController
とPrintReportController
を持っています。
PrintReportController
にはgetPrintReport
というメソッドがあります。
SubmitPerformanceController
でこのメソッドにアクセスする方法?
あなたはこのようにあなたのコントローラメソッドにアクセスすることができます:
app('App\Http\Controllers\PrintReportController')->getPrintReport();
これはうまくいくでしょうが、コード構成の点では悪いです(あなたのPrintReportController
には正しい名前空間を使うことを忘れないでください)
PrintReportController
を拡張して、SubmitPerformanceController
がそのメソッドを継承するようにすることができます。
class SubmitPerformanceController extends PrintReportController {
// ....
}
しかし、これは他のすべてのメソッドもPrintReportController
から継承します。
最善の方法はtrait
を作成し、そこにロジックを実装してそれを使用するようにあなたのコントローラに指示することです。
trait PrintReport {
public function getPrintReport() {
// .....
}
}
この特色を使うようにコントローラーに伝えてください:
class PrintReportController extends Controller {
use PrintReport;
}
class SubmitPerformanceController extends Controller {
use PrintReport;
}
どちらのソリューションもSubmitPerformanceController
をgetPrintReport
メソッドにするため、コントローラ内から$this->getPrintReport();
で呼び出すことも、ルートとして直接呼び出すこともできます(routes.php
にマップした場合)。
あなたはここで特性についてもっと読むことができます。
そのメソッドが別のコントローラで必要な場合は、それを抽象化して再利用可能にする必要があります。その実装をサービスクラス(ReportingServiceまたはそれに類似したもの)に移動し、それをあなたのコントローラに注入します。
例:
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
}
}
その実装が必要な他のコントローラについても同じことをしてください。他のコントローラーからコントローラーメソッドに手を伸ばすのはコードの匂いです。
他のコントローラからコントローラを呼び出すことはお勧めできませんが、何らかの理由でそれを行わなければならない場合は、次のようにします。
Laravel 5互換方式
return \App::call('bla\bla\ControllerName@functionName');
注:これはページのURLを更新しません。
代わりにRouteを呼び出して、それをコントローラに呼び出させる方が良いです。
return \Redirect::route('route-name-here');
しないでください。これはアンチパターンです。あるコントローラに別のコントローラでアクセスする必要があるメソッドがある場合は、それが見直す必要がある兆候です。
メソッドをサービスクラスにリファクタリングすることを検討してください。これにより、複数のコントローラでインスタンス化できます。あなたが複数のモデルのために印刷報告書を提供する必要があるならば、あなたはこのような何かをすることができました:
class ExampleController extends Controller
{
public function printReport()
{
$report = new PrintReport($itemToReportOn);
return $report->render();
}
}
まず、他のコントローラからのコントローラの要求方法はEVILです。これはLaravelにおけるライフサイクルの多くの隠れた問題を引き起こすでしょう。
とにかく、それをするための多くの解決策があります。あなたはこれらの様々な方法の1つを選ぶことができます。
しかし、あなたはこの方法でパラメータや認証をすることはできません。
app(\App\Http\Controllers\PrintReportContoller::class)->getPrintReport();
あなたはこれで任意のパラメータと何かができます。あなたのプログラミング生活のための最善の解決策。 Repository
を代わりに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
特性を使用します。このプロキシを作成する特別な理由がある場合はお勧めします。あなたは任意のパラメータとカスタムヘッダを使うことができます。またこれは内部要求になります。 (偽のHTTPリクエスト)call
メソッドの詳細なマニュアルは にあります 。
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 ...
}
}
しかし、これも「良い」解決策ではありません。
私が思うに最もひどい解決策。あなたはどんなパラメータとカスタムヘッダも使うことができます。しかし、これは外部の余分なhttpリクエストを作ります。そのため、HTTP Webサーバーは稼働している必要があります。
$client = new Client([
'base_uri' => request()->getSchemeAndhttpHost(),
'headers' => request()->header()
]);
$a = $client->get('/performance/submit')->getBody()->getContents()
最後に、ケース2の方法1を使用しています。
\App::call('App\Http\Controllers\MyController@getFoo')
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();
}
}
ここでは特性はlaravelルーター(ミドルウェアと依存性注入のサポートを含む)によって実行中のコントローラーを完全にエミュレートします。 5.4バージョンでのみテスト済み
<?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();
}
}
それからそれをあなたのクラスに追加してコントローラを実行してください。依存性注入は現在のルートに割り当てられることに注意してください。
class CustomController extends Controller {
use RunsAnotherController;
public function someAction()
{
$controller = app()->make('App\Http\Controllers\AnotherController');
return $this->runController($controller, 'doSomething');
}
}
返信が遅くなりましたが、しばらくの間これを探していました。これは非常に簡単な方法で可能になりました。
パラメータなし
return redirect()->action('HomeController@index');
パラメータあり
return redirect()->action('UserController@profile', ['id' => 1]);
ドキュメント: https://laravel.com/docs/5.6/responses#redirecting-controller-actions
5.0に戻って、それは全体のパスを必要としました、今でははるかに簡単です。