gremo
gremo

Reputation: 48919

Is this the right way of implementing "Design by contract" pattern in PHP?

I've discovered the "Design by contract" pattern and how to implement in in PHP. I can't find a real world example of how to do this in PHP. First question is am i'm doing it in the right way? Second one is why the assert callback is not honored?

A static class Asserts for reusable assertions:

class Asserts
{
    public static function absentOrNotNumeric($value)
    {
        return !isset($value) ? true : is_numeric($value);
    }
}

Usage:

assert_options(ASSERT_ACTIVE,   true);
assert_options(ASSERT_BAIL,     true);
assert_options(ASSERT_WARNING,  true);
assert_options(ASSERT_CALLBACK, array('UseAsserts', 'onAssertFailure'));

class UseAsserts
{
    private $value;

    public function __construct($value)
    {
        // Single quotes are needed otherwise you'll get a
        // Parse error: syntax error, unexpected T_STRING 
        assert('Asserts::absentOrNotNumeric($value)');
        $this->value = $value;
    }

    public static function onAssertFailure($file, $line, $message)
    {
        throw new Exception($message);
    }
}

// This will trigger a warning and stops execution, but Exception is not thrown
$fail = new UseAsserts('Should fail.');

Only the (right) warning is triggered:

Warning: assert() [function.assert]: Assertion "Asserts::absetOrNotNumeric($value)" failed.

Upvotes: 5

Views: 327

Answers (2)

Jason Brumwell
Jason Brumwell

Reputation: 3550

Your exception is being thrown, altering it to:

public static function onAssertFailure($file, $line, $message)
{
    echo "<hr>Assertion Failed:
    File '$file'<br />
    Line '$line'<br />
    Code '$code'<br /><hr />";
}

results in a display of the text, some testing discovers that if you alter this option

assert_options(ASSERT_BAIL,     false);

The exception will be thrown, so it seems that it bails on the execution prior to throwing the exception.

Hope that helps

Upvotes: 4

Naftali
Naftali

Reputation: 146310

Your code: http://codepad.org/y10BlV8m

My code: http://codepad.org/slSX3HKd

Try using double quotes: assert("Asserts::absentOrNotNumeric($value)");

Upvotes: -1

Related Questions