3

I have a base class called ProductRepository and there are other classes which extends it; such as PushProductRepository or SocialProductRepository.

class ProductRepository implements ProductRepositoryInterface
{
    private $product;

    public function __construct(Product $product)
    {
        $this->product = $product;
    }

    public function create($name, $language, $type)
    {
        $this->product->create([
            'name' => $name,
            'language' => $language,
            'type' => $type
        ]);
    }
}

As you can see there is a type parameter in create function. It may be the values such as 'push' or 'social'. It will take the value from the classes which extends it. Instead of sending it as a parameter; I want to have a different approach. I will create a property in ProductRepository such as type and use $this->type in create function.

But I want to be sure that every class that extends ProductRepository should set this property in it's own class (probably in it's constructor)

How can I be sure that every class that extends ProductRepository will set type in it's constructor ? Is there any better way to achieve this? Is this violates anything? If it is so, how can i prevent it ?

1 Answer 1

3

Without delving into whether it's good or bad approach and just answering the question how?, I would make ProductRepository abstract, with abstract getType() method. So it would look like the following:

abstract class ProductRepository
{
    private $product;

    public function __construct(Product $product)
    {
        $this->product = $product;
    }

    public function create($name, $language, $type)
    {
        $this->product->create([
            'name' => $name,
            'language' => $language,
            'type' => $this->getType()
        ]);
    }

    abstract protected function getType();
}

As far as I can tell, type has something to do with a product itself, that is, with domain, so I would discourage building this logic in repository. What about creating a product with specific type property? It looks way cleaner for me -- at least domain logic resides in domain. And I don't understand why create method belongs to product. Probably you should have ProductRepository looking like that:

class ProductRepository
{
    private $dataStorage;

    public function __construct(DataStorage $dataStorage)
    {
        $this->dataStorage = $dataStorage;
    }

    public function add(Product $product)
    {
        $this->dataStorage
            ->insert(
                $product->getName(),
                $product->getLanguage(),
                $product->getType()
            )
        ;
    }
}
4
  • Product is a model (orm) and in that case create method is it's own method. What should i do when i need to instantiate ProductRepository ?
    – Ersoy
    Commented Dec 27, 2017 at 20:09
  • Um, what ORM are you using? I just can't realize why on Earth you need to call create method on an entity, and moreover, pass the entities properties as arguments. Why, if you already have them within that entity? Commented Dec 28, 2017 at 7:19
  • > What should i do when i need to instantiate ProductRepository ? Typically you need some DAL (like Doctrine's), or just PDO. Commented Dec 28, 2017 at 7:22
  • It is eloquent (laravel) and model is injected and it doesn’t have a knowledge about it’s properties, so i don’t have them in my model. When i said about instantiating i mean I can’t instantiate an abstract class if i turn it into concrete one then I can’t use abstract method ?
    – Ersoy
    Commented Dec 31, 2017 at 7:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.