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

Ift*_*lam 129 laravel laravel-5

我有两个控制器SubmitPerformanceControllerPrintReportController.

PrintReportController我有一个方法叫getPrintReport.

如何访问此方法SubmitPerformanceController

sha*_*ddy 318

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

app('App\Http\Controllers\PrintReportController')->getPrintReport();
Run Code Online (Sandbox Code Playgroud)

这可行,但在代码组织方面很糟糕(记得为你使用正确的命名空间PrintReportController)

你可以扩展,PrintReportController所以SubmitPerformanceController将继承该方法

class SubmitPerformanceController extends PrintReportController {
     // ....
}
Run Code Online (Sandbox Code Playgroud)

但是这也将继承所有其他方法PrintReportController.

最好的方法是创建一个trait,在那里实现逻辑并告诉控制器使用它:

trait PrintReport {

    public function getPrintReport() {
        // .....
    }
}
Run Code Online (Sandbox Code Playgroud)

告诉你的控制器使用这个特性:

class PrintReportController extends Controller {
     use PrintReport;
}

class SubmitPerformanceController extends Controller {
     use PrintReport;
}
Run Code Online (Sandbox Code Playgroud)

两种解决方案app/Traits都有SubmitPerformanceController方法,因此您可以getPrintReport在控制器内或直接作为路径调用它(如果您将其映射到$this->getPrintReport();)

您可以在此处阅读有关特征的更多信息.

  • `app('App\Http\Controllers\PrintReportController') - > getPrintReport();`可以转换为`app(PrintReportController :: class') - > getPrintReport()`.为我清洁解决方案. (19认同)
  • 应该保存包含特征的文件在哪里? (8认同)
  • 在 Laravel 中使用特征的一个小例子:https://www.develodesign.co.uk/news/laravel-traits-what-are-traits-and-how-to-create-a-laravel-trait/ (4认同)
  • @VincentDecaux 你忘了`'`:-P。删除它,否则它将不起作用 (4认同)
  • @EricMcWinNEr应用程序/特质是一个很好的起点。 (2认同)
  • @Brainmaniac 在“app/Traits”中。更多相关信息[此处](/sf/answers/2820216451/)。 (2认同)

Ruf*_*les 41

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

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

  • 如果项目不大,则为“Services”文件夹;如果项目较大且使用“按功能文件夹”结构,则为名为“Reporting”的功能文件夹。 (2认同)
  • @Baspa 不,一个普通的 PHP 类。 (2认同)

Mah*_*alt 22

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

Laravel 5兼容方法

return \App::call('bla\bla\ControllerName@functionName');
Run Code Online (Sandbox Code Playgroud)

注意:这不会更新页面的URL.

最好是调用Route而让它调用控制器.

return \Redirect::route('route-name-here');
Run Code Online (Sandbox Code Playgroud)

  • 为什么不推荐呢? (5认同)
  • 调用控制器操作与重定向不同,因此它不是“更好”。 (2认同)

Mar*_*ean 13

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

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

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


小智 8

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

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

案例1)如果你想根据类调用

方式1)简单的方法

但是你不能用这种方式进行任何参数或认证.

app(\App\Http\Controllers\PrintReportContoller::class)->getPrintReport();
Run Code Online (Sandbox Code Playgroud)

方式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 ...
    }
}
Run Code Online (Sandbox Code Playgroud)

案例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 ...
    }
}
Run Code Online (Sandbox Code Playgroud)

然而,这也不是"好"的解决方案.

方式2)使用guzzlehttp客户端

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

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

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


Jay*_*arz 8

这种方法也适用于控制器文件的相同层次结构:

$printReport = new PrintReportController;

$prinReport->getPrintReport();
Run Code Online (Sandbox Code Playgroud)


小智 7

\App::call('App\Http\Controllers\MyController@getFoo')
Run Code Online (Sandbox Code Playgroud)

  • 尽管您的答案可能是正确的,但将它扩展一点并提供更多解释会更好. (9认同)

Ahm*_*oud 6

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();   
    }
   }
Run Code Online (Sandbox Code Playgroud)

  • 请使用更多信息进行编辑。不鼓励只使用代码和“试试这个”的答案,因为它们不包含可搜索的内容,并且没有解释为什么有人应该“试试这个”。 (9认同)