2

So far, my Lumen based Backend-API fetches the following results from my MariaDB:

[{
  "Internal_key": "TESTKEY_1",
  "extensiontable_itc": {
    "description": "EXTENSION_iTC_1"
  },
  "extensiontable_sysops": {
    "description": "EXTENSION_SYSOPS_1"
  }
}, {
  "Internal_key": "TESTKEY_2",
  "extensiontable_itc": {
    "description": "EXTENSION_ITC_2"
  },
  "extensiontable_sysops": {
    "description": "EXTENSION_SYSOPS_2"
  }
}, {
  "Internal_key": "TESTKEY_3",
  "extensiontable_itc": {
    "description": "EXTENSION_ITC_3"
  },
  "extensiontable_sysops": {
    "description": "EXTENSION_SYSOPS_3"
  }
}, {
  "Internal_key": "TESTKEY_4",
  "extensiontable_itc": {
    "description": "EXTENSION_ITC_4"
  },
  "extensiontable_sysops": {
    "description": "EXTENSION_SYSOPS_4"
  }
}, {
  "Internal_key": "TESTKEY_5",
  "extensiontable_itc": {
    "description": "EXTENSION_ITC_5"
  },
  "extensiontable_sysops": {
    "description": "EXTENSION_SYSOPS_5"
  }
}]

What you're seeing is the fetch from 3 Tables, one Coretable and two extensiontables. The coretable contains the "Internal_Key" and it is referenced by the extensiontables via its id, which I declared hidden in the model and therefore its currently not being displayed in the fetchresults. The line of code executing this fetch looks like this:

$join = coretable::with($permittedTables)->get();

The $permittedTables is an array of tablenames, so basically any number and combination of extensiontables can be fetched alongside the referenced records from the coretable.

The data shall ultimately be inserted into a list-like view. Here, for each "Internal_key" a row shall be created into which all the data associated with that key will be inserted.

I'm perfectly fine with the current structure of the data, as I can loop through it however I want and thereby extract the data accordingly to the needs of the list. However, I would like to know if there is any way to (re)organize it differently. If I wanted to put each set of data from the extensiontables on the same "arraylevel" as its respective Internal_key, how should I do this? Should I change the way I fetch the data, or should rearrange the data after the fetch? And in both cases: Whats the easiest, most reliable way to do it?

EDIT: Some more info on the structure of my DB. Coretable has an ID as primary Key which is referenced in the extensiontables via the "coretable_id" FK. Here is the schema of my foreign keys for my DB:

+------------------------------------+-----------------------------+--------------------------------------+--------------------------+------------------------+
| TABLE_NAME                         | COLUMN_NAME                 | CONSTRAINT_NAME                      | REFERENCED_TABLE_NAME    | REFERENCED_COLUMN_NAME |
+------------------------------------+-----------------------------+--------------------------------------+--------------------------+------------------------+
| ad_usersxad_groups                 | Ad_user_id                  | fk_ad_groupxad_user                  | ad_users                 | id                     |
| ad_usersxad_groups                 | Ad_group_id                 | fk_ad_userxad_group                  | ad_groups                | id                     |
| extensiontables_registryxad_groups | ad_group_id                 | fk_ad_groupxextensiontables_registry | ad_groups                | id                     |
| extensiontables_registryxad_groups | extensiontables_registry_id | fk_extensiontables_registryxad_group | extensiontables_registry | id                     |
| extensiontable_itc                 | coretable_id                | fk_extensiontable_itc_coretable      | coretable                | id                     |
| extensiontable_sysops              | coretable_id                | fk_extensiontable_sysops_coretable   | coretable                | id                     |
| inaccessibletable                  | coretable_id                | fk_inaccessibletable_coretable       | coretable                | id                     |
+------------------------------------+-----------------------------+--------------------------------------+--------------------------+------------------------+
Narktor
  • 977
  • 14
  • 34

1 Answers1

2

First of all: we don't have informations on the coretable and extensiontables models, so we don't know if you've implemented Polymorphic Relationships, which would possibly fit your scope perfectly.

That said, a possible reorganization would be to flatten the tree to an array of objects, with

  • A property referencing the internal key
  • Other properties storing their type extensiontable source in the name, e.g. "desc_itc" : "EXTENSION_iTC_1"

That would leave you with something like this:

[{
  "Internal_key": "TESTKEY_1",
  "desc_itc": "EXTENSION_iTC_1",
  "desc_sysops": "EXTENSION_SYSOPS_1"
  }
}, ...
]

EDIT: You mentioned in your comment that there's a one to one relationship with every foreign key only present in an extensiontable, and referencing coretable.id with the key coretable_id .

