Большинство моих контроллеров в laravel выглядят одинаково
Пример:
class CourseController extends Controller
{
public function index(Request $request)
{
$courses = Course::query();
$courses = $this->commonIndex($courses, $request);
return CourseResource::collection($courses);
}
public function store(StoreCourseRequest $request)
{
$course = Course::create($request->validated);
return CourseResource::make($course);
}
public function show(Request $request, Course $course)
{
return CourseResource::make($course);
}
public function update(UpdateCourseRequest $request, Course $course)
{
$course->update($request->validated());
return CourseResource::make($course);
}
public function destroy(Course $course)
{
$course->delete();
return response()->noContent();
}
}
Я хотел бы создать общий контроллер, который расширяется всеми простыми контроллерами и передает Model
, FormRequest
и Resource
как общедоступные переменные, примерно так.
class CommonController extends BaseController
{
use AuthorizesRequests, ValidatesRequests;
public $model;
public $resource;
public $storeFormRequest;
public $updateFormRequest;
public function index(Request $request)
{
$model = new $this->model;
$resource = new $this->resource($request);
$data = $model->query();
return $resource->collection($data);
}
public function show(Request $request, string $id)
{
$model = new $this->model;
$resource = new $this->resource($request);
$data = $model->find($id);
return $resource->make($data->load($loadWith));
}
public function store(Request $request)
{
$model = new $this->model;
$resource = new $this->resource($request);
$request = new $this->storeFormRequest($request->toArray());
$validated = $request->validated();
$data = $model->create($validated);
return $resource->make($data);
}
}
Я не знаю, как лучше всего передать общедоступные переменные конструктору и оценить их.
Также я столкнулся с проблемой, когда new $this->storeFormRequest($request->toArray())
оценивается как ноль.
$storeFormRequest
— это стандартный Laravel FormRequest
class StoreCourseRequest extends FormRequest
{
public function authorize(): bool
{
return true;
}
public function rules(): array
{
return [
'name' => 'required|string',
'description' => 'required|string',
'language_id' => 'required|exists:languages,id',
'image' => 'array',
];
}
}
Вот как я использую CommonController
class CourseController extends CommonController
{
public $model = Course::class;
public $resource = CourseResource::class;
public $storeFormRequest = StoreCourseRequest::class;
public $updateFormRequest = StoreCourseRequest::class;
}
@Mohammadsiabbou извините за то, что я использовал черту под названием CommonController, которая отличается от контроллера, я удалил ее из своего вопроса
Я бы порекомендовал сделать базовый класс абстрактным с помощью сеттеров, для второго вопроса $request->toArray()
, можете ли вы отладить больше и предоставить более подробную информацию об этом.
В целом, если ваша реализация контроллера базового класса работает так, как вы хотите, следуйте правилу «если он не сломан, не чините его»;)
Было сказано, что...
Я не знаю, как лучше всего передать общедоступные переменные конструктору и оценить их.
Поскольку вам не требуется доступ к переменным-членам извне класса, вы можете их создать protected
; нет необходимости в функциях «установщика».
class CommonController extends BaseController
{
use AuthorizesRequests, ValidatesRequests;
protected $model;
protected $resource;
protected $storeFormRequest;
protected $updateFormRequest;
...
}
class CourseController extends CommonController
{
protected $model = Course::class;
protected $resource = CourseResource::class;
protected $storeFormRequest = StoreCourseRequest::class;
protected $updateFormRequest = StoreCourseRequest::class;
}
Вы можете немного привести в порядок методы CommonController
, используя статические методы там, где они доступны.
Например, вместо этого:
$model = new $this->model;
...
$data = $model->find($id);
сделай это:
$data = ($this->model)::find($id);
Если бы это был я, я бы сделал следующее:
Сначала я бы определил CommonController
как абстрактный класс, а затем добавил четыре абстрактных метода для получения соответствующего имени класса обработки.
abstract protected function GetModel(): string;
abstract protected function GetResource(): string;
abstract protected function GetStoreFormRequest(): string;
abstract protected function GetUpdateFormRequest(): string;
Затем я реализую в подклассе четыре метода для возврата имени класса.
protected function GetModel(): string
{
return Course::class;
}
Почему? Использование абстрактных методов ограничивает возможность их реализации каждым подклассом. Это всего лишь мое личное мнение, я не думаю, что на этот вопрос есть правильный ответ.
Вы написали
use CommonController;
значит это должно быть чертой характера? или вы хотите это как класс ??