Create a interface
basis that will serve as contract for all other Repository classes bases of your program, example:
<?php namespace App\Repositories\Base;
interface IRepositoryBase
{
public function create(array $data);
public function edit(array $data, $id);
public function find($id);
public function all();
public function delete($id);
}
With that interface
create your abstract class based on the basic commands of a CRUD
:
<?php namespace App\Repositories\Base;
use Illuminate\Database\Eloquent\Model;
abstract class RepositoryBase implements IRepositoryBase
{
protected $model;
public function __construct($model)
{
if (($model instanceof Model) === false)
throw new \Exception("Model is invalid");
$this->model = $model;
}
public function create(array $array)
{
return $this->model->create($array);
}
public function edit(array $array, $id)
{
$m = $this->find($id);
if ($m)
{
$m->fill($array);
if ($m->save()) return $m;
}
return null;
}
public function find($id)
{
return $this->model->find($id);
}
public function delete($id)
{
$m = $this->find($id);
if ($m) return $m->delete();
return false;
}
public function all()
{
return $this->model->all();
}
}
This code will be used by all its entity classes, i.e., for each entity (Illuminate\Database\Eloquent\Model
) will possess an abstract base class and another concrete for its instacing, examples:
User
Model User
<?php namespace App\Models;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
protected $table = "users";
protected $fillable = ['name', 'email', 'password'];
protected $hidden = ['password', 'remember_token'];
}
Abstract base class:
<?php namespace App\Repositories\Base;
use App\Models\User;
abstract class RepositoryUserBase extends RepositoryBase implements IRepositoryBase
{
public function __construct(User $model)
{
parent::__construct($model);
}
}
Concrete class:
<?php namespace App\Repositories;
use App\Repositories\Base\RepositoryUserBase;
class RepositoryUser extends RepositoryUserBase
{
}
Notice
Model Notice
<?php namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Notice extends Model
{
protected $table = "notices";
protected $primaryKey = "id";
protected $fillable = ['title'];
}
Abstract base class:
<?php namespace App\Repositories\Base;
use App\Models\Notice;
abstract class RepositoryNoticeBase extends RepositoryBase implements IRepositoryBase
{
public function __construct(Notice $model)
{
parent::__construct($model);
}
}
Concrete class:
<?php namespace App\Repositories;
use App\Repositories\Base\RepositoryNoticeBase;
class RepositoryNotice extends RepositoryNoticeBase
{
}
Note that the constructor of the Base classes RepositoryNoticeBase
and RepositoryUserBase
is being passed its class corresponds, respectively, Notice
and User
and all code made in the base is equal to its spelling and standardization, but internally belongs to its configuration of Model
which is configured in the constructor of each base class and belongs to its particular table, so for each new Repository created this which is changes from one to the other and also the names of the classes which must follow the same logic that the two followed. This ensures no repetition of coding that is in your question, of course, also this model can be further improved, this would be an initial standard.
So that the Container
and Dependency Injection is set open the file in the folder app\Providers\AppServiceProvider.php
and configure as follows in the method register()
:
<?php namespace App\Providers;
use App\Repositories\Base\RepositoryNoticeBase;
use App\Repositories\Base\RepositoryUserBase;
use App\Repositories\RepositoryNotice;
use App\Repositories\RepositoryUser;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
public function boot()
{
}
public function register()
{
//
app()->singleton(RepositoryNoticeBase::class, RepositoryNotice::class);
app()->singleton(RepositoryUserBase::class, RepositoryUser::class);
}
}
Why do this?
For injection to work in the manufacturers or methods of the controller
of its application, example:
<?php namespace App\Http\Controllers;
use App\Repositories\Base\RepositoryNoticeBase;
use App\Repositories\Base\RepositoryUserBase;
use Illuminate\Http\Request;
class TestController extends Controller
{
private $notice;
private $user;
private $request;
public function __construct(
RepositoryNoticeBase $notice,
RepositoryUserBase $user,
Request $request)
{
$this->notice = $notice;
$this->user = $user;
$this->request = $request;
}
public function index()
{
return $this->user->all();
}
}
Observing: if you do not want to do this part just put the direct concrete class in the constructors or methods instead of the base classes, example:
<?php namespace App\Http\Controllers;
use App\Repositories\Base\RepositoryNoticeBase;
use App\Repositories\Base\RepositoryUserBase;
use Illuminate\Http\Request;
class TestController extends Controller
{
private $notice;
private $user;
private $request;
public function __construct(
RepositoryNotice $notice,
RepositoryUser $user,
Request $request)
{
$this->notice = $notice;
$this->user = $user;
$this->request = $request;
}
public function index()
{
return $this->user->all();
}
}
which will have the same effect.
Reference:
I face would not do a extends in Model that I think wrong by repeating all the codes you will do in the other classes.
– novic
@Virgilionovic, what do you suggest? Since I want to avoid calling in the controller s the models, so I’m separating the responsibilities, in services and repositories.
– Williams
I’ll propose an example with repository to see if you understand this part !!!
– novic