Codeigniter Generate Dynamic Table Row Data - php

I am trying to load dynamic table data, my URI is;
example.coma/admin/view/form/<form_id>
My model query is;
public function getRecords($table, $form_id) {
$this->db->select('*');
$this->db->from($table);
$this->db->where('form_id', $form_id);
$query = $this->db->get();
if ($query->num_rows() > 0) {
return $query->result_array();
}
}
This returns an array of data, I need to build a HTML table based on this array.
I'll show an example of two different arrays returned by the query.
Array 1.
(select * from members where form_id = 123)
Array
(
[0] => Array
(
[id] => 104
[member_no] =>
[firstname] => Peter
[lastname] => Keys
[address] => 17 main road
[email] => P3TER#HOTMAIL.CO.UK
[postcode] => UK123
[city] => London
[telnum] => 123123123
[fk_form_submission_id] => 123
)
)
Array 2.
(select * from orders where form_id = 123)
Array
(
[0] => Array
(
[colour] => blue
[type] => shirt
[age] => 34
[size] => medium
[quantity] => 2
[discount] => Y
[posted] => N
)
)
What I want to achieve is display a vertical table to display the dataset. Obviously each table will have different row names, example below;
Table 1.
+---------------+-------+
| ID | 104 |
+---------------+-------+
| Member Number | |
+---------------+-------+
| First Name | Peter |
+---------------+-------+
| Last Name | Keys |
+---------------+-------+
| etc | etc |
+---------------+-------+
Table 2.
+--------+--------+
| Colour | blue |
+--------+--------+
| P Type | shirt |
+--------+--------+
| Age | 34 |
+--------+--------+
| Size | medium |
+--------+--------+
| etc | etc |
+--------+--------+
How can I set these table row names? Do I need to create another array of table headers and merge both arrays?
Any advice is appreciated.

I'm not sure I fully understand - but if you want to set the keys of the array dynamiclly you can do that with foreach loop as:
<table>
<tr><th>Key</th><th>Value</th></tr>
<?php foreach($res[0] as $key => $val)
echo '<tr><td>'. $key . '</td><td>' . $val . '</td></tr>'; ?>
</table>
Edit:
If you want to change the keys name to something more displayable I would recommend using another array for swap (most of the time it done for translation...).
$displayName = array("id" => "ID", "member_no" => "Member Number", "firstname" => "First Name" ..., "type" => "P type", ...);
foreach($res[0] as $key => $val)
echo '<tr><td>'. $displayName[$key] . '</td><td>' . $val . '</td></tr>';
You can also use array_combine but that will need to know which kind of keys you have...
Notice that this solution will work only if the display name are unique for all kind of keys

Related

combining data from multiple lines into a single array

