Despite I've checked a lot of StackOverflow questions, as well as Google, I can't find any solution for this. (any solution which I can understand and be able to do).
The status quo
- I cannot alter source database (but I would if there's not any other way).
- Items of the hierarchy are into separated tables. (I have not a master hierarchy table).
- If I query one of those tables, I have a relation of an item and its parent, but between diferent tables, those items doesn't share its parenting.
Relation to achieve:
- Country
- Region
- City
- And so on ...
- City
- Region
My starting point
Source data is in the following tables (depicted as table => columns
)
country_table => id
region_table => id, country_id
city_table => id, region_id
... and so on ...
But when I query&join these tables, they don't share a "master" parent in any way. D'oh!
Solutions I've thought so far
- Screw the "cannot alter source database" and build a proper hierarchy table (following the guides from an answer to this question: What is the most efficient/elegant way to parse a flat table into a tree?
- Worst never-ever do solution (if it can be called a solution at all): Hardcode the tree hierarchy, parenting all I can in each table and then parenting table by table.Con: Unmaintenable code, the deeper the hierarchy goes, the longest the lines of code are. And if hierarchy changes you're screwed.
EDIT: Final decision (and solution)
- I didn't thought about converting that array into an XML Object (using PHP's SimpleXMLElement).
Code:
function buildLocationTree()
{
//We retrieve raw data from model (Laravelish style)
$aLocations = WhateverModel::getLocations();
$oXML = new SimpleXMLElement('<xml/>');
//I add a root node called 'result'
$oResult = $oXML->addChild('result');
foreach ($aLocations as $oLocation)
{
if (! ($oXML->xpath("//country[@id=" . $oLocation->CountryId . "]")))
{
$oCountry = $oResult->addChild('country', $oLocation->CountryName);
$oCountry->addAttribute('id', $oLocation->CountryId );
}
if (! ($oXML->xpath("//region[@id=" . $oLocation->RegionId. "]")))
{
$oRegion = $oCountry->addChild('region', $oLocation->RegionName);
$oRegion->addAttribute('id', $oLocation->RegionId );
}
//And so on... build many structures 'search in nodes + add child' as deep levels
}
return $oXML;
}
Then do whatever you need with the XML object... jsonize it, build a file...
I'd be nice to have some feedback or listen your thoughts about this solution! Is an acceptable one? Risky or prone to errors?