<?php
namespace App\Repositories;
use App\Contracts\{
CompanyInterface,
ImageUploaderInterface
};
use App\Models\Company;
use Illuminate\Support\Facades\Auth;
class CompanyRepository implements CompanyInterface
{
protected $imageUploaderRepository;
public function __construct(ImageUploaderInterface $imageUploaderRepository)
{
$this->imageUploaderRepository = $imageUploaderRepository;
}
public function myCompany(): Company
{
$companies = Auth::user()->companies;
if ($companies && $companies->count() > 0) {
return $companies->first();
}
return new Company();
}
public function upsert(Company $company, array $validated): Company
{
$company->name = $validated['name'];
$company->address_number = $validated['address_number'];
$company->address_street = $validated['address_street'];
$company->address_city = $validated['address_city'];
$company->address_region = $validated['address_region'];
$company->address_postcode = $validated['address_postcode'];
$company->address_country = $validated['address_country'];
$company->address_geolocation = $validated['address_geolocation'];
$company->contact_number = $validated['contact_number'];
$company->contact_email = $validated['contact_email'];
$company->fax_number = $validated['fax_number'];
$company->opening_times = json_encode($validated['opening_times']);
$company->timezone = $validated['timezone'];
if (array_key_exists('logo', $validated)) {
$this->imageUploaderRepository->deleteIfExists($company->logo);
$company->logo = $this->imageUploaderRepository->uploadCompanyLogo($validated['logo']);
}
$company->save();
if ($company->wasRecentlyCreated) {
$company->user()->attach(Auth::user());
}
return $company;
}
}
This works as expected, however I am not entirely sure if what I have done adheres to S.O.L.I.D principles and infact a good implementation of repository pattern.
Given the contexts:
- I have two models (
User
andCompany
) and the relationship between the two is many-to-many - The relationship is enabled via a pivot table (
user_company
) - At the moment, a user can only have one company, later I will be making it possible for a user to own more than one company.
- Company's logo can be replaced with a new one.
My issue / what I am unsure of is;
- Is it okay that I use Auth::User in this repository? or should the logic of loading user's
myCompany
be put inUserRepository
? - Is it okay for me to use another repository (e.g.
imageUploaderRepository
) in this repository? - Should controller be the one to orchestrate the logo uploading and not mix the operation in the company repo?
- Is it okay that I do the many-to-many linking (via
attach
) in this repo? or should the controller do it?
P.S. this is how I use the repo in my controller:
public function save(SaveCompanyRequest $request)
{
$company = $this->companyRepository->myCompany();
$validated = $request->validated();
$this->companyRepository->upsert($company, $validated);
return redirect()
->back()
->with('status', 'Company details updated.');
}
And here are my interfaces:
- Contracts\CompanyInterface - https://pastebin.com/sF1izT4D
- Contracts\DateTimeInterface - https://pastebin.com/8BH9pUdQ
- Contracts\ImageUploaderInterface - https://pastebin.com/WJFQy0SK
And the other two repositories i am using in CompanyInterface:
- Repositories\DateTimeRepository - https://pastebin.com/8xCAX00p
- Repositories\ImageUploaderRepository - https://pastebin.com/XXuECLSD
Lastly, the two related models:
- Models\User - https://pastebin.com/YCw1rGZL
- Models\Company - https://pastebin.com/cu54xknR
Company
Model class? \$\endgroup\$collect($validated)->map(function($val, $key) use($company){$company->$key = ($key != "opening_times"? $val : json_encode($val));});
\$\endgroup\$upsert
function \$\endgroup\$