piotr.jura
piotr.jura

Reputation: 899

A way to require trait is used in a specific class

http://hacklang.org/tutorial/ - see last exercise (24).

...
trait T {
    require extends C;
...

How would you achive this in PHP?

I'd like to use that in PHP Unit tests, like below:

class EventsTest extends TrafficWebTestCase
{
    use EntityRepositoryMock;
    use ValidatorMock;
    use EventsDataProviderTrait;

An example of trait:

trait ValidatorMock
{
...
protected function getValidatorMock($validateObject, $return = [])
{
    if (!method_exists($this, 'getMockForAbstractClass')) {
        throw new InvalidTraitUseException();
    }

    $this->validatorMock = $this->getMockForAbstractClass(
        'Symfony\Component\Validator\Validator\ValidatorInterface'
    );

    $this->validatorMock->expects($this->once())
        ->method('validate')
        ->with($this->equalTo($validateObject))
        ->willReturn($return);

    return $this->validatorMock;
}

Those trait create some specific mocks or do other stuff that's only related to a unit test. In those traits I use methods from the \PHPUnit_Framework_TestCase, so I'd like to check if trait is used in a valid context.

Upvotes: 1

Views: 3179

Answers (1)

Marcin Nabiałek
Marcin Nabiałek

Reputation: 111829

I think you want something like that:

trait T
{
    public function __construct()
    {
        if (!($this instanceof C)) {
            die('Not an instance of C');
        }
        echo "Everything fine here<br />";

        $this->someMethod();
    }


}

class C
{
    public function someMethod()
    {
        echo "required method<br />";
    }

}

class A extends C
{
    use T;

    public function doSomething()
    {

    }
}

class B
{
    use T;

    public function doSomething()
    {

    }
}

$a = new A();
$b = new B();

Using instanceof you can check if object extends some class.

For the following code result will be:

Everything fine here
required method
Not an instance of C

More complex code (without checking in constructor):

trait T
{

    public function myFunction()
    {
        $this->checkHierarchy();

        echo "normal actions<br />";

    }

    public function secondFunction()
    {
        $this->checkHierarchy('D');

        echo "normal actions<br />";

    }

    private function checkHierarchy($className = 'C')
    {
        if (!($this instanceof $className)) {
            throw new \Exception('Not an instance of ' . $className . "<br />");
        }
        echo "Everything fine here<br />";
    }


}

class C
{
    public function someMethod()
    {
        echo "required method<br />";
    }

}

class A extends C
{
    use T;

    public function doSomething()
    {

    }

    public function __construct()
    {
        echo "aaa<br />";
    }
}

class B
{
    use T;

    public function doSomething()
    {

    }

    public function __construct()
    {
        echo "bbb<br />";

    }
}


$a = new A();
try {
    $a->myFunction();
} catch (\Exception $e) {
    echo $e->getMessage();
}

try {
    $a->secondFunction();
} catch (\Exception $e) {
    echo $e->getMessage();
}
$b = new B();
try {
    $b->myFunction();
} catch (\Exception $e) {
    echo $e->getMessage();
}

Upvotes: 3

Related Questions