phpdependency-injectionormnette

Error while trying to use Nette framework with Nextras/ORM package - model object injected to a handler is always null


I have worked with most of existing PHP frameworks, but this is the first time I am working with Nette and unfortunately I can't make something which sounded like an easy task to work. How SHOULD it work:

How it WORKS:

After debugging and googling I found out that the problem is that I am trying to use the entity before I instantiated the model. The model object I am sending to the api handler class through DI (at least that's what I thought I'm doing), but when I try to var_dump it, I get the error message Typed property ... must not be accessed before initialization

This is how my configuration looks like for the API endpoints

services:
    - App\Core\RouterFactory::createRouter
    apiOutputConfigurator: Tomaj\NetteApi\Output\Configurator\DebuggerConfigurator
    apiErrorHandler: Tomaj\NetteApi\Error\DefaultErrorHandler

    # define apiKey in local.neon
    staticTokenRepository: Tomaj\NetteApi\Misc\StaticTokenRepository([%apiKey%: '*'])
    - Tomaj\NetteApi\Link\ApiLink
    - Tomaj\NetteApi\Misc\IpDetector
    apiDecider:
        factory: Tomaj\NetteApi\ApiDecider
        setup:
            - addApi(Tomaj\NetteApi\EndpointIdentifier('GET', 1, 'get-endpoint'), \App\api\Handlers\GetEndpointHandler(), Tomaj\NetteApi\Authorization\NoAuthorization())
            - addApi(Tomaj\NetteApi\EndpointIdentifier('POST', 1, 'post-endpoint'), \App\api\Handlers\PostEndpointHandler(), \Tomaj\NetteApi\Authorization\QueryApiKeyAuthentication('api_key', @staticTokenRepository))

This is how my configuration looks like for the ORM:

extensions:
    nextras.dbal: Nextras\Dbal\Bridges\NetteDI\DbalExtension
    nextras.orm: Nextras\Orm\Bridges\NetteDI\OrmExtension

nextras.orm:
    model: App\Model\Orm

services:
    - \App\Model\Repository\MyRepository(\App\Model\Mapper\MyMapper())

The names of the classes are of course censored for privacy reasons but they are not that important.

This is my entity

/**
 * @property int           $id         {primary}
 * LIST OF ALL OTHER PROPERTIES
 */
class MyEntity extends Entity
{

}

This is my mapper

/**
 * @extends DbalMapper<MyEntity>
 */
class MyMapper extends DbalMapper
{

}

And this is the repository class

/**
 * @extends Repository<MyEntity>
 */
class MyRepository extends Repository
{
    /**
     * @inheritDoc
     */
    public static function getEntityClassNames(): array
    {
        return [MyEntity::class];
    }
}

And last but not least the model class

/**
 * Model
 *
 * @property-read MyRepository $things
 */
class Orm extends Model
{

}

I tried to inject the model object to the handler class simply like this (as I've seen in the demo)

#[Inject]
    private Orm $orm;

but as the error messages say it's not working. What did I forget? As I wrote above this is the first time I am doing something with Nette so I'm pretty sure it's something what an experienced Nette dev would find immediately. I have also studied the demo which can be found here : https://github.com/nextras/orm-demo-nette but it woudn't help, I think I have everything done the same way - the only change being is they are injecting it to a presenter and I need to get it working in a Api handler. Thanks for any help.

EDIT: If I try to manually send the ORM in the constructor of the handler class, I am putting it to the config here (hopefully correctly)

apiDecider:
        factory: Tomaj\NetteApi\ApiDecider
        setup:
            - addApi(Tomaj\NetteApi\EndpointIdentifier('GET', 1, 'get-endpoint'), \App\api\Handlers\GetEndpointHandler(App\Model\Orm()), Tomaj\NetteApi\Authorization\NoAuthorization())
            - addApi(Tomaj\NetteApi\EndpointIdentifier('POST', 1, 'post-endpoint'), \App\api\Handlers\PostEndpointHandler(App\Model\Orm()), \Tomaj\NetteApi\Authorization\QueryApiKeyAuthentication('api_key', @staticTokenRepository))

I am getting a new error Service 'apiDecider' (type of Tomaj\NetteApi\ApiDecider): Parameter $configuration in Nextras\Orm\Model\Model::__construct() has no class type or default value, so its value must be specified.


Solution

  • So ... this is embarrassing but I found the error and it was on my side. For whatever reason creating an empty web application with composer generates Bootstrap.php which reads services.neon, but cloning our repo generates a Bootstrap.php where all config files have singular names, meaning service.neon . For some reason. In other words I was writing my configuration in a file which Bootstrap did NOT load. After renaming it properly, everything suddenly works as expected, what a surprise. Thanks for everybody's time, I'm going to silently rethink my life :)