I have some code which pulls from multiple tables of a MS SQL database, arranges the data and outputs an array, I then need to use that array to populate a worksheet telling someone what items are needed on a day to day basis. Right now the output looks like the below, where the fields are ID, Name, Date, number (they are asterisk deliminated because some names include commas).
74*xxxx*2017-06-04*1
74*xxxx*2017-06-05*1
74*xxxx*2017-06-06*2
74*xxxx*2017-06-07*2
74*xxxx*2017-06-08*2
74*xxxx*2017-06-09*2
74*xxxx*2017-06-10*2
75*yyyy*2017-06-05*123
75*yyyy*2017-06-06*111
75*yyyy*2017-06-07*124
75*yyyy*2017-06-08*107
75*yyyy*2017-06-09*194
75*yyyy*2017-06-10*195
I am trying to get them to merge them into a single value per ID so that I can print it out to a grid to look similar to:
| ID | NAME | 06-04 | 06-05 | 06-06 | 06-07 | 06-08 | 06-09 | 06-10 |
| 74 | xxxx | 1 | 1 | 2 | 2 | 2 | 2 | 2 |
| 75 | yyyy | - | 123 | 111 | 124 | 107 | 194 | 195 |
my intent was to merge the array values into a single array with the dates as the keys, the (most recent) code I was trying is:
$schedule[] = $PID . "*" . $program . "*" . $date . "*" . $num;
$grid = array();
foreach ($schedule as $item ) {
$ex = explode('*', $item);
$grid[$ex[0]] = array(
'name' => $ex[1],
$ex[2] => $ex[3],
);
}
with the intent that that would merge them into a single array line to look like:
[74] => Array ( [name] => xxxx [2017-06-04] => 1 [2017-06-05] => 1 [2017-06-06] => 2 [2017-06-07] => 2 [2017-06-08] => 2 [2017-06-09] => 2 [2017-06-10] => 2)
after which I could just use it line by line with $grid[$i][1] etc to pull the value and print to each cell. I've tried other methods than the above, that is the only one I presently have the code snippet for and I've only been able to get it to keep the last value I add on a per ID basis.
I'm certain there is a piece I am missing or simply not understanding, if anyone could offer some input it would be appreciated.
If I understood your requirement correctly, the below code will give the desired array.
$schedule[] = '74*xxxx*2017-06-04*1';
$schedule[] = '74*xxxx*2017-06-05*1';
$schedule[] = '74*xxxx*2017-06-06*2';
$schedule[] = '74*xxxx*2017-06-07*2';
$schedule[] = '74*xxxx*2017-06-08*2';
$schedule[] = '74*xxxx*2017-06-09*2';
$schedule[] = '74*xxxx*2017-06-10*2';
$schedule[] = '75*yyyy*2017-06-05*123';
$schedule[] = '75*yyyy*2017-06-06*111';
$schedule[] = '75*yyyy*2017-06-07*124';
$schedule[] = '75*yyyy*2017-06-08*107';
$schedule[] = '75*yyyy*2017-06-09*194';
$schedule[] = '75*yyyy*2017-06-10*195';
$grid = array();
foreach ($schedule as $item ) {
$ex = explode('*', $item);
$grid[$ex[0]]['name'] = $ex[1];
$grid[$ex[0]][$ex[2]] = $ex[3];
}
print_r($grid);
And out put is
Array
(
[74] => Array
(
[name] => xxxx
[2017-06-04] => 1
[2017-06-05] => 1
[2017-06-06] => 2
[2017-06-07] => 2
[2017-06-08] => 2
[2017-06-09] => 2
[2017-06-10] => 2
)
[75] => Array
(
[name] => yyyy
[2017-06-05] => 123
[2017-06-06] => 111
[2017-06-07] => 124
[2017-06-08] => 107
[2017-06-09] => 194
[2017-06-10] => 195
)
)

Select where HSTORE value is $value Laravel

Using the query builder to try and select rows where a value in the HSTORE key $type is present.
My Where Statement:
->where("meta_data_fields->'$type'", 'like', '%'.$query.'%')
Not sure what I'm doing wrong. I get this error:
Undefined column: 7 ERROR: column "meta_data_fields->'Entity::hstore'" does not exist
Any ideas?
to get all records in table that have HSTORE
Model::where("meta_data_fields", 'like', '%'.$query.'%')->get();
This should do normally do the trick. In your case, data in meta_data_fields is a json string. if the search is performed on all rows in the table, will select all. So here is What I did,
I created a queryScope in the model
1 - fetch all data
2 - extract meta_data_field and decode it
3 - loop through meta_data_field
4 - select only that match the criteria and build the array
here is a table
+----+-------------+------------------------------------+-----------+
| id | name | desc | vendor_id |
+----+-------------+------------------------------------+-----------+
| 1 | apples | {"type":"fruit","origin":"mexico"} | 1 |
| 2 | oranges | {"type":"fruit","origin":"peru"} | 1 |
| 3 | Peaches | {"type":"fruit","origin":"mexico"} | 2 |
| 4 | Cherries | {"type":"fruit","origin":"us"} | 1 |
| 5 | banans | {"type":"fruit","origin":"brazil"} | NULL |
| 6 | Water Melon | {"type":"fruit","origin":"mexico"} | 1 |
+----+-------------+------------------------------------+-----------+
public function scopeItems($name ="mexico"){
$items = array();
$data = Self::get();
$meta_fields = json_decode($data -> pluck('desc') ,true);
foreach ($meta_fields as $key => $value) {
if (isset($value['origin']) && $value['origin'] == $name ){
$items[$key] = $data[$key] -> toArray();
}
}
return $items;
}
// output
Array
(
[0] => Array
(
[id] => 1
[name] => apples
[desc] => Array
(
[type] => fruit
[origin] => mexico
)
[vendor_id] => 1
)
[2] => Array
(
[id] => 3
[name] => Peaches
[desc] => Array
(
[type] => fruit
[origin] => mexico
)
[vendor_id] => 2
)
[5] => Array
(
[id] => 6
[name] => Water Melon
[desc] => Array
(
[type] => fruit
[origin] => mexico
)
[vendor_id] => 1
)
)
Hope this works for you this time.
So here's what worked in my situation with Laravel.
$result = \DB::select(\DB::raw("SELECT hstore_fields, id from table where lower(hstore_fields->'$type') like lower('%$query%')"));

Generate xml file from Laravel template

I have a Laravel template and I want to generate an XML file depending on it.
For example, the structure has a name, XPath and type. So the XML should look like this:
<name>
</name>
<type>
</type>
<xpath>
</xpath>
Of course I am looking for something more complex that can deal with relationships.
Is there any tool for that?
I am using MySQL, so maybe there is a tool for that, too? Or maybe a PHP script?
I already tried to search and all I have found is a tool to generate HTML forms from XSD and general XML from XSD.
Update
The tables and their columns are:
xml_document table with columns: id
general_information table with columns: id, xml_document_id, domain, start_url and `category
master_information table with columns: id, xml_document_id, container, and next_page
master_attribute table with columns: id, master_information_id, name, xpath, and type
details_attribute table with columns: id, xml_document_id, and type
As you may notice, the relationships between:
xml_document and master_information is one to one.
xml_document and general_information is one to one.
xml_document and details_attribute is one to many.
master_information and master_attribute is one to many
As per the Laravel Documentation, Collections and their relationships can be output to arrays:
$roles = User::find(1)->roles->toArray();
for example, I have two models, User and Phone, and a user hasMany() phones.
users phones
+----+--------+ +----+-----------+---------+
| id | name | | id | number | user_id |
+----+--------+ +----+-----------+---------+
| 1 | user 1 | | 1 | 111111111 | 1 |
| 2 | user 2 | | 2 | 222222222 | 2 |
+----+--------+ | 3 | 333333333 | 1 |
+----+-----------+---------+
we can return an array of this using the toArray() method, and with() to pull out all the related Phones:
$users = User::with('phones')->get()->toArray();
giving this (I have hidden some of the fields on the model for the purposes of this answer):
Array (
[0] => Array (
[id] => 1
[name] => user 1
[phones] => Array (
[0] => Array (
[id] => 1
[number] => 111111111
[user_id] => 1
)
[1] => Array (
[id] => 3
[number] => 333333333
[user_id] => 1
)
)
)
[1] => Array (
[id] => 2
[name] => user 2
[phones] => Array (
[0] => Array (
[id] => 2
[number] => 222222222
[user_id] => 2
)
)
)
)
Then you can use any of the various methods for turning arrays into XML. Here's one I've lifted from another answer on SO
function array_to_xml(array $arr, SimpleXMLElement $xml)
{
foreach ($arr as $k => $v) {
is_array($v)
? array_to_xml($v, $xml->addChild($k))
: $xml->addChild($k, $v);
}
return $xml;
}
Example output:
<?xml version="1.0"?>
<root><0><id>1</id><name>user 1</name><phones><0><id>1</id><number>111111111</number><user_id>1</user_id></0><1><id>3</id><number>333333333</number><user_id>1</user_id></1></phones></0><1><id>2</id><name>user 2</name><phones><0><id>2</id><number>222222222</number><user_id>2</user_id></0></phones></1></root>

php (PDO) simple way to turn rows in lookup table into simple array

given a very simple table structure thus:
mysql> describe songpart;
+----------+---------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+----------+---------+------+-----+---------+----------------+
| id | int(11) | NO | MUL | NULL | auto_increment |
| partName | text | NO | | NULL | |
+----------+---------+------+-----+---------+----------------+
which results in an array like this in php (when queried)
Array ( [0] => Array ( [id] => 1 [0] => 1 [partName] => Lead Guitar [1] => Lead Guitar )
[1] => Array ( [id] => 2 [0] => 2 [partName] => Bass Guitar [1] => Bass Guitar )
[2] => Array ( [id] => 3 [0] => 3 [partName] => Drums [1] => Drums )
[3] => Array ( [id] => 4 [0] => 4 [partName] => Keyboard [1] => Keyboard ) )
Am I missing some simple trick to turn this into a simple array with id as the key like so:
Array ( [1] => Lead Guitar
[2] => Bass Guitar
[3] => Drums
[4] => Keyboard )
or is it possible to get PDO to deliver an array like this?
TiA
You can simply use the PDO::FETCH_KEY_PAIR is you have only 2 columns in your result.
You can also use the PDO::FETCH_GROUP and PDO::FETCH_ASSOC together if you have more. Example :
$result = $db->query('select * from channels')->fetchAll(PDO::FETCH_GROUP|PDO::FETCH_ASSOC);
This will yield an array indexed with the first column containing at each index an array of the result for this key. You can fix this by using array_map('reset', $result) to get your goal.
Example :
$result = array_map('reset', $db->query('select * from channels')->fetchAll(PDO::FETCH_GROUP|PDO::FETCH_ASSOC));
Try this:
$records = $pdo->query('SELECT id, partName FROM myTable');
$records->setFetchMode(PDO::FETCH_KEY_PAIR);
print_r($records->fetchAll());
For that you need to set only your desired fields in iteration.
$part_name = [];
$records = $pdo->query('SELECT * FROM your_table');
foreach ($records as $row) {
$part_name[$row['id']] = $row['partName'];
}

Turn database result into array

I have just made the update/add/delete part for the "Closure table" way of organizing query hierarchical data that are shown on page 70 in this slideshare: http://www.slideshare.net/billkarwin/sql-antipatterns-strike-back
My database looks like this:
Table Categories:
ID Name
1 Top value
2 Sub value1
Table CategoryTree:
child parent level
1 1 0
2 2 0
2 1 1
However, I have a bit of an issue getting the full tree back as an multidimensional array from a single query.
Here's what I would like to get back:
array (
'topvalue' = array (
'Subvalue',
'Subvalue2',
'Subvalue3)
);
);
Update:
Found this link, but I still have a hard time to convert it into an array:
http://karwin.blogspot.com/2010/03/rendering-trees-with-closure-tables.html
Update2 :
I was able to add depths to each of the categories now, if that can be of any help.
Okay, I've written PHP classes that extend the Zend Framework DB table, row, and rowset classes. I've been developing this anyway because I'm speaking at PHP Tek-X in a couple of weeks about hierarchical data models.
I don't want to post all my code to Stack Overflow because they implicitly get licensed under Creative Commons if I do that. update: I committed my code to the Zend Framework extras incubator and my presentation is Models for Hierarchical Data with SQL and PHP at slideshare.
I'll describe the solution in pseudocode. I'm using zoological taxonomy as test data, downloaded from ITIS.gov. The table is longnames:
CREATE TABLE `longnames` (
`tsn` int(11) NOT NULL,
`completename` varchar(164) NOT NULL,
PRIMARY KEY (`tsn`),
KEY `tsn` (`tsn`,`completename`)
)
I've created a closure table for the paths in the hierarchy of taxonomy:
CREATE TABLE `closure` (
`a` int(11) NOT NULL DEFAULT '0', -- ancestor
`d` int(11) NOT NULL DEFAULT '0', -- descendant
`l` tinyint(3) unsigned NOT NULL, -- levels between a and d
PRIMARY KEY (`a`,`d`),
CONSTRAINT `closure_ibfk_1` FOREIGN KEY (`a`) REFERENCES `longnames` (`tsn`),
CONSTRAINT `closure_ibfk_2` FOREIGN KEY (`d`) REFERENCES `longnames` (`tsn`)
)
Given the primary key of one node, you can get all its descendants this way:
SELECT d.*, p.a AS `_parent`
FROM longnames AS a
JOIN closure AS c ON (c.a = a.tsn)
JOIN longnames AS d ON (c.d = d.tsn)
LEFT OUTER JOIN closure AS p ON (p.d = d.tsn AND p.l = 1)
WHERE a.tsn = ? AND c.l <= ?
ORDER BY c.l;
The join to closure AS p is to include each node's parent id.
The query makes pretty good use of indexes:
+----+-------------+-------+--------+---------------+---------+---------+----------+------+-----------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+---------------+---------+---------+----------+------+-----------------------------+
| 1 | SIMPLE | a | const | PRIMARY,tsn | PRIMARY | 4 | const | 1 | Using index; Using filesort |
| 1 | SIMPLE | c | ref | PRIMARY,d | PRIMARY | 4 | const | 5346 | Using where |
| 1 | SIMPLE | d | eq_ref | PRIMARY,tsn | PRIMARY | 4 | itis.c.d | 1 | |
| 1 | SIMPLE | p | ref | d | d | 4 | itis.c.d | 3 | |
+----+-------------+-------+--------+---------------+---------+---------+----------+------+-----------------------------+
And given that I have 490,032 rows in longnames and 4,299,883 rows in closure, it runs in pretty good time:
+--------------------+----------+
| Status | Duration |
+--------------------+----------+
| starting | 0.000257 |
| Opening tables | 0.000028 |
| System lock | 0.000009 |
| Table lock | 0.000013 |
| init | 0.000048 |
| optimizing | 0.000032 |
| statistics | 0.000142 |
| preparing | 0.000048 |
| executing | 0.000008 |
| Sorting result | 0.034102 |
| Sending data | 0.001300 |
| end | 0.000018 |
| query end | 0.000005 |
| freeing items | 0.012191 |
| logging slow query | 0.000008 |
| cleaning up | 0.000007 |
+--------------------+----------+
Now I post-process the result of the SQL query above, sorting the rows into subsets according to the hierarchy (pseudocode):
while ($rowData = fetch()) {
$row = new RowObject($rowData);
$nodes[$row["tsn"]] = $row;
if (array_key_exists($row["_parent"], $nodes)) {
$nodes[$row["_parent"]]->addChildRow($row);
} else {
$top = $row;
}
}
return $top;
I also define classes for Rows and Rowsets. A Rowset is basically an array of rows. A Row contains an associative array of row data, and also contains a Rowset for its children. The children Rowset for a leaf node is empty.
Rows and Rowsets also define methods called toArrayDeep() which dump their data content recursively as a plain array.
Then I can use the whole system together like this:
// Get an instance of the taxonomy table data gateway
$tax = new Taxonomy();
// query tree starting at Rodentia (id 180130), to a depth of 2
$tree = $tax->fetchTree(180130, 2);
// dump out the array
var_export($tree->toArrayDeep());
The output is as follows:
array (
'tsn' => '180130',
'completename' => 'Rodentia',
'_parent' => '179925',
'_children' =>
array (
0 =>
array (
'tsn' => '584569',
'completename' => 'Hystricognatha',
'_parent' => '180130',
'_children' =>
array (
0 =>
array (
'tsn' => '552299',
'completename' => 'Hystricognathi',
'_parent' => '584569',
),
),
),
1 =>
array (
'tsn' => '180134',
'completename' => 'Sciuromorpha',
'_parent' => '180130',
'_children' =>
array (
0 =>
array (
'tsn' => '180210',
'completename' => 'Castoridae',
'_parent' => '180134',
),
1 =>
array (
'tsn' => '180135',
'completename' => 'Sciuridae',
'_parent' => '180134',
),
2 =>
array (
'tsn' => '180131',
'completename' => 'Aplodontiidae',
'_parent' => '180134',
),
),
),
2 =>
array (
'tsn' => '573166',
'completename' => 'Anomaluromorpha',
'_parent' => '180130',
'_children' =>
array (
0 =>
array (
'tsn' => '573168',
'completename' => 'Anomaluridae',
'_parent' => '573166',
),
1 =>
array (
'tsn' => '573169',
'completename' => 'Pedetidae',
'_parent' => '573166',
),
),
),
3 =>
array (
'tsn' => '180273',
'completename' => 'Myomorpha',
'_parent' => '180130',
'_children' =>
array (
0 =>
array (
'tsn' => '180399',
'completename' => 'Dipodidae',
'_parent' => '180273',
),
1 =>
array (
'tsn' => '180360',
'completename' => 'Muridae',
'_parent' => '180273',
),
2 =>
array (
'tsn' => '180231',
'completename' => 'Heteromyidae',
'_parent' => '180273',
),
3 =>
array (
'tsn' => '180213',
'completename' => 'Geomyidae',
'_parent' => '180273',
),
4 =>
array (
'tsn' => '584940',
'completename' => 'Myoxidae',
'_parent' => '180273',
),
),
),
4 =>
array (
'tsn' => '573167',
'completename' => 'Sciuravida',
'_parent' => '180130',
'_children' =>
array (
0 =>
array (
'tsn' => '573170',
'completename' => 'Ctenodactylidae',
'_parent' => '573167',
),
),
),
),
)
Re your comment about calculating depth -- or really length of each path.
Assuming you've just inserted a new node to your table that holds the actual nodes (longnames in the example above), the id of the new node is returned by LAST_INSERT_ID() in MySQL or else you can get it somehow.
INSERT INTO Closure (a, d, l)
SELECT a, LAST_INSERT_ID(), l+1 FROM Closure
WHERE d = 5 -- the intended parent of your new node
UNION ALL SELECT LAST_INSERT_ID(), LAST_INSERT_ID(), 0;
Proposed Solution
This following example gives a little more than you ask for, but it's a really nice way of doing it and still demonstrates where the information comes from at each stage.
It uses the following table structure:
+--------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| parent | int(10) unsigned | NO | | NULL | |
| name | varchar(45) | NO | | NULL | |
+--------+------------------+------+-----+---------+----------------+
Here it is:
<?php
// Connect to the database
mysql_connect('localhost', 'root', '');
mysql_select_db('test');
echo '<pre>';
$categories = Category::getTopCategories();
print_r($categories);
echo '</pre>';
class Category
{
/**
* The information stored in the database for each category
*/
public $id;
public $parent;
public $name;
// The child categories
public $children;
public function __construct()
{
// Get the child categories when we get this category
$this->getChildCategories();
}
/**
* Get the child categories
* #return array
*/
public function getChildCategories()
{
if ($this->children) {
return $this->children;
}
return $this->children = self::getCategories("parent = {$this->id}");
}
////////////////////////////////////////////////////////////////////////////
/**
* The top-level categories (i.e. no parent)
* #return array
*/
public static function getTopCategories()
{
return self::getCategories('parent = 0');
}
/**
* Get categories from the database.
* #param string $where Conditions for the returned rows to meet
* #return array
*/
public static function getCategories($where = '')
{
if ($where) $where = " WHERE $where";
$result = mysql_query("SELECT * FROM categories$where");
$categories = array();
while ($category = mysql_fetch_object($result, 'Category'))
$categories[] = $category;
mysql_free_result($result);
return $categories;
}
}
Test Case
In my database I have the following rows:
+----+--------+-----------------+
| id | parent | name |
+----+--------+-----------------+
| 1 | 0 | First Top |
| 2 | 0 | Second Top |
| 3 | 0 | Third Top |
| 4 | 1 | First Child |
| 5 | 1 | Second Child |
| 6 | 2 | Third Child |
| 7 | 2 | Fourth Child |
| 8 | 4 | First Subchild |
| 9 | 4 | Second Subchild |
+----+--------+-----------------+
And thus the script outputs the following (lengthy) information:
Array
(
[0] => Category Object
(
[id] => 1
[parent] => 0
[name] => First Top
[children] => Array
(
[0] => Category Object
(
[id] => 4
[parent] => 1
[name] => First Child
[children] => Array
(
[0] => Category Object
(
[id] => 8
[parent] => 4
[name] => First Subchild
[children] => Array
(
)
)
[1] => Category Object
(
[id] => 9
[parent] => 4
[name] => Second Subchild
[children] => Array
(
)
)
)
)
[1] => Category Object
(
[id] => 5
[parent] => 1
[name] => Second Child
[children] => Array
(
)
)
)
)
[1] => Category Object
(
[id] => 2
[parent] => 0
[name] => Second Top
[children] => Array
(
[0] => Category Object
(
[id] => 6
[parent] => 2
[name] => Third Child
[children] => Array
(
)
)
[1] => Category Object
(
[id] => 7
[parent] => 2
[name] => Fourth Child
[children] => Array
(
)
)
)
)
[2] => Category Object
(
[id] => 3
[parent] => 0
[name] => Third Top
[children] => Array
(
)
)
)
Example Usage
I'd suggest creating some kind of recursive function if you're going to create menus from the data:
function outputCategories($categories, $startingLevel = 0)
{
$indent = str_repeat(" ", $startingLevel);
foreach ($categories as $category)
{
echo "$indent{$category->name}\n";
if (count($category->children) > 0)
outputCategories($category->children, $startingLevel+1);
}
}
$categories = Category::getTopCategories();
outputCategories($categories);
which would output the following:
First Top
First Child
First Subchild
Second Subchild
Second Child
Second Top
Third Child
Fourth Child
Third Top
Enjoy
I loved the answer from icio, but I prefer to have arrays of arrays, rather than arrays of objects. Here is his script modified to work without making objects:
<?php
require_once('mysql.php');
echo '<pre>';
$categories = Taxonomy::getTopCategories();
print_r($categories);
echo '</pre>';
class Taxonomy
{
public static function getTopCategories()
{
return self::getCategories('parent_taxonomycode_id = 0');
}
public static function getCategories($where = '')
{
if ($where) $where = " WHERE $where";
$result = mysql_query("SELECT * FROM taxonomycode $where");
$categories = array();
// while ($category = mysql_fetch_object($result, 'Category'))
while ($category = mysql_fetch_array($result)){
$my_id = $category['id'];
$category['children'] = Taxonomy::getCategories("parent_taxonomycode_id = $my_id");
$categories[] = $category;
}
mysql_free_result($result);
return $categories;
}
}
I think it fair to note that both my answer, and icios do not address your question directly. They both rely on having a parent id link in the main table, and make no use of the closure table. However, recursively querying the database is definitely the way to do, but instead of recursively passing the parent id, you have to pass in the parent id AND the level of the depth (which should increase by one on each recursion) so that the queries at each level can use parent + depth to get the direct parent information from the closure table rather than having it in the main table.
HTH,
-FT
When you want the output as a unordered list you can change the outputCategories method as follows (based on ftrotters arrays in arrays):
public function outputCategories($categories, $startingLevel = 0)
{
echo "<ul>\n";
foreach ($categories as $key => $category)
{
if (count($category['children']) > 0)
{
echo "<li>{$category['name']}\n";
$this->outputCategories($category['children'], $startingLevel+1);
echo "</li>\n";
}
else
{
echo "<li>{$category['name']}</li>\n";
}
}
echo "</ul>\n";
}
Sorry but I don't think you can't get a multi-dimensional array out of your (or any) database query.

Categories