php-deal / framework

Design by Contract framework for PHP
MIT License
252 stars 22 forks source link

Bootstrap from class and run on self #33

Closed panosru closed 5 years ago

panosru commented 5 years ago

Hello again!

Nice progress on the framework!

I run in an issue today, I wanted to have an "App" class for an application I'm building and there to have a bootstrap method (run), but when I tried to apply contracts on that same app it didn't work.

MyApp.php file:

<?php
declare(strict_types=1);

namespace Demo;

use PhpDeal\Annotation as Contract;
use PhpDeal\ContractApplication;

class MyApp
{
    /**
     * @return void
     */
    final public function run(): void
    {
      ContractApplication::getInstance()->init([
          'debug' => true,
          'appDir' => __DIR__ ,
          'cacheDir' => __DIR__ . '/../cache',
      ]);
    }

    /**
     * Just a number
     *
     * @param int $num
     *
     * @return void
     *
     * @Contract\Verify("$num>10 && is_numeric($num)")
     */
    public function test(int $num): void
    {
      echo $num;
    }
}

test file:

<?php
declare(strict_types=1);

/**
 * Author: panosru
 * Date: 2019-02-19
 * Time: 16:41
 */

require_once __DIR__ . '/vendor/autoload.php';

$app = new \Demo\MyApp();
$app->run();

$app->test(5);

I got 5 as a result instead of an exception for contract violation: image

Thanks!

icanhazstring commented 5 years ago

Hi @panosru thanks for reaching out. This is due to the design of GoAop and how the composer autoloader is functioning.

As you maybe know, goaop creates a proxy class for your original one \Demo\MyApp. This way if you try to instantiate this class, you won't directly instantiate your class, but the proxy one.

But this only happens after you called init() on the ContractApplication. This is the point where GoAop changes the autoloader to give you the proxy, not your class.

Long story short. You MUST call the ContractApplication::getInstance()->init() before you create instances of your classes.

I hope I could help you out better understand what is happening behind the scenes :)

panosru commented 5 years ago

@icanhazstring Thanks for the explanation!

Yeap I read the source and more or less understood the process, I just thought maybe I might miss something and I could use the framework on the class itself, however, even so, it isn't much of an issue, just one class that won't have the functionality of the framework...

Thanks!