Another way to organize this data would be to add two columns to coretable, extendable_type e extendable_id and implement a one to one polymorphic relationship: storing the model name in the extendable_type column will let you invoke all extensions by simply accessing the extendable property of your Eloquent model, e.g.

$extendable = $core->extendable;

In order to achieve this, you'd only have to define the following method in the coretable model:

/**
* Returns the matching extension data
*/
public function extendable() {
        return $this->morphTo();
    }

And this to each extensiontable_* model:

/**
* Returns the matching core data
*/
public function coretable() {
  return $this->morphOne('App\coretable', 'extendable');
}
Simone Chiesi
  • 91
  • 1
  • 8
  • I will edit in some more info on my DB structure in a sec! :=) – Narktor Feb 04 '20 at 10:34
  • edited in the info on the relations between coretable and extensions :) – Narktor Feb 04 '20 at 10:38
  • Thanks! Which of the foreign keys are subject to a UNIQUE constraint? – Simone Chiesi Feb 04 '20 at 11:08
  • Basically all of the FKs from extensiontable to coretable. Coretable and extensiontable always have a One-To-One Relationship. Therefore I added the UNIQUE Constraint to the foreign keys. I hope this can be deemed a not entirely bad practice? xD – Narktor Feb 04 '20 at 11:13
  • Also, there seems to be no relation between coretable and the tables having a foreign key in it. Is that quite right? – Simone Chiesi Feb 04 '20 at 11:17
  • I'm not sure if I get what you want to know ^^ The extension tables FK "coretable_id" reference the Primary Key "id" of coretable. This is intended, yes. Would there be any reason to establish a foreign key on the coretable, referencing each of the extensiontables? – Narktor Feb 04 '20 at 11:23
  • And if you meant the other tables like "ad_user" etc.: No, those shall NOT have any relation to coretable. Coretable shall only be referenced by the tables with "extensiontable" in their name :) – Narktor Feb 04 '20 at 11:30
  • Perfect! Edited answer considering a one to one relationship. Just a question: are you sure it's a one to one? The first fetch you posted seemed to point to a one to many (e.g. one coretable record, many extensiontable_* entries). – Simone Chiesi Feb 04 '20 at 11:37
  • Yes, it is a One-To-One. Example: Coretable.Internal_key = "Workstation-17W15R". The workstation has then additional info on the extensiontables, like the CPU, graphics card, MAC-Adress, IP-Adress etc.. There shall be no history of these aspects, so the DB only reflects the present state of the inventory. In this regard, I think it wouldn't be of any use to establish One-To-Many relationship. The multitude of extensiontables was chosen because each table caters to the needs of different departments (for example IT-Supp wants the MAC-Adress, the Devteam does not but wants things IT doesnt want) – Narktor Feb 04 '20 at 11:48
  • About your answer: Polymorphic Relationships are interesting and I once used them in another project, but I'm not sure if this approach really is suitable here. Each item present in coretable will have records in all of the extensiontables, and in this case I need multiple rows/records on coretable for each item to properly apply the references to the extensions. This way I cant make use solely of the ID as the primary key, can I? I think this would make things more complicated than they need to be, but maybe I'm also just not seeing the advantage here, or the disadvantage of my own approach – Narktor Feb 04 '20 at 11:55
  • Ah, got it: we have many one to one relationships. Sorry, the practical use case made everything much clearer. I wonder, if every table is linked to a departmend (and thus their number isn't expected to change with any significant frequency), why aren't FKs stored within coretable, pointing to the various extensiontables? – Simone Chiesi Feb 04 '20 at 13:32
  • Well, the direction of the relation was kind of derived from the workflow of the DDL operations. If the FKs were stored on the coretable, then before being able to insert into coretable, I would have to insert into the extensiontables first. The most important drawback I can think of in this scenario is that every department MUST have info about every item in our inventory. This is not intended, a department might very well have no info about certain items at all, therefore redundant DEFAULT or NULL records would have to be created on their side to allow for the item to exist at all. – Narktor Feb 04 '20 at 13:41
  • As per https://stackoverflow.com/questions/7573590/can-a-foreign-key-be-null-and-or-duplicate, those keys can be nullable, as long as you don't implement a UNIQUE constraint, thus delegating any duplicate check on triggers. Having them nullable would allow you to fill in the extensiontable references at a later time, and filter machines to which a department does not have access (either from extensiontable_* references or boolean flags, e.g. sysop_visibile). Would that have shortcomings? – Simone Chiesi Feb 04 '20 at 13:47
  • What advantages would it have to invert the direction in which the coretable and extensiontables establish their relationship? Especially for the purpose of facilitating a data fetch resulting in a flat structure of the fetched data? Reconfiguring the morphology of the DB and applying custom triggers in places where they werent necessary before seems a bit much for the sole purpose of rearranging a fetchresult. – Narktor Feb 04 '20 at 14:57