Nextras\ORM a views – jak na to?

chikeet
Člen | 160
+
0
-

Zdravím,
zkouším použít pro jeden datagrid v aplikaci view místo tabulky (s vlastní entitou nad tím view, pochopitelně) a nemůžu se dostat přes tohle:

Storage 'places_view' has not defined any primary key.

Na tom view primární klíč nenastavím, neb to MySQL podle všeho neumožňuje. View si bere primární klíč ze své základní tabulky, ale vypadá to, že to nestačí.

Dá se to nějak rozumně obejít? Nastavit nějak třeba v mapperu, nebo něco na ten způsob?

V mapperu mám aktuálně definovaný pouze název view:

class PlaceViewsMapper extends BaseMapper
{
    function getTableName() {
        return "places_view";
    }

}

BaseMapper:

use Nextras\Orm\Mapper\Dbal\QueryBuilderHelper;
use Nextras\Orm\Mapper\Mapper;

abstract class BaseMapper extends Mapper
{

	public function getAlias()
	{
		return QueryBuilderHelper::getAlias($this->getTableName());
	}

}

PlaceView:

/**
 * @property int $id {primary}
 * ...
*/
Jan Tvrdík
Nette guru | 2595
+
+1
-

@chikeet Dohledal jsem tohle starší vlákno https://gist.github.com/…47bb1632d0f0#…

chikeet
Člen | 160
+
0
-

Jan Tvrdík napsal(a):

@chikeet Dohledal jsem tohle starší vlákno https://gist.github.com/…47bb1632d0f0#…

Díky moc, pomohlo.

Jen ještě nevím, jestli nějak můžu přimět ORM, aby používalo cizí klíče z původní tabulky places. Všechny sloupce, kterých se to týká, jsou do view natáhnuté z places (např. region_id), v places jsou na ně nastavené cizí klíče (a bez problémů fungují), ale ve view jsou všechny navázané entity nullové (např. ten region). Svou custom StorageReflection mám vytvořenou tak, že extenduju UnderscoredStorageReflection, ale hádám, že tam asi problém nebude vzhledem k tomu, že se tam jen překládájí názvy sloupců na properties.

Jan Tvrdík
Nette guru | 2595
+
0
-

@chikeet Můžeš zkusit pro to view vrátit reflection té tabulky? Tj. dát jako druhý parametr konstruktoru místo názvu view název té tabulky, které té view odpovídá?

chikeet
Člen | 160
+
0
-

Jan Tvrdík napsal(a):

@chikeet Můžeš zkusit pro to view vrátit reflection té tabulky? Tj. dát jako druhý parametr konstruktoru místo názvu view název té tabulky, které té view odpovídá?

Paráda, funguje – díky moc!

Kdyby se to někomu hodilo, tak…
Mapper:

class PlaceViewsMapper extends BaseMapper
{
    function getTableName() {
        return "places_view";
    }

	protected function createStorageReflection()
	{
		return new ViewReflection(
			$this->connection,
			'places', // nazev tabulky misto $this->getTableName()
			$this->getRepository()->getEntityMetadata()->getPrimaryKey(),
			$this->cache
		);
	}

}

StorageReflection:

use Nextras\Orm\Mapper\Dbal\StorageReflection\UnderscoredStorageReflection;

class ViewReflection extends UnderscoredStorageReflection
{

	public function getStoragePrimaryKey()
	{
		return ['id'];
	}
	protected function getDefaultMappings()
	{
		return [];
	}
	protected function getDefaultModifiers()
	{
		return [];
	}
}

Edit: tak to vypadá, že postup s nastavením tabulky natvrdo zmate ORM tak, že se snaží view používat i tam, kde má být použita tabulka (původní entita Places). Takže zatím nevyřešeno.

Editoval chikeet (30. 5. 2017 22:03)

hrach
Člen | 1834
+
0
-

@chikeet nemelo by stacit rovnou zavolat puvodni UnderscoredStorageReflection jen s nazvem puvodni tabulky? Tedy ze neni treba pretezovat ty metody?

chikeet
Člen | 160
+
0
-

@hrach Zkusím, zatím mi to nefunguje podle očekávání (viz edit v předchozím příspěvku). Popravdě nemám fungování Nextras\ORM nastudováno moc nad rámec základní práce, takže se v tom zatím blbě orientuju a dost možná dělám chyby z neznalosti (LeanMapper i Doctrine mi přišly srozumitelnější, ale třeba to chce jen pořádně pročíst docku).

chikeet
Člen | 160
+
0
-

@hrach Tak nakonec stačilo použít ViewReflection s přepsanou metodou getStoragePrimaryKey, jinak to padalo právě na tom chybějícím primary key (při použití přímo UnderscoredStorageReflection).

Foreign key properties vyřešilo přepsání table name na places (původní tabulka k places_view).

Aby to nerozhazovalo vztahy jinde v aplikaci, bylo třeba použít u navázaných entit v PlaceView oneSided=true.