I'm attempting to implement something that sort of resemble the the repository pattern. To do this I have a interface that all repos implement and a model base class that all models extend.
I get the following error message from PHP
Fatal error: Declaration of MVCBP\Repositories\UserRepository::add() must be compatible with MVCBP\Core\RepositoryInterface::add(MVCBP\Core\Model $model) in D:\wamp\www\mvc\MVCBP\Repositories\UserRepository.php on line 9
What I want is that my methods in the repository classes should accept an instance of Model as argument according to the Interface. However I want to type hint a specific Model in the implementation. Is this doable in PHP?
RepositoryInterface.php
<?php
namespace MVCBP\Core;
use MVCBP\Core\ModelInterface;
interface RepositoryInterface
{
public function add(ModelInterface $model);
}
UserRepository.php
<?php
namespace MVCBP\Repositories;
use MVCBP\Core\PDOMySQL;
use MVCBP\Core\RepositoryInterface;
use MVCBP\Models\User;
class UserRepository extends PDOMySQL implements RepositoryInterface
{
public function add(User $user)
{
//Omitted
}
//Omitted
}
ModelInterface.php
<?php
namespace MVCBP\Core;
interface ModelInterface {}
User.php
<?php
namespace MVCBP\Models;
use MVCBP\Core\ModelInterface;
use MVCBP\Core\Validate;
use MVCBP\Repositories\UserRepository;
require_once(__DIR__ . '/../lib/password.php');
class User implements ModelInterface
{
//Omitted
}
You can do that. You must modify your UserRepository definition. Your add
method accept only MVCBP\Core\Model
instances.
UserRepository.php
<?php
namespace MVCBP\Repositories;
use MVCBP\Core\PDOMySQL;
use MVCBP\Core\RepositoryInterface;
//There was another mistake. Your User class is in MVCBP\Models namespace;
//use MVCBP\Core\Models\User; -> wrong one
use MVCBP\Models\User; //correct one
use MVCBP\Core\Model;
class UserRepository extends PDOMySQL implements RepositoryInterface
{
public function add(Model $user)
{
if (!$user instanceof User)
throw new \Exception('Exception msg', 101); //example exception
//Omitted
}
//Omitted
}
I prefer to require an interface instance ie.
public function add(SomeInterface $user)
{
if (!$user instanceof User)
throw new \Exception('Exception msg', 101); //example exception
}
class User implements SomeInterface {
//some code
}
And then ReposituryInterface.php looks like this:
<?php
namespace MVCBP\Core;
use MVCBP\Core\Model;
use MVCBP\Core\SomeInterface;
interface RepositoryInterface
{
//We must change method definition so it can take SomeInterface implementation
public function add(SomeInterface $model);
public function find($id);
public function edit(Model $model);
public function remove($id);
public function all();
}