回答:
次のようにコントローラーメソッドにアクセスできます。
app('App\Http\Controllers\PrintReportController')->getPrintReport();
これは機能しますが、コード編成の点で悪いです(に適切な名前空間を使用することを忘れないでくださいPrintReportController
)
あなたは拡張することができるPrintReportController
のでSubmitPerformanceController
、そのメソッドを継承します
class SubmitPerformanceController extends PrintReportController {
// ....
}
ただし、これはから他のすべてのメソッドも継承しPrintReportController
ます。
最良のアプローチは、trait
(たとえばでapp/Traits
)を作成し、そこにロジックを実装し、それを使用するようにコントローラーに指示することです。
trait PrintReport {
public function getPrintReport() {
// .....
}
}
このトレイトを使用するようにコントローラーに指示します。
class PrintReportController extends Controller {
use PrintReport;
}
class SubmitPerformanceController extends Controller {
use PrintReport;
}
どちらのソリューションSubmitPerformanceController
もgetPrintReport
メソッドを持っているので$this->getPrintReport();
、コントローラ内から、またはルートとして直接呼び出すことができます(でマッピングした場合routes.php
)
特性について詳しくは、こちらをご覧ください。
app('App\Http\Controllers\PrintReportController')->getPrintReport();
に変換できapp(PrintReportController::class')->getPrintReport()
ます。私のためのクリーンなソリューション。
別のコントローラーでそのメソッドが必要な場合は、それを抽象化して再利用可能にする必要があります。その実装をサービスクラス(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
}
}
その実装が必要な他のコントローラーについても同じようにします。他のコントローラーからコントローラーメソッドに到達すると、コードのにおいがします。
Services
プロジェクトが大きくない場合は、フォルダや機能のフォルダが呼ばれReporting
、それが大きなプロジェクトや用途だ場合Folders By Feature
の構造。
別のコントローラーからコントローラーを呼び出すことはお勧めできませんが、何らかの理由でこれを行う必要がある場合は、次のようにできます。
Laravel 5互換メソッド
return \App::call('bla\bla\ControllerName@functionName');
注:これによってページのURLが更新されることはありません。
代わりにルートを呼び出して、コントローラーを呼び出せるようにすることをお勧めします。
return \Redirect::route('route-name-here');
すべきではない。それはアンチパターンです。あるコントローラーに別のコントローラーでアクセスする必要があるメソッドがある場合、それはリファクタリングする必要がある兆候です。
複数のコントローラーでインスタンス化できるように、サービスクラスにメソッドをリファクタリングすることを検討してください。したがって、複数のモデルの印刷レポートを提供する必要がある場合は、次のようにすることができます。
class ExampleController extends Controller
{
public function printReport()
{
$report = new PrintReport($itemToReportOn);
return $report->render();
}
}
\App::call('App\Http\Controllers\MyController@getFoo')
まず第一に、別のコントローラーからコントローラーのメソッドを要求することは悪です。これは、Laravelのライフサイクルで多くの隠れた問題を引き起こします。
とにかく、それを行うための多くの解決策があります。これらのさまざまな方法のいずれかを選択できます。
ただし、この方法でパラメーターや認証を追加することはできません。
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
アプリケーションの単体テストで使用される特性を使用します。このプロキシを作成する特別な理由がある場合は、これをお勧めします。任意のパラメータとカスタムヘッダーを使用できます。また、これは laravelの内部リクエストになります。(偽の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を使用しています。パラメーターが必要です。
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で静的メソッドを使用して、SubmitPerformanceControllerから呼び出すことができます。
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();
}
}
ここで、トレイルは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');
}
}
app()->make(......)
はと等しいapp(......)
ため、短くなることを考慮してください。
返事が遅くなりましたが、私はこれをしばらく探していました。これは非常に簡単な方法で可能になりました。
パラメータなし
return redirect()->action('HomeController@index');
パラメータあり
return redirect()->action('UserController@profile', ['id' => 1]);
ドキュメント:https : //laravel.com/docs/5.6/responses#redirecting-controller-actions
5.0では、パス全体が必要でしたが、今でははるかに簡単になりました。