The following code represents the store method of a resource controller.
A user can create an training offer on my website and can pass various information like website
, trainers
, date
, title
, address
, videos
and also upload a coverImage
and multiple images for a gallery
.
The following steps are conducted:
- Validate the input in
StoreTraining
- Parse the input from user in
ParseStoreTraining
- Create the training model in
TrainingRepository
- Upload cover image in
TrainingRepository
- Upload gallery in
MediaRepository
- Create relationships for training model (this is a hasManyThrough relation for
gallery
andvideo
) inMediaRepository
.
Here comes the store method from the TrainingsController
.
public function store(StoreTraining $request)
{
\App\Repositories\TrainingRepository::create($request);
return view('home.training.show');
}
The StoreTraining
is a FormRequest
that handles the validation:
class StoreTraining extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'addressid' => 'required',
'trainer' => 'required',
'dates' => 'required',
'mode' => 'required',
];
}
}
The TrainingRepository
class handles the creation of the training.
class TrainingRepository
{
public static function create(Request $request)
{
$parsedRequest = new ParseStoreTraining($request);
$profileTraining = ProfileCalender::create($parsedRequest->all());
// Upload Image
if (!empty($request->file('coverImage'))) {
$path = Storage::disk('public')->putFile('trainings/' . $profileTraining->id, $request->file('coverImage'));
$profileTraining->cover_image = $path;
$profileTraining->save();
}
// Update relations
$mediaRepository = new MediaRepository($profileTraining);
if (!empty($request->gallery)) {
$mediaRepository->addGalleryToTraining($request->gallery);
}
if (!empty($request->video_url)) {
$mediaRepository->addVideo($request->video_url);
}
}
}
The ParseStoreTraining
request converts the input to be useable for the ProfileCalender::create
method:
class ParseStoreTraining
{
private $request;
private $trainerA;
private $trainerB;
private $institute_id;
private $beginn_date;
public function __construct(FormRequest $request)
{
$this->request = $request;
$this->identifyTrainer();
$this->identifyInstitute();
$this->identifyDate();
}
public function all(): array
{
return [
'idAddress' => $this->request->addressid,
'trainerA' => $this->trainerA,
'trainerB' => $this->trainerB,
'beginnDate' => $this->beginn_date,
'mode_id' => $this->request->mode,
'idInstitute' => $this->institute_id,
'viewable' => false,
'idOrga' => getOrga(),
'title' => $this->request->title,
'coreArea' => $this->request->focus,
'url' => $this->request->website,
'price' => $this->request->price,
'description' => $this->request->description,
];
}
private function identifyTrainer(): void
{
if (is_array($this->request->trainer)) {
$this->trainerA = $this->request->trainer[0];
$this->trainerB = $this->request->trainer[1] ?? null;
return;
}
$this->trainerA = $this->request->trainer;
$this->trainerB = null;
}
private function identifyInstitute(): void
{
$this->institute_id = \Auth::user()->getInstituteId();
if (empty($this->institute_id)) {
throw new \Exception('User has no related institute id', 1);
}
}
private function identifyDate(): void
{
// Convert JS Date to MYSQL Timestamp
$cleanDate = preg_replace('/\(.*\)/', '', $this->request->dates);
$beginn_date = strtotime($cleanDate);
$this->beginn_date = date('Y-m-d', $beginn_date);
}
}
A training has many galleries
and videos
through a media
class. The MediaRepository
is responsible for creating these relations:
class MediaRepository
{
private $training;
public function __construct(ProfileCalender $training)
{
$this->training = $training;
}
public function addGalleryToTraining(array $images): void
{
if (empty($images)) {
return;
}
$media = $this->training->media()->create([
'institute' => false, // prevent duplicate images if user does not understand how to use gallery
]);
$gallery = $media->galleries()->create();
foreach ($images as $image) {
$image_path = Storage::disk('public')->putFile('trainings/gallery/' . $gallery->id . '/pictures', $image);
$avatar = \Image::make($image->getRealPath());
$avatar->fit(221, 146);
$avatar_path = 'trainings/gallery/' . $gallery->id . '/avatars/' . $image->hashName();
Storage::disk('public')->put($avatar_path, $avatar);
$gallery->images()->create([
'path_image' => $image_path,
'path_avatar' => $avatar_path,
]);
}
}
public function addVideo(String $url, String $name = null): void
{
$media = $this->training->media()->create([
'institute' => false, // prevent duplicate images if user does not understand how to use gallery
]);
$media->videos()->create([
'url' => $url,
'name' => $name,
]);
}
}
Any suggestions how I could improve the code?