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
:
<?php
namespace 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()
.
<?php
namespace 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.
Offers
class which needs a methodisLawyer
— I'm having a hard time understanding what you are trying to accomplish here. What does an "Offers" object represent, and why would it be a lawyer or not? The whole situation makes no sense to me; perhaps some more background information would help. \$\endgroup\$