diff --git a/dibi/libs/DibiResult.php b/dibi/libs/DibiResult.php index dca12f76..c65b6ca9 100644 --- a/dibi/libs/DibiResult.php +++ b/dibi/libs/DibiResult.php @@ -291,13 +291,87 @@ class DibiResult extends DibiObject implements IDataSource /** * Fetches all records from table and returns associative tree. - * Associative descriptor: assoc1,#,assoc2,=,assoc3,@ - * builds a tree: $data[assoc1][index][assoc2]['assoc3']->value = {record} + * Examples: + * - associative descriptor: col1[]col2->col3 + * builds a tree: $tree[$val1][$index][$val2]->col3[$val3] = {record} + * - associative descriptor: col1|col2->col3=col4 + * builds a tree: $tree[$val1][$val2]->col3[$val3] = val4 * @param string associative descriptor * @return DibiRow * @throws InvalidArgumentException */ final public function fetchAssoc($assoc) + { + if (strpos($assoc, ',') !== FALSE) { + return $this->oldFetchAssoc($assoc); + } + + $this->seek(0); + $row = $this->fetch(); + if (!$row) return array(); // empty result set + + $data = NULL; + $assoc = preg_split('#(\[\]|->|=|\|)#', $assoc, NULL, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY); + + // check columns + foreach ($assoc as $as) { + // offsetExists ignores NULL in PHP 5.2.1, isset() surprisingly NULL accepts + if ($as !== '[]' && $as !== '=' && $as !== '->' && $as !== '|' && !isset($row[$as])) { + throw new InvalidArgumentException("Unknown column '$as' in associative descriptor."); + } + } + + if ($as === '->') { // must not be last + array_pop($assoc); + } + + if (empty($assoc)) { + $assoc[] = '[]'; + } + + // make associative tree + do { + $x = & $data; + + // iterative deepening + foreach ($assoc as $i => $as) { + if ($as === '[]') { // indexed-array node + $x = & $x[]; + + } elseif ($as === '=') { // "value" node + $x = $row->{$assoc[$i+1]}; + break; + + } elseif ($as === '->') { // "object" node + if ($x === NULL) { + $x = clone $row; + $x = & $x->{$assoc[$i+1]}; + $x = NULL; // prepare child node + } else { + $x = & $x->{$assoc[$i+1]}; + } + + } elseif ($as !== '|') { // associative-array node + $x = & $x[$row->$as]; + } + } + + if ($x === NULL) { // build leaf + $x = $row; + } + + } while ($row = $this->fetch()); + + unset($x); + return $data; + } + + + + /** + * @deprecated + */ + private function oldFetchAssoc($assoc) { $this->seek(0); $row = $this->fetch(); @@ -306,14 +380,6 @@ class DibiResult extends DibiObject implements IDataSource $data = NULL; $assoc = explode(',', $assoc); - // check columns - foreach ($assoc as $as) { - // offsetExists ignores NULL in PHP 5.2.1, isset() surprisingly NULL accepts - if ($as !== '#' && $as !== '=' && $as !== '@' && !isset($row[$as])) { - throw new InvalidArgumentException("Unknown column '$as' in associative descriptor."); - } - } - // strip leading = and @ $leaf = '@'; // gap $last = count($assoc) - 1; @@ -328,11 +394,9 @@ class DibiResult extends DibiObject implements IDataSource } } - // make associative tree do { $x = & $data; - // iterative deepening foreach ($assoc as $i => $as) { if ($as === '#') { // indexed-array node $x = & $x[]; diff --git a/examples/fetch.php b/examples/fetch.php index 6c67de55..c3eecfab 100644 --- a/examples/fetch.php +++ b/examples/fetch.php @@ -81,14 +81,14 @@ INNER JOIN [orders] USING ([product_id]) INNER JOIN [customers] USING ([customer_id]) '); -$assoc = $res->fetchAssoc('customers.name,products.title'); // key +$assoc = $res->fetchAssoc('customers.name|products.title'); // key Debug::dump($assoc); echo '