来自Laravel 5中另一个控制器的Access Controller方法

时间:2015-05-21 05:21:19

标签: laravel laravel-5

我有两个控制器SubmitPerformanceControllerPrintReportController

PrintReportController我有一个名为getPrintReport的方法。

如何在SubmitPerformanceController

中访问此方法

15 个答案:

答案 0 :(得分:274)

您可以像这样访问您的控制器方法:

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();或直接作为路径调用它(如果您在{{1}中映射它})

您可以阅读有关特征here的更多信息。

答案 1 :(得分:35)

如果您需要在另一个控制器中使用该方法,则意味着您需要对其进行抽象并使其可重用。将该实现移动到服务类(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
  }
}

对需要该实现的其他控制器执行相同操作。从其他控制器到达控制器方法是代码味道。

答案 2 :(得分:18)

  

不建议从另一个控制器调用控制器,但是如果由于任何原因你必须这样做,你可以这样做:

Laravel 5兼容方法

application server

注意:这不会更新网页的网址。

最好拨打路线,让它呼叫控制器。

return \App::call('bla\bla\ControllerName@functionName');

答案 3 :(得分:9)

你不应该。这是一种反模式。如果您在一个控制器中有一个方法需要在另一个控制器中访问,那么这是一个需要重新分解的符号。

考虑将方法重新分解为服务类,然后可以在多个控制器中实例化。因此,如果您需要为多个模型提供打印报告,您可以执行以下操作:

class ExampleController extends Controller
{
    public function printReport()
    {
        $report = new PrintReport($itemToReportOn);
        return $report->render();
    }
}

答案 4 :(得分:7)

<select>

答案 5 :(得分:6)

首先,来自另一个控制器的控制器的请求方法是EVIL。这将导致Laravel中许多隐藏的生命周期问题。

无论如何,有很多解决方案可以做到这一点。您可以选择以下各种方式之一。

案例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请求)您可以在here中查看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客户端

我认为最可怕的解决方案。您也可以使用任何参数和自定义标题。但这使得外部额外的http请求。所以HTTP Web服务器必须正在运行。

$client = new Client([
    'base_uri' => request()->getSchemeAndhttpHost(),
    'headers' => request()->header()
]);
$a = $client->get('/performance/submit')->getBody()->getContents()

最后我使用了案例2的方法1.我需要参数和

答案 6 :(得分:3)

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();   
    }
   }

答案 7 :(得分:1)

这里的特性完全模仿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');
    }
}

答案 8 :(得分:1)

您可以在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();

    }

}

答案 9 :(得分:0)

最新答复,但我一直在寻找它。现在这可以以非常简单的方式实现。

没有参数

return redirect()->action('HomeController@index');

带有参数

return redirect()->action('UserController@profile', ['id' => 1]);

文档:https://laravel.com/docs/5.6/responses#redirecting-controller-actions

在5.0版本中,它需要整个路径,现在要简单得多。

答案 10 :(得分:0)

您可以通过实例化控制器并调用doAction:(在控制器类的声明前放置use Illuminate\Support\Facades\App;)来访问控制器

$controller = App::make('\App\Http\Controllers\YouControllerName');
$data = $controller->callAction('controller_method', $parameters);

还请注意,这样做将不会执行在该控制器上声明的任何中间件。

答案 11 :(得分:0)

此方法也适用于相同层次的Controller文件:

$printReport = new PrintReportController;

$prinReport->getPrintReport();

答案 12 :(得分:0)

//在控制器A中
公共静态函数function1(){

}

在控制器B中,“视图”或任何其他地方
A :: function1();

答案 13 :(得分:0)

尝试在SubmitPerformanceController中创建一个新的PrintReportController对象,然后直接调用getPrintReport方法。

例如,假设我在SubmitPerformanceController中有一个名为“ Test”的函数,那么我可以执行以下操作:

public function test() { 
  $prc = new PrintReportController();
  $prc->getPrintReport();
 }

答案 14 :(得分:0)

  1. 当然,您可以实例化另一个控制器并调用所需的方法。也许这不是一个好习惯,但我不知道为什么:
$otherController = new OtherController();
$otherController->methodFromOtherController($param1, $param2 ...);
  1. 但是,这样做会遇到问题:另一种方法返回诸如response()-> json($ result)之类的东西,不是您想要的。

  2. 要解决此问题,请将另一个控制器的方法的第一个参数定义为:

public function methodFromOtherController(Request $request = null, ...
  1. 从主控制器调用methodFromOtherController时,您将传递null作为第一个参数值:
$otherController = new OtherController();
$otherController->methodFromOtherController(null, $param1, $param2 ...);
  1. 最后,在methodFromOtherController方法的末尾创建一个条件:
public function methodFromOtherController(Request $request = null, ...) 
{
  ...
  if (is_null($request)) {
    return $result;
  } else {
    return response()->json($result);
  }
}
  1. 一旦Laravel在直接路由调用中设置了$ request,就可以区分每种情况并返回相应的值。