Laravel 5의 다른 컨트롤러에서 액세스 컨트롤러 방법
두 개의 컨트롤러 SubmitPerformanceController
가 PrintReportController
있습니다.
에라 PrintReportController
는 메소드가 getPrintReport
있습니다.
에서이 방법에 액세스하는 방법은 SubmitPerformanceController
무엇입니까?
다음과 같이 컨트롤러 메소드에 액세스 할 수 있습니다.
app('App\Http\Controllers\PrintReportController')->getPrintReport();
이것은 작동하지만 코드 구성 측면에서 나쁩니다 (에 적합한 네임 스페이스를 사용해야 함 PrintReportController
)
당신은 확장 할 수 있습니다 PrintReportController
그래서 SubmitPerformanceController
그 방법을 상속합니다
class SubmitPerformanceController extends PrintReportController {
// ....
}
그러나 이것은에서 다른 모든 방법을 상속합니다 PrintReportController
.
가장 좋은 방법은 trait
(예 : in 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
)
다른 컨트롤러에서 해당 방법이 필요한 경우이를 추상화하여 재사용 할 수 있어야합니다. 해당 구현을 서비스 클래스 (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입니다. 이것은 라 라벨의 라이프 사이클에서 많은 숨겨진 문제를 일으킬 것입니다.
어쨌든, 그렇게하는 많은 솔루션이 있습니다. 이러한 다양한 방법 중 하나를 선택할 수 있습니다.
사례 1) 수업을 기준으로 전화를 걸려면
방법 1) 간단한 방법
그러나이 방법으로는 매개 변수 나 인증 을 추가 할 수 없습니다 .
app(\App\Http\Controllers\PrintReportContoller::class)->getPrintReport();
방법 2) 컨트롤러 로직을 서비스로 나누십시오.
이것으로 매개 변수와 무언가 를 추가 할 수 있습니다 . 프로그래밍 수명을위한 최고의 솔루션. 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 ...
}
}
사례 2) 경로를 기준으로 전화를 걸려면
방법 1) 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 ...
}
}
그러나 이것은 또한 '좋은'해결책이 아닙니다.
방법 2) guzzlehttp 클라이언트 사용
This is the most terrible solution I think. You can use any parameters and custom headers, too. But this would be making an external extra http request. So HTTP Webserver must be running.
$client = new Client([
'base_uri' => request()->getSchemeAndhttpHost(),
'headers' => request()->header()
]);
$a = $client->get('/performance/submit')->getBody()->getContents()
Finally I am using Way 1 of Case 2. I need parameters and
\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();
}
}
Here the trait fully emulates running controller by laravel router (including support of middlewares and dependency injection). Tested only with 5.4 version
<?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();
}
}
Then just add it to your class and run the controller. Note, that dependency injection will be assigned with your current route.
class CustomController extends Controller {
use RunsAnotherController;
public function someAction()
{
$controller = app()->make('App\Http\Controllers\AnotherController');
return $this->runController($controller, 'doSomething');
}
}
Late reply, but I have been looking for this for sometime. This is now possible in a very simple way.
Without parameters
return redirect()->action('HomeController@index');
With Parameters
return redirect()->action('UserController@profile', ['id' => 1]);
Docs: https://laravel.com/docs/5.6/responses#redirecting-controller-actions
Back in 5.0 it required the entire path, now it's much simpler.
You can use a static method in PrintReportController and then call it from the SubmitPerformanceController like this;
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();
}
}
'IT story' 카테고리의 다른 글
아이폰 키보드, UITextField 커버 (0) | 2020.07.12 |
---|---|
Hive에서 테이블 파티셔닝과 버킷 팅의 차이점은 무엇입니까? (0) | 2020.07.12 |
주어진 숫자와 같은 합을 가진 배열에서 원소의 쌍을 찾으십시오. (0) | 2020.07.12 |
동적 셀 높이를 가진 UITableView의 reloadData ()로 인해 스크롤이 급증합니다. (0) | 2020.07.12 |
XAMPP에서 phpMyAdmin으로“구성에 정의 된 controluser 연결에 실패했습니다” (0) | 2020.07.12 |