Zaciatocnicka otazka ohladom nextras-orm – ako injectnut model do api handleru?

pittrek
Člen | 3
+
0
-

Zdravim, absolutne zaciatocnicka otazka, ale dufam ze mi niekto bude vediet poradit. S Nette nemam skusenosti, tak sa vopred ospravedlnujem ak sa jedna o trivialny problem.

Mam aplikaciu, ktora ma nejake API (urobene za pomoci tomaj/nette-api). Teraz by som v oboch API handleroch potreboval pracovat s databazou, v jednom handleri chcem z nej citat, v druhom do nej zapisovat. Chcel som skusit nextras orm, lenze „quick overview“ je na moj vkus az prilis „quick“, zrazu sa tam pouziva nejaky objekt $orm bez toho aby bol definovany a trochu som sa stratil… Po precitani zvysku dokumentacie a po prestdovani si prislusneho dema (https://github.com/…m-demo-nette) som pochopil ze $orm je objekt a ma byt injectnuty cez dependency injection, lenze nieco mi stale chyba. Myslel som si ze mam vsetko urobene rovnako ako v deme, az na rozdiel ze tam to autor injectuje do presentera a ja by som to potreboval nejako dostat do tych mojich 2 api handlerov.

Moja konfiguracia

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())

Moja entita

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

}

Moj mapper

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

}

a moj repository

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

A samozrejme model

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

}

V handleroch som sa snazil pridat $orm podla dema

#[Inject]
private Orm $orm;

Ked hocikde v handleri zavolam $this->orm, dozviem sa ze orm este nie je inicializovana.

Na co som podla vas zabudol? Diky za akukolvej pomoc

Editoval pittrek (20. 5. 22:16)

Marek Bartoš
Nette Blogger | 1311
+
+1
-

Viz https://doc.nette.org/…ion/services#… a https://doc.nette.org/…od-attribute#…
Mimo abstraktní Base* třídy se spoustou závislostí je ale obvyklé použít spíš konstruktor.

pittrek
Člen | 3
+
0
-

Diky za odpoved. Ten druhy link – presne tak som to mal doteraz, lenze nie v presenteri ale v apihandleri

#[Inject]
public Orm $orm;

Ten prvy link neviem ci som prepisal spravne, moj services.neon teraz vyzera takto

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
    getEndpointHandler: ## tato cast je posunuta von z apiDecider.setup
        create: \App\api\Handlers\GetEndpointHandler
        inject: true
    apiDecider:
        factory: Tomaj\NetteApi\ApiDecider
        setup:
            - addApi(Tomaj\NetteApi\EndpointIdentifier('GET', 1, 'get-endpoint'), @getEndpointHandler, Tomaj\NetteApi\Authorization\NoAuthorization())

Cize povodne mal apiDecider v setup metodu addApi, ktora brala ako druhy parameter konstruktor api handler classy, tu som teraz vyhodil vyssie (dufam ze spravne, jedna sa o moj prvy nette produkt) a teraz dostavam nasledovnu chybu

*Nette\DI\MissingServiceException

Service of type App\Model\Orm required by App\api\Handlers\GetEndpointHandler::$orm not found. Did you add it to configuration file?*

Takze som mu este manualne vlozil do konstruktora api handlera konstruktor ORM, cize

getEndpointHandler: ## tato cast je posunuta von z apiDecider.setup
        create: \App\api\Handlers\GetEndpointHandler(App\Model\Orm())
        inject: true

nepomohlo, chyba je stale hlasena rovnaka

Marek Bartoš
Nette Blogger | 1311
+
0
-

Máš třídu Orm opravdu v namespace App\Model? Změní se chyba, když místo ní vyžádáš předka Nextras\Orm\Model\Model?
Inject máš nastavený dobře. Nette DI tvůj inject atribut našlo, ale neví jakou službu tam předat. Nejspíš je tedy problém v konfiguraci předávané orm extension.

pittrek
Člen | 3
+
0
-

Skontrolovany namespace – ano, trieda je App\Model\Orm a je zdedena z Nextras\Orm\Model\Model.
Je zaujimave ze ked som skusil

create: \App\api\Handlers\GetEndpointHandler(Nextras\Orm\Model\Model)

chyba sa stale nezmenila a stale tvrdi ze Service of type App\Model\Orm … not found.

Je spravne moja Api Handler class?

class GetEndpointHandler extends BaseHandler
{
    #[Inject]
    public App\Model\Orm $orm;

    public function handle(array $params): ResponseInterface
    {
        var_dump($this->orm);die();
    }
}

Momentalne tam nemam konstruktor ale ak ho pridam, chyba sa nezmeni a predtym ako som v configu pridal inject: true, v pripade ze tam bol konstruktor hadzalo to inu chybu, nieco ze parameter $configuration v Model::__construct nie je definovany

Marek Bartoš
Nette Blogger | 1311
+
+1
-

Ani jeden zápis ti nefunguje, protože DI nemůže najít službu typu App\Model\Orm. To může mít dva důvody. Buď tam služba vůbec není, nebo je autowired typ nastaven na předka. Pokud je autowired nastavené na Nextras\Orm\Model\Model, tak ti App\Model\Orm nebude fungovat automaticky. Pokud není uveden autowired, tak se bere z type nebo create (historicky factory).

Zkus se prodebugovat tímto kódem https://github.com/…xtension.php#L68
Vypadá to, že nextras nenajde žádný repozitář, a tak ti ani nezaregistruje Model.

Kdyby to nevyšlo, tak zatím z DI odstraň služby vyžadující Model, aby se zkompiloval container (ukládá se myslím do temp/nette.configurator). Z containeru už se dá lépe vyčíst, co je se službou špatně.


create: \App\api\Handlers\GetEndpointHandler(Nextras\Orm\Model\Model)

Tohle ti fungovat nebude, odkazy na služby podle názvu i podle typu musí být prefixované s @, takže @Nextras\Orm\Model\Model. Obvykle bys takový zápis ale neměl potřebovat