Подтвердить что ты не робот

Метод контроля доступа от другого контроллера в Laravel 5

У меня есть два контроллера SubmitPerformanceController и PrintReportController.

В PrintReportController у меня есть метод под названием getPrintReport.

Как получить доступ к этому методу в SubmitPerformanceController?

4b9b3361

Ответ 1

Вы можете получить доступ к своему методу контроллера следующим образом:

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)

Подробнее о чертах вы можете прочитать здесь.

Ответ 2

Если вам нужен этот метод в другом контроллере, это означает, что вам нужно абстрагироваться от него и сделать его многоразовым. Переместите эту реализацию в класс службы (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
  }
}

Сделайте то же самое для других контроллеров, где вам нужна эта реализация. Приобретение методов контроллера из других контроллеров - это запах кода.

Ответ 3

Вызов контроллера из другого контроллера не рекомендуется, однако если по какой-либо причине вы должны это сделать, вы можете сделать это:

совместимый с Laravel 5 метод

return \App::call('bla\bla\[email protected]');

Примечание. это не приведет к обновлению URL-адреса страницы.

Лучше называть Route вместо этого и позволить ему вызвать контроллер.

return \Redirect::route('route-name-here');

Ответ 4

Вы не должны. Его анти-шаблон. Если у вас есть метод в одном контроллере, который вам нужен для доступа к другому контроллеру, то это знак, который вам нужно изменить.

Рассмотрим перефакторинг метода в классе обслуживания, который затем можно создать в нескольких контроллерах. Поэтому, если вам нужно предлагать отчеты о печати для нескольких моделей, вы можете сделать что-то вроде этого:

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

Ответ 5

Прежде всего, запрос метода контроллера от другого контроллера - ЗЛО. Это вызовет множество скрытых проблем в жизненном цикле 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-запрос) Более подробную информацию о методе 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 Webserver должен быть запущен.

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

Наконец, я использую способ 1 из случая 2. Мне нужны параметры и

Ответ 7

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

Ответ 8

Здесь эта черта полностью эмулирует управляемый контроллер маршрутизатором laravel (включая поддержку middlewares и инъекции зависимостей). Протестировано только с версией 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');
    }
}

Ответ 9

Поздний ответ, но я долго искал это. Теперь это возможно очень простым способом.

Без параметров

return redirect()->action('[email protected]');

с параметрами

return redirect()->action('[email protected]', ['id' => 1]);

Документы: https://laravel.com/docs/5.6/responses#redirecting-controller-actions

Еще в 5.0 для этого требовался весь путь, теперь все намного проще.

Ответ 10

Вы можете использовать статический метод в 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();

    }

}

Ответ 11

Вы можете получить доступ к контроллеру, создав его экземпляр и вызвав doAction: (поместите use Illuminate\Support\Facades\App; перед объявлением класса контроллера)

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

Также обратите внимание, что при этом вы не будете запускать какое-либо промежуточное программное обеспечение, объявленное на этом контроллере.