Wzorzec Repository w Laravelu

0

Witam serdecznie,
Robię projekt z wykorzystaniem Laravela 5.8.

Mam następujący kod:

1.BaseRepository:

abstract class BaseRepository implements RepositoryInterface
  {

      protected $model;

      public function getAll(string $order = 'id', string $by = 'desc')
      {
          return $this->model->orderBy($order, $by)->get()->appends(request()->query());
      }

      public function getAllWithPaginate(string $order = 'id', string $by = 'desc', int $perPage = 1)
      {
          return $this->model->orderBy($order, $by)->paginate($perPage)->appends(request()->query());
      }

      public function with($relations)
      {
          return $this->model->with($relations);
      }

      public function create(array $data)
      {
          return $this->model->create($data);
      }

      public function save(array $data): int
      {
          $model = $this->model->create($data);
          return $model->id;
      }

      public function update(array $data, int $id)
      {
          return $this->model->where("id", "=", $id)->update($data);
      }

      public function delete(int $id)
      {
          return $this->model->destroy($id);
      }

      public function find(int $id, string $order, string $by)
      {
          return $this->model->find($id)->orderBy($order, $by);
      }

      public function findOrFail(int $id, string $order, string $by)
      {
          return $this->model->findOrFail($id)->orderBy($order, $by);
      }

      public function getModel()
      {
          return $this->model;
      }

  }
  1. RepositoryInterface:

    interface RepositoryInterface
    {
        public function getAll(string $order, string $by);

        public function getAllWithPaginate(string $order, string $by, int $perPage);

        public function create(array $data);

        public function save(array $data);

        public function update(array $data, int $id);

        public function delete(int $id);

        public function find(int $id, string $order, string $by);

        public function findOrFail(int $id, string $order, string $by);

        public function getModel();
    }

3 AdRepository:


    class AdRepository extends BaseRepository
    {

        public function __construct(Ad $model)
        {
            $this->model = $model;
        }

        public function search(string $query, string $order = 'id', string $by = 'desc', int $perPage = 1)
        {
            return $this->model->where('title', 'LIKE', '%' . $query . '%')->orWhere('id', 'LIKE', '%' . $query . '%')->orWhere('content', 'LIKE', '%' . $query . '%')->orderBy($order, $by)->paginate($perPage)->appends(request()->query());
        }
    }

  1. Controller:
use App\Models\Ad;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Repositories\AdRepository;

    public function index(Request $request)
        {
            if($request->input('query') != ""){
                $adsList = $this->repository->with('author')->search($request->input('query'));
            } else{
                $adsList = $this->repository->with('author')->getAllWithPaginate();
            }

            return view('modules.ad.ad_list', ['adsList' => $adsList]);
        }

protected $model;

    public function __construct(AdRepository $repository)
    {
        $this->model = $repository;
    }


Kiedy uruchamiam mój kod, otrzymuję błąd:
Call to undefined method Illuminate\Database\Eloquent\Builder::getAllWithPaginate()

W jaki sposób mogę to naprawić?

0

$this->repository->with(...) zwraca instancję Model (już nie repozytorium!), na której potem próbujesz zrobić getAllWithPaginate(); ciężko powiedzieć jak to naprawić, ponieważ nie jest jasne, co próbujesz osiągnąć.

Jedno jest jednak pewne: cały ten kod jest nieprawidłowy - próbujesz na pałę wykorzystać wzorzec, którego nie rozumiesz (ew. kopiujesz kod od innych ludzi, którzy również tego wzorca nadużywają). Poczytaj sobie np. http://commitandrun.pl/2016/05/11/Repozytorium_najbardziej_niepotrzebny_wzorzec_projektowy/.

0
Patryk27 napisał(a):

$this->repository->with(...) zwraca instancję Model (już nie repozytorium!), na której potem próbujesz zrobić getAllWithPaginate(); ciężko powiedzieć jak to naprawić, ponieważ nie jest jasne, co próbujesz osiągnąć.

Jedno jest jednak pewne: cały ten kod jest nieprawidłowy - próbujesz na pałę wykorzystać wzorzec, którego nie rozumiesz (ew. kopiujesz kod od innych ludzi, którzy również tego wzorca nadużywają). Poczytaj sobie np. http://commitandrun.pl/2016/05/11/Repozytorium_najbardziej_niepotrzebny_wzorzec_projektowy/.

Przerabiam takie artykuły: https://medium.com/employbl/use-the-repository-design-pattern-in-a-laravel-application-13f0b46a3dce

tylko na tych przykładach mają np. return $this->model->all();

Mam np. ten model:


class Ad extends Model
{
    use scopeActiveTrait;

    protected $quarded = ['id'];
    protected $fillable = ['company_id', 'user_id', 'title', 'content', 'provincial_id', 'enable', 'url_address'];
    public $timestamps = true;

    public function author()
    {
        return $this->belongsTo('App\Models\User', 'user_id');
    }
}

I próbuję go według tego przykładu wyświetlić wraz z relacją autorzy:

$this->model->with('author')->getAllWithPaginate()

taka konstrukcja:
$this->model->with('author')->get()

działa bez problemu

0

Przerabiam takie artykuły

Przytoczony przez Ciebie artykuł prezentuje właśnie takie upośledzone, nikomu niepotrzebne repozytorium (choć wierzę, że autor miał dobre intencje); ogólnie: Active Record i repozytoria nie idą w parze, brak DDD i repozytoria nie idą w parze etc. Odsyłam do materiałów zalinkowanych przeze mnie oraz @mr_jaro, coby nie powtarzać argumentów.

Z ciekawości: dlaczego chciałeś zastosować u siebie akurat ten pattern?

taka konstrukcja:
$this->model->with('author')->get()
działa bez problemu

Tutaj wołasz ->get() na modelu, nie repozutorium, dlatego to działa.

Twój design (z "dynamicznym" ->with()) zwyczajnie nie nadaje się do wykorzystania w parze z repozytorium i nie przyniesie żadnej korzyści, ponad dodatkowym kodem do utrzymania.

0
Patryk27 napisał(a):

Przerabiam takie artykuły

Przytoczony przez Ciebie artykuł prezentuje właśnie takie upośledzone, nikomu niepotrzebne repozytorium (choć wierzę, że autor miał dobre intencje); ogólnie: Active Record i repozytoria nie idą w parze, brak DDD i repozytoria nie idą w parze etc. Odsyłam do materiałów zalinkowanych przeze mnie oraz @mr_jaro, coby nie powtarzać argumentów.

Z ciekawości: dlaczego chciałeś zastosować u siebie akurat ten pattern?

taka konstrukcja:
$this->model->with('author')->get()
działa bez problemu

Tutaj wołasz ->get() na modelu, nie repozutorium, dlatego to działa.

Twój design (z "dynamicznym" ->with()) zwyczajnie nie nadaje się do wykorzystania w parze z repozytorium i nie przyniesie żadnej korzyści, ponad dodatkowym kodem do utrzymania.

Dzięki za opinie :)

Gdyby ktoś szukał rozwiązania, to to działa poprawnie:

public function listWithPaginate(string $orderByColumn, string $orderBy = 'desc', array $with = [], array $columns = ['*'], int $perPage = 10)
    {
        return $this->model->with($with)
            ->orderBy($orderByColumn, $orderBy)
            ->paginate($perPage, $columns)->appends(request()->query());
    }

0 użytkowników online, w tym zalogowanych: 0, gości: 0