简体   繁体   中英

Laravel repository pattern explanation

I'm working in my Laravel 5.4 project with the Repository Pattern (I'm quite new to that pattern). I've red a lot about this on the web but I still have two important questions:

> Question #1:

Imagine I use Laravel ORM Eloquent and I have a interface that looks like this:

<?php

namespace App\Repositories\User;

interface UserRepoInterface
{
    /**
     * @param array $user
     */
    public function update(array $request, User $user);
}

You can see that I have specified the eloquent User model like a parameter.

The eloquent implementation looks like this:

public function update(array $request, User $user)
{
    $user->name             = $request['name'];
    $user->last_name        = $request['last_name'];
    $user->email            = $request['email'];
    $toUpdate->save();
}

So my question:

Is it wrong to hardcode the eloquent User model in my interface? In lots of examples on the web I see people doing this but what If I want to swap the eloquent implementation with a file based implementation? That's a problem because I have to pass a User model to the update method!

What is the solution to this problem should I only declare $user instead of User $user ?

> Question #2:

How should I handle pagination?

For example in my eloquent UserRepository I've a method that looks like this:

public function index()
{
    return User::orderBy('name', 'asc')
        ->withCount('messages')
        ->with('corporation')
        ->paginate(10);
}

Is this wrong? Should I only paginate in my controller?

A good explanation would help me a lot.

Question 1

Laravel uses ActiveRecord as pattern to its models + data access layer.

This pattern has as objective make things easier and faster. When you use a Repository pattern, you are kind of running away from that.

To use for real the repository pattern, you would have to create data transfer objects, DAT (in java they call it POJO). And then, use the Eloquent entity just as an Entity Manager.

POPO

class User {

  private $id;
  private $a;

  public setId ($id) { $this->id = $id; } 
  public getId () { return $this->id; } 

  public setA ($a) { $this->a = $a; } 
  public getA () { return $this->a; } 
}

Entity Manager

class UserEloquent extends Eloquent {
   protected $_table = 'user';
}

Repository

class EloquentUserRepository implements UserReposistory {
   private $em;

   public __constructor (UserEloquent $em) { $this->em = $em; }

   public update (User $dat) {
     $user  = $em->find($dat->getId());
     $user->a = $dat->getA();
     $user->save();
   }
}

Can you see how verbose would it be? If you really want to use this approach, I recommend you to use Doctrine .

But if you want to use ActiveRecord as it is, I recommend you to see some ruby on rails projects! They are really good in this pattern :)

Now what I really think: make what is good for the project. Make it simple, think with your team and build the best practices for you. Don't use always the same pattern because someone told you.

If the project is small and fast, use what the framework gives you (I'm not saying to relax and make bad code). If it's a big project, with a lot of developers in the team and you know that eventually you may want to change your Data Access Layer, think about Repository Pattern.

Of course sometimes we can take wrong architecture decisions, but it is how we learn! And keep reading about patterns, I think you are following a good path to be a great Architect :)

Question 2

It depends in what you've decided above. If its Eloquent using ActiveRecord as it is, doesn't matter where to call it (Controller or some middle class). Just follow some pattern. If you call in Controller always do it in Controller. Else you'll get lost in your code.

Using Repository, I think inside the repository it is fine :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM