Vnější relace
S vnitřními relacemi jste se pravděpodobně již seznámili a v tématu definice jste narazili na téma vnějších relací. Tak se na ně pojďme podívat.
Vnější relace je vztah mezi dvěma nezávislými entitami. Tedy entitami, které vůči sobě nejsou nijak hierarchicky uspořádané - nejedná se o subenetity. Můžete tak provázat dvě nezávisle entity a tuto provázanost využít zejména při tvorbě dotazů. Důležité je, že ta provázanost není automaticky principiálně dána, jako jsou relace vnitřní, ale je nutné přesně definovat s čím (s jakou entitou) a zejména jak je daná entita provázána.
Ale pojďme raději od teorie rovnou k praxi a ukažme si to opět na příkladu z ukázkové aplikace. Jak již bylo řečeno v kapitole o principech modelování, tak obrázky v rámci malé ukázkové galerie nejsou subentitou galerie, ale samostatnou entitou a to z toho důvodu. že jich může být velké množství a tvořila by se tak datově velice velká entita a to by nemuselo být vhodné. Ale přes to potřebujeme znát fakt, že galerie je z obrázky provázána. Dá se to použít například při hledání (jak si ukážeme), ale určitě nejen tak.
Jak tedy takovou vnější relaci definovat? V rámci ukázkové třídy JetApplication\Content_Gallery takto:
namespace JetApplication;
use Jet\DataModel;
use Jet\DataModel_Definition;
use Jet\DataModel_IDController_UniqueString;
use Jet\DataModel_Query;
#[DataModel_Definition(
name: 'gallery',
database_table_name: 'image_galleries',
id_controller_class: DataModel_IDController_UniqueString::class,
relation: [
'related_to_class_name' => Content_Gallery_Image::class,
'join_by_properties' => ['id' => 'gallery_id'],
'join_type' => DataModel_Query::JOIN_TYPE_LEFT_OUTER_JOIN
]
)]
class Content_Gallery extends DataModel
{
//... ... ...
}
Tedy vlastně vůbec nic složitého .... Je nutné určit tyto věci:
- related_to_class_name
Na jakou třídu (entitu) relace směřuje. - join_by_properties
Jaké vlastnosti tříd tvoří vazbu. Jedná se o asociované pole, kde klíč je název vlastnosti třídy k níž se váže definice (v příkladu je to tedy JetApplication\Content_Gallery) a hodnota je název vlastnosti provazované třídy (zde JetApplication\Content_Gallery_Image). Vlastností může být N, respektive musí být tolik, kolik je pro provázání třeba. - join_type
Jak má vazba fungovat. Možnosti jsou DataModel_Query::JOIN_TYPE_LEFT_JOIN a DataModel_Query::JOIN_TYPE_LEFT_OUTER_JOIN a je to opravdu myšleno jako LEFT JOIN a LEFT OUTER JOIN z hlediska SQL.
Než si ukážeme k čemu je to dobré v praxi, tak si ještě řekněme, že vnějších relací může být definováno X - tedy ne pouze jedna, jak je v příkladu, ale tolik kolik potřebujete.
A ještě jedno důležité upozornění. Tato vazba slouží pouze pro dotazy a načítání dat. Neznamená to například, že při smazání entity A dojde automaticky ke smazání navázaných entit B. Ne vždy je to žádoucí a proto to Jet nedělá automaticky a ponechává to na logice vaší aplikace.
K čemu je to dobré?
Zde trochu předběhnu téma a ukážeme si načítání dat a tvorbu dotazů. V malé ukázkové galerii je možné v v administračním modulu jednoduše vyhledávat galerie a to i na základě názvu obrázku, který v ní je. To má na starost metoda JetApplication\Content_Gallery::search. A ta nedělá nic jiného než že vytvoří jednoduchý dotaz používající vnější relaci a načte galerie splňující daná kritéria. Díky definici vnější relace systém pochopí, že hledáme i pomocí vnější relace a postará se o vygenerování potřebného SQL dotazu:
/**
* @param string $search
*
* @return Content_Gallery[]
*/
public static function search( string $search ): iterable
{
$search = '%' . $search . '%';
return static::fetchInstances(
[
'gallery_localized.title *' => $search,
'OR',
'image.file_name *' => $search
]
);
}