Joining Multidimensional Associative Arrays based on Equivalent Key => Value Pair

I’ve been working on a project that pulls data from a DB2 database and formats it for the end user.

I have a class for each type of output (currently only one type exists), that constructs an associative array to specify what tables to pull from and what columns to grab from each table ($capturegroups). My controller gathers that information and uses it to construct SQL queries that are sent to the database and return values in an associative array ($output).

Here is an example of the $captureGroups array (in the format of “alias” => “columname”):

            "lineitem" => array(
                "schema1.table1" => array(
                    "item" => "POISQ",
                    "qty" => "QTYOR",
                    "unit" => "UMORD",
                    "bnc part no." => "ITNBR",
                    "description" => "ITDSC",
                    "dock date" => "DUEDT", # or DOKDT?
                    "acct" => "ACCTN",
                    "unit price" => "STKPR",
                    "total" => "EXTPR",
                ),
                "schema1.table2" => array(
                    "item" => "POISQ",
                    "comment 1"	=> "CMNT1",
                    "comment 2"	=> "CMNT2"
                )

I use this to generate an sql query in the format:

SELECT columnName, columnName, columnName FROM scheme.table WHERE orderKey='userInput' ORDER BY orderKey

Here is a sample of the $output array (print_r() formatting):

Array
(
    [geninfo] => Array
        (
            [noquery] => Array
                (
                    [for sale] =>  
                    [for use] =>  
                )

            [schema1.table0] => Array
                (
                    [0] => Array
                        (
                            [order date] => 1180316                                                                                             
                            [shipped via] =>                                                                                                     
                            [terms] =>                                                                                                     
                        )

                )

        )

Yesterday, I hit a brick wall. My view file (the template that formats the data) is based mostly on foreach loops that know very little about the data that is coming to them.

The PHP that I am having issues with generates an HTML table, with a simple foreach loop that adds a <th> field to the <thead> for every “key” in the specified array, then adds a <td> to the <tbody> for each “value”. However, I need the HTML table to contain data for two separate arrays, and I am not sure how to make that happen.

The first array contains line item data:

[lineitem] => Array
        (
            [schema1.table1] => Array
                (
                    [0] => Array
                        (
                            [item] => 1                                                                                                   
                            [qty] => 5.000                                                                                               
                            [unit] => EXAMPLE                                                                                                  
                            [part no.] => 1234567                                                                                          
                            [description] => EXAMPLE DESC                                                                                        
                            [dock date] => 1180423                                                                                             
                            [acct] => 130                                                                                                    
                            [unit price] => 123.4500                                                                                           
                            [total] => 617.2500                                                                                           
                        )

The array that I need to join this with contains comments pertaining to each line item. The comments have an identical <“item” => int> pair to the line item they belong to.

([lineitem]...)

            [schema1.table2] => Array
                (
                    [0] => Array
                        (
                            [item] => 1                                                                                                   
                            [comment 1] => THIS ITEM DCK DATE WAS CHANGED                                                                      
                            [comment 2] => WAS        04/02/18, CHANGED    04/03/18                                                            
                        )

My question: is there a way to marry/join the comment data with the line item data based on the common key=>value pair in the $output array? I want the data to be accessible essentially like so:

[lineitem]
            [0] => array
                (
                            [item] => 1                                                                                                   
                            [qty] => 5.000                                                                                               
                            [unit] => EXAMPLE                                                                                                  
                            [part no.] => 1234567                                                                                          
                            [description] => EXAMPLE DESC                                                                                        
                            [dock date] => 1180423                                                                                             
                            [acct] => 130                                                                                                    
                            [unit price] => 123.4500                                                                                           
                            [total] => 617.2500                                 
                            [comment 1] => THIS ITEM DCK DATE WAS CHANGED                                                                      
                            [comment 2] => WAS        04/02/18, CHANGED    04/03/18
            )

Doing this by joining the current output arrays would be far more convenient than the most obvious alternative, which is to start using three-part namespaces and SQL joins whenever a capturegroup (eg “lineitems”) draws from multiple tables. Using 3-part namespaces and joins would require me to rewrite / restructure the $captureGroups array, the code that generates my SQL queries, and probably reformat the $output to work with the “view”/template file - something that I’m not entirely against doing, but would like to avoid if possible.

I’ve looked at array_merge and similar functions but I can’t seem to figure out how to get things together based on the identical key=>value pairs.

I think I’ll have any easier time maintaining this code in the future if I do a little bit of rewriting. For posterity I’ll post my solution.

I’m going to change my my $captureGroups array to the following format:

$captureGroups = array(
	
	"lineitem" => array(
		
		"tables" => array(
			
			[0] => "schema1.table1",
			[1] => "schema1.table2"
			
		),
		
		"columns" => array(
			
			"item" 		=> "schema1.table1.POISQ",
			"qty"		=> "schema1.table1.QTYOR",
			"unit"		=> "schema1.table1.UMORD",
			"bnc part no."  => "schema1.table1.ITNBR",
			"description"	=> "schema1.table1.ITDSC",
			"comment 1" 	=> "schema1.table2.CMNT1",
			"comment 2" 	=> "schema1.table2.CMNT2",
			"dock date" 	=> "schema1.table1.DUEDT",
			"acct"		=> "schema1.table1.ACCTN",
			"work order" 	=> "schema1.table1.WONB",
			"unit price" 	=> "schema1.table1.STKPR",
			"total"		=> "schema1.table1.EXTPR"
			
		),
		
		"parameters" => array(
			
			"join" => "1",
			"joinKey" => "poisq"

		)
		
	)

I’ll generate the SQL queries in the following format:

sql = "SELECT implode(", ", $columns) 
		   FROM implode(", ", $tables) 
		   WHERE $conditions 
		   ORDER BY $orderKey;"

(With $columns being pulled with foreach from the [‘columns’] part of my $captureGroups array, and $tables the same. Conditions will be generated with a few conditionals, based on the [“parameters”].

I am still trying to figure out where the $orderKey will be specified – previously, I set one for the class (that would be used by most tables) and allowed it to be overwritten for individual tables by specifying “newOrderKey” => “(FieldName)” in the table’s respective array. I think I will specify it in “parameters” in the rewritten code.

That will give me the query:

	SELECT schema1.table1.ORDNO,
	       schema1.table1.POISQ, 
	       schema1.table2.POISQ, 
	       schema1.table1.QTYOR, 
	       schema1.table1.UMORD, 
	       schema1.table1.ITNBR, 
	       schema1.table1.ITDSC,
	       schema1.table2.CMNT1, 
	       schema1.table2.CMNT2, 					
	       schema1.table1.DUEDT, 
	       schema1.table1.ACCTN, 
	       schema1.table1.WONB, 
	       schema1.table1.STKPR, 
	       schema1.table1.EXTPR
	FROM schema1.table1, schema1.table2 
	WHERE schema1.table1.POISQ = schema1.table2.POISQ;

Using db2_fetch_assoc will then give me the array in the format I need.

While I’m sure there is a way to merge the arrays in $output, this method is a little more robust and (hopefully) pretty well reduced to a general enough form (so that I dont have to type redundant code every time this issue pops up).

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.