我有两个控制器SubmitPerformanceController
和PrintReportController
。
在PrintReportController
我有一个方法称为getPrintReport
。
如何在中访问此方法SubmitPerformanceController
?
我有两个控制器SubmitPerformanceController
和PrintReportController
。
在PrintReportController
我有一个方法称为getPrintReport
。
如何在中访问此方法SubmitPerformanceController
?
Answers:
您可以这样访问控制器方法:
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
结构。
首先,从另一个控制器请求控制器的方法是EVIL。这将在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 Webserver必须正在运行。
$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();
}
}
这种方法也适用于相同层次的Controller文件:
$printReport = new PrintReportController;
$prinReport->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(......)
所以做得更短。
您可以通过实例化控制器并调用doAction :(use Illuminate\Support\Facades\App;
在控制器类声明之前放置)来访问控制器。
$controller = App::make('\App\Http\Controllers\YouControllerName');
$data = $controller->callAction('controller_method', $parameters);
还要注意,这样做将不会执行在该控制器上声明的任何中间件。
回复较晚,但一段时间以来我一直在寻找。现在这可以以非常简单的方式实现。
没有参数
return redirect()->action('HomeController@index');
带参数
return redirect()->action('UserController@profile', ['id' => 1]);
文件: https //laravel.com/docs/5.6/responses#redirecting-controller-actions
回到5.0,它需要完整的路径,现在要简单得多。