1

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

  1. I cannot alter source database (but I would if there's not any other way).
  2. Items of the hierarchy are into separated tables. (I have not a master hierarchy table).
  3. 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 ...

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?

Community
  • 1
  • 1
zedee
  • 419
  • 1
  • 4
  • 15
  • 1
    This is not true recursion because it is not potentially infinitely recursive nor is it reentrant: after `City` would be `Street` or `Subdivision` and then just `House number`. This is just an example of tedium ;) – Dai Nov 14 '14 at 11:04
  • So I suppose my question is: just how deep can this hierarchy go down? If you can't alter the database, then you have all the tables there, so you know exactly how far down it goes. – Dai Nov 14 '14 at 11:05
  • Right now, it goes down one more level deep, but it's planned (in a short timeframe) to have two additional levels of depth (which they still have to define, that's why are not yet). But yes, still it will have a finite depth. By the way, what do you mean by "_This is just an example of tedium_"? That I will have to craft the parenting "manually" ? – zedee Nov 14 '14 at 11:08
  • 1
    yes, unfortunately. Granted, you *could* hypothetically write some meta-code which would be recursive over raw database objects (e.g. `select * from information_schema.tables`) but that would not be worth the trouble because you'll likely need to have special-case handling for each entity. – Dai Nov 14 '14 at 11:14
  • Jeez... that's bad news then. However, I will try to make the tedious task _less_ tedious (will update if I find a fancy solution). – zedee Nov 14 '14 at 11:19
  • 1
    I don't recommend it: don't try to be smart, that's how bugs happen. – Dai Nov 14 '14 at 11:20

0 Answers0