I have an Offers class which is basically a seller which has specific skills, such as law knowledge.It needs a method isLawyer. Offers has a parent_cat_id column, which references the id of a Category.Here's Offers :<?phpnamespace App\Models;use App\Services\CategoryService\AbstractCategory;use LogicException;class Offers{    /** @var AbstractCategory $category */    private $categoryService;    public function isLawyer(): bool    {        return $this->getCategoryService()->isLawyer($this->getParentCatId());    }    public function setParentCatId(int $catId)    {        $this->parent_cat_id = $catId;    }    public function getParentCatId(): int    {        return (int)$this->parent_cat_id;    }    public function setCategoryService(AbstractCategory $categoryService)    {        $this->categoryService = $categoryService;    }    public function getCategoryService(): AbstractCategory    {        if (is_null($this->categoryService)) {            throw new LogicException('Category service should be set beforehand.');        }        return $this->categoryService;    }}AbstractCategory is an abstract class that different categories will extend. I don't care about the implementation of this as of now.Now in tests, it's all good and fun :/** @test */public function is_lawyer_defers_to_category_is_lawyer_method(){    $category = Mockery::mock(AbstractCategory::class);    $category->shouldReceive('isLawyer')->once()->with(1)->andReturn(true);    $offer = new Offers;    $offer->setParentCatId(1);    $offer->setCategoryService($category);    $this->assertTrue($offer->isLawyer());}But as for the real implementation, it gets tricky, as I have 3-4 layers before I'm using $offers->isLawyer().<?phpnamespace App\Models\Product\Chat;use App\Models\Offers;class Chat{    /** @var Offers $offer */    private $offer;    /**     * @param Offers $offers     */    public function setOffer(Offers $offers)    {        $this->offer = $offers;    }    /**     * @return Offers     */    public function getOffer()    {        return $this->offer;    }    /**     * @return bool     */    public function byLawyer(): bool    {        return $this->getOffer()->isLawyer();    }}Chat uses isLawyer of Offers, but byLawyer is itself called by something else.I still need to set the AbstractCategory before I use this method.So, should I pass it through as a parameter to every step ? This sounds ridiculous.Should I setup Offers and set the AbstractCategory even before it's assigned to the Chat ?Should I give up and instantiate a new Category right in the Offers class ? Setting the abstraction felt like a better design.Thanks.
Setter use for dependency injection, passing interface through too many layers
php;object oriented;dependency injection