3
\$\begingroup\$
<?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:

  1. I have two models (User and Company) and the relationship between the two is many-to-many
  2. The relationship is enabled via a pivot table (user_company)
  3. 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.
  4. Company's logo can be replaced with a new one.

My issue / what I am unsure of is;

  1. Is it okay that I use Auth::User in this repository? or should the logic of loading user's myCompany be put in UserRepository?
  2. Is it okay for me to use another repository (e.g. imageUploaderRepository) in this repository?
  3. Should controller be the one to orchestrate the logo uploading and not mix the operation in the company repo?
  4. 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:

And the other two repositories i am using in CompanyInterface:

Lastly, the two related models:

\$\endgroup\$
6
  • \$\begingroup\$ Are you able to include the implementation for the Company Model class? \$\endgroup\$ Apr 22, 2018 at 2:46
  • \$\begingroup\$ @SamOnela sure, question has been updated. \$\endgroup\$
    – Latheesan
    Apr 22, 2018 at 11:47
  • 1
    \$\begingroup\$ Since you are using laravel you could do collect($validated)->map(function($val, $key) use($company){$company->$key = ($key != "opening_times"? $val : json_encode($val));}); \$\endgroup\$ Apr 24, 2018 at 14:06
  • \$\begingroup\$ Whit that you avoid all those repetitive lines in the upsert function \$\endgroup\$ Apr 24, 2018 at 14:07
  • \$\begingroup\$ Just, forget about repository pattern, look at the code your are returning Eloquent instance of Company, what good is that? You need to return array or some other object but not Eloquent* you defeat the purpose. Whole repository pattern is just big fuss in Laravel community. Good luck! :) \$\endgroup\$
    – Kyslik
    May 9, 2018 at 7:54

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Browse other questions tagged or ask your own question.