views:

112

answers:

3

I'm trying to mesh the below mysql query results into a single json object, but not quite sure how to do it properly.

$id = $_POST['id'];

$sql = "SELECT contracts.po_number, contracts.start_date, contracts.end_date, contracts.description, contracts.taa_required, contracts.account_overdue, jobs.id AS jobs_id, jobs.job_number, companies.id AS companies_id, companies.name AS companies_name
FROM contracts
LEFT JOIN jobs ON contracts.job_id = jobs.id
LEFT JOIN companies ON contracts.company_id = companies.id
WHERE contracts.id = '$id'
ORDER BY contracts.end_date";

$sql2 = "SELECT types_id
FROM contracts_types
WHERE contracts_id = '$id'";

//return data
$sql_result = mysql_query($sql,$connection) or die ("Fail.");
$arr = array();
while($obj = mysql_fetch_object($sql_result)) { $arr[] = $obj; }
echo json_encode($arr); //return json

//plus the selected options
$sql_result2 = mysql_query($sql2,$connection) or die ("Fail.");
$arr2 = array();
while($obj2 = mysql_fetch_object($sql_result2)) { $arr2[] = $obj2; }
echo json_encode($arr2); //return json

Here's the current result:

[{"po_number":"test","start_date":"1261116000","end_date":"1262239200","description":"test","taa_required":"0","account_overdue":"1","jobs_id":null,"job_number":null,"companies_id":"4","companies_name":"Primacore Inc."}][{"types_id":"37"},{"types_id":"4"}]

Notice how the last section [{"types_id":"37"},{"types_id":"4"}] is placed into a separate chunk under root. I'm wanting it to be nested inside the first branch under a name like, "types".

I think my question has more to do with Php array manipulation, but I'm not the best with that.

Thank you for any guidance.

+1  A: 

It would seem like you'd be better served by consolidating the two queries with a JOIN at the SQL level. However, assuming the two arrays have equal length:

for ($x = 0, $c = count($arr); $x < $c; $x++) {
    if (isset($arr2[$x])) {
        $arr[$x] += $arr2[$x];
    }
}

echo json_encode($arr);

Edit: you would need to change from mysql_fetch_object to mysql_fetch_assoc for this to work properly.

awgy
A: 

Why are you using 2 distinct arrays ? I would simply add the rows of the 2nd query in $arr instead of $arr2. This way, you end up with a single array containing all rows from the 2 queries.

Serge - appTranslator
ok I did that, and it looks like this:[{"po_number":"test","start_date":"1261116000","end_date":"1262239200","description":"test","taa_required":"0","account_overdue":"1","jobs_id":null,"job_number":null,"companies_id":"4","companies_name":"Primacore Inc."},{"types_id":"37"},{"types_id":"4"}]There can be a variable number of types_id values included (they're checkboxes), so is this the best way to organize the data? Seems to me like it should be more like {"types_id":["2","4","67","43"]} or similar so that it doesn't repeat the key name.
Dan
+1  A: 

Combine the results into another structure before outputting as JSON. Use array_values to convert the type IDs into an array of type IDs. Also, fix that SQL injection vulnerability. Using PDO, and assuming the error mode is set to PDO::ERRMODE_EXCEPTION:

$id = $_POST['id'];
try {
    $contractQuery = $db->prepare("SELECT contracts.po_number, contracts.start_date, contracts.end_date, contracts.description, contracts.taa_required, contracts.account_overdue, jobs.id AS jobs_id, jobs.job_number, companies.id AS companies_id, companies.name AS companies_name
        FROM contracts
        LEFT JOIN jobs ON contracts.job_id = jobs.id
        LEFT JOIN companies ON contracts.company_id = companies.id
        WHERE contracts.id = ?
        ORDER BY contracts.end_date");

    $typesQuery = $db->prepare("SELECT types_id
        FROM contracts_types
        WHERE contracts_id = ?");

    $contractQuery->execute(array($id));
    $typesQuery->execute(array($id));

    $result = array();
    $result['contracts'] = $contractQuery->fetchAll(PDO::FETCH_ASSOC);
    $result['types'] = array_values($typesQuery->fetchAll(PDO::FETCH_NUM));

    echo json_encode($result); //return json
} catch (PDOException $exc) {
    ...
}

If $contractQuery returns at most one row, change the fetch lines to:

    $result = $contractQuery->fetch(PDO::FETCH_ASSOC);
    $result['types'] = array_values($typesQuery->fetchAll(PDO::FETCH_NUM));
outis
holy crap. new shiny!
Dan
outis
Ok I finally got this to work... missing a parenthesis at the end of the second sql statement. But damn, this is bad ass, never learned how to use the PDO queries before, now I think I'll use this from now on. Thank you!
Dan
@outis: you're right, I need to put it as an element of contracts
Dan
@Dan: typo is now fixed. Prepared statements are a huge win, both in terms of security and efficiency. Read http://php.net/manual/en/pdo.prepared-statements.php for the details. I should mention that mysqli also supports prepared statements, but PDO is much nicer to deal with. You can even loop over results in a foreach loop: `$query->execute(...); foreach ($query as $row) {...}` because PDOStatement (http://php.net/PDOStatement) implements Traversable (http://php.net/Traversable).
outis
Ahh this is very pro. Thank you so much for the extra fetch line example, I was contemplating how to format the json in php correctly. Now I get to go change all my db queries to the new shinyness!
Dan