2

I have the following Code:

Controller

class UserController {
    
    public function __construct(userRepository $userRepository) {
        $this->userRepository = $userRepository;
    }
[...]

Repository

class UserRepository extends AbstractRepository {

    public function getTablename() {
        return "tbl_users";
    }

    public function getModel() {
        return "administration\\CMR\\UserModel";
    }
[...]

AbstractRepository

abstract class AbstractRepository {
    
    protected $pdo;

    public function __construct(PDO $pdo) {
        $this->pdo = $pdo;
    }
    
    abstract public function getTablename();
    abstract public function getModel();
    
    function readAll() {
        
        $table = $this->getTablename();
        $model = $this->getModel();
        
        $stmt = $this->pdo->query("SELECT * FROM $table");
        $res = $stmt->fetchAll(PDO::FETCH_CLASS, $model);
        return $res;
    }
[...]

My Problem is, that I need the "tbl_users" for one query and a secound table (tbl_locations) for another query. Could anyone please explain how to do this? I think it's unnecessary to write again the same readAll()-Function only with other variable.

TheQuestionmark
  • 69
  • 1
  • 10
  • 1
    If you have a `tbl_locations` table, then you should have a corresponding `LocationRepository` as well. So use that to get whatever Location model instances you need to get access to at this point. (Btw. your table names should use the singular, not plural.) – CBroe Apr 07 '22 at 08:43

2 Answers2

2

Start by adding location repository

class LocationRepository extends AbstractRepository implements LocationRepositoryInterface {

    public function getTablename() {
        return "tbl_locations";
    }

    public function getModel() {
        return "administration\\CMR\\LocationModel";
    }
[...]

and put both repositories to upper layer, say UserLocationService.

class UserLocationService implements UserLocationInterface {
    public function __construct(
        protected UserRepositoryInterface $userRepository,
        protected LocationRepositoryInterface $locationRepository
    ) {
    }

[...]
}

This way you have separate repositories for users and locations, yet you can operate on both, in Service that does require both repositories to fulfill its' logic.

yergo
  • 4,761
  • 2
  • 19
  • 41
  • Thanks for the answer. I think this is the solution, but I dont understand it completely. What is "LocationRepositoryInterface"? Could you please write down the complete Code? I'm a blodly beginner and learn to manage OOP and MVC. If you need more code to help, please let me know. – TheQuestionmark Apr 08 '22 at 22:32
  • 1
    @TheQuestionmark your code does not look like totally beginner. Interface is a description of a class how it should look like and can be used for enforcing types. You can remove the interface part from the code, and where it is required, replace it with its solid class implementation. Eg. replace UserRepositoryInterface with UserRepository – yergo Apr 09 '22 at 19:45
-1

If I understand correctly, you want to be able to set the tablename to your likings. One possibility is to pass a tablename in the UserRepository constructor (and set a default), like this:

class UserRepository extends AbstractRepository {

    public function getTablename() {
        return $this->tablename;
    }

    public function getModel() {
        return "administration\\CMR\\UserModel";
    }
    [...]



abstract class AbstractRepository {
    
    protected $pdo;
    protected $tablename;

    public function __construct(PDO $pdo, string $tablename = "tbl_users") {
        $this->pdo = $pdo;
        $this->tablename = $tablename;
    }
    
    abstract public function getTablename();
    abstract public function getModel();
    
    function readAll() {
        
        $table = $this->getTablename();
        $model = $this->getModel();
        
        $stmt = $this->pdo->query("SELECT * FROM $table");
        $res = $stmt->fetchAll(PDO::FETCH_CLASS, $model);
        return $res;
    }
    [...]
Jos
  • 1,387
  • 1
  • 13
  • 27
  • The whole idea of OOP breakdown is to incapsulate subtle implementation details in order to simplify APIs, switching UserRepository silently to another table might seem like a good-KISS-idea, but actually it makes this abstraction leaking, which in turn opens path to all sorts of hard to trace bugs, hardens effective testing and reuse. – shomeax Apr 08 '22 at 09:27