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>
Related
I have 2 tables in a database, 1 of them are linked with a foreign key to the first one. Each row on table 1 is linked to multiple rows in table 2. I am trying to make a query that looks at a WHERE from table 2 and returns multiple rows from table 2 which are sorted into the rows they linked with in table 1 and then put this all into one big multi dimensional array, so it should work something like this:
$array[0][column_name][0] this would use row 1 from table 1 and give me a the first result in the column called column_name
$array[1][column_name][0] this would use row 2 from table 1 and give me a the first result in the column called column_name
$array[1][column_name][3] this would use row 2 from table 1 and give me a the 4th result in the column called column_name
etc
How can I query this and store it in a 3 dimensional array using PHP.
I have tried to word this in as clear manner as possible, if you are unsure what I am asking, please comment and I will update my question to make it clearer.
Assume that we have two tables, Company and Employee:
Company
------------------
ID Company_Name
1 Walmart
2 Amazon.com
3 Apple
Employee
---------------------------------
ID Company_Id Employee_Name
1 1 Sam Walton
2 1 Rob Walton
3 1 Jim Walton
4 1 Alice Walton
5 2 Jeff Bezos
6 2 Brian T. Olsavsky
7 3 Steve Jobs
8 3 Tim Cook
The easiest way to envision a multi-dimensional (nested) array is to mimic the looping required to get it: outer loop is the company, inner loop is the employees:
// ignoring database access, this is just pseudo code
$outer = [];
// select id, company_name from company
foreach $companyResult as $companyRow {
// select * from employee where company_id = ? {$companyRow['id']}
$inner= [];
foreach $employee_result as $employeeRow {
$inner[] = $employeeRow; // ie, ['id'=>'1','Company_Id'=>'1','Employee_Name'=>'Sam Walton']
}
$outer[] = $inner;
}
print_r($outer);
// yields ====>
Array
(
[0] => Array
(
[0] => Array
(
[id] => 1
[Company_Id] => 1
[Employee_Name] => Sam Walton
)
[1] => Array
(
[id] => 2
[Company_Id] => 1
[Employee_Name] => Rob Walton
)
[2] => Array
(
[id] => 3
[Company_Id] => 1
[Employee_Name] => Jim Walton
)
[3] => Array
(
[id] => 4
[Company_Id] => 1
[Employee_Name] => Alice Walton
)
)
[1] => Array
(
[0] => Array
(
[id] => 5
[Company_Id] => 2
[Employee_Name] => Jeff Bezos
)
[1] => Array
(
[id] => 6
[Company_Id] => 2
[Employee_Name] => Brian T. Olsavsky
)
)
[2] => Array
(
[0] => Array
(
[id] => 7
[Company_Id] => 3
[Employee_Name] => Steve Jobs
)
[1] => Array
(
[id] => 8
[Company_Id] => 3
[Employee_Name] => Tim Cook
)
)
)
It is also possible to do if you use associative arrays. Consider the flat file that this query produces:
select company.id company_id, company.name company_name,
emp.id employee_id, emp.employee_name
from company
inner join employee on company.id = employee.company_id
-----
company_id company_name employee_id employee_name
1 Walmart 1 Sam Walton
1 Walmart 2 Rob Walton
1 Walmart 3 Jim Walton
1 Walmart 4 Alice Walton
2 Amazon.com 5 Jeff Bezos
2 Amazon.com 6 Brian T. Olsavsky
3 Apple 7 Steve Jobs
3 Apple 8 Tim Cook
Just use the primary IDs as the keys for your arrays:
$employeeList = [];
foreach($result as $row) {
$cid = $row['company_name'];
$eid = $row['employee_name'];
// avoid uninitialized variable
// $employeeList[$row['company_name']] = $employeeList[$row['company_name']] ?? [];
// easier to read version of above
$employeeList[$cid] = $employeeList[$cid] ?? [];
// assign it...
$employeeList[$cid][$eid] = $row;
}
Or, if you simply want each company row to hold an array of employee names,
$employeeList[$cid][] = $row['employee_name'];
The way that I've shown you is useful if you know the company_id and want to find the associated rows:
foreach($employeeList[2] as $amazon_guys) { ... }
But it's not at all useful if you're trying to group by employee, or some other field in the employee table. You'd have to organize the order of your indexes by your desired search order.
In the end, it's almost always better to simply do another query and let the database give you the specific results you want.
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
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'];
}
Questions
How should I do the query(ies) to get this results?
Should I use a different structure for database tables?
Details
I want to get results from 3 tables:
+------------------------------+-------------------+
| courses | id | <-------+
| | name | |
| | | |
+------------------------------+-------------------+ |
| sections | id | <-------|----------+
| | course_id | <- FK(courses.id) |
| | name | |
+------------------------------+-------------------| |
| resources | id | |
| | section_id | <- FK(sections.id)-+
| | name |
+------------------------------+-------------------+
I want to store results in a PHP Array like this:
Array
(
[courses] => Array
(
[id] => 1
[name] => course 1
[sections] => Array
(
[0] => Array
(
[id] => 1
[course_id] => 1
[name] => course 1 section 1
[resources] => Array
(
[0] => Array
(
[id] => 1
[section_id] => 1
[name] => resource 1
)
)
)
)
)
)
EDIT
What I did:
$cources = DB::query(Database::SELECT,
'select * from courses')->execute($db,false)[0]; // Get all courses as array
foreach($courses as &$course) {
$sections = DB::query(Database::SELECT,
'select * from sections where course_id = '.$courses['id']);
$course['sections'] = $sections;
foreach($course['sections'] as &§ion) {
$resources = DB::query(...); // Get array of resources
$section['resources'] = $resources;
}
}
The database structure is normalized - this is correct and should not be changed.
However, SQL returns de-normalized or "flattened" data for an N+ join: only a set of homogenous records can be returned in a single result-set. (Some databases, like SQL Server, allow returning structure by supporting XML generation.)
To get the desired array structure in PHP will require:
Separate queries/result-sets (as shown in the post): ick!
There will about one query/object. While the theoretical bounds might be similar, the practical implementation will be much less efficient and the overhead will be much more than for single query. Remember that every query incurs (at the very least) a round-trip penalty - as such, this is not scalable although it will likely work just fine for smaller sets of data or for "time insensitive" operations.
Re-normalize the resulting structure:
This is very trivial to do with support of a "Group By" operation, as found in C#/LINQ. I am not sure how this would be approached [easily] in PHP1. This isn't perfect either, but assuming that hashing is used for the grouping, this should be able to scale fairly well - it will definitely be better than #1.
Instead of the above, consider writing the query in such a way that the "flat" result can be used within the current problem/scope, if possible. That is, analyze how the array is to be used - then write the queries around that problem. This is often a better approach that can scale very well.
1 Related to re-normalizing the data, YMMV:
SQL result to PHP multidimensional array
PHP array to multidimensional array
Group a multidimensional array by a particular value?
You can try something like this
SELECT * FROM (
select c.id, c.name from courses c
union
select s.id, r.name,s.course_ID from sections s
union
select r.id, r.name,r.section_ID from resources r
)
You cant get multi dimensional result from mysql. The query for getting the elements should be like this:
select courses.id as coursesId,courses.name as coursesName,sections.id as sectionsId,sections.name as sectionsName,resources.id as resourcesId, resources.name as resourcesName
from courses
left join sections on courses.id=sections.course_id
left join resources on sections.id=resources.section_id;
But ofcourse it will not give you the array as you like.
if you are familiar with php then you can use this code i am writing only 2nd level you can write same way with third label
$final=array();
$c=-1;
$cid=false;
$cname=false;
$query = "SELECT c.*,s.*,r.* FROM courses AS c LEFT JOIN sections AS s ON c.id=s.course_id LEFT JOIN resources AS r ON r.section_id =s.id";
$result=mysql_query($query, $this->con) or die(mysql_error());
while($row= mysql_fetch_array($result)){
if($cid!=$row[2]){
$final['cources'][++$c]['id']=$cid=$row[0];
$final['cources'][$c]['name']=$cname=$row[1];
$s=-1;
}
$final['cources'][$c]['sections'][++$s]['id']=$row[2];
$final['cources'][$c]['sections'][$s]['course_id']=$row[3];
$final['cources'][$c]['sections'][$s]['name']=$row[4];
}
echo "<pre>";
print_r($final);
echo "</pre>";
//Outpur
Array
(
[cources] => Array
(
[0] => Array
(
[id] => 1
[name] => c1
[sections] => Array
(
[0] => Array
(
[id] => 1
[course_id] => 1
[name] => s1-1
)
[1] => Array
(
[id] => 1
[course_id] => 1
[name] => s1-1
)
)
)
[1] => Array
(
[id] => 2
[name] => c2
[sections] => Array
(
[0] => Array
(
[id] => 2
[course_id] => 2
[name] => s1-2
)
)
)
)
)
So I'm working on a permission system. It is basically a role-based system. I have a group table with a many-to-many relationship with a tasks table, and a permissions table to tie them together.
The data would look something like this (tasks table):
+-----+--------+---------+----------+
| id | task | group | parent |
|-----------------------------------|
| 1 | view | news | |
|-----------------------------------|
| 2 | edit | news | |
|-----------------------------------|
| 3 | view | forums | |
|-----------------------------------|
| 4 |a forum | forums | view |
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
What I'm trying to do is allow each group specific permissions with each page. But when needed, more specificity is available. For example on a forums page, I want to be able to control which group can view/edit posts/delete posts/etc from each individual forum.
This is all working - my problem is how to display this data so that it can be assigned. This is what I want it to look like:
News
-- View
-- Edit
Forums
-- View
---- a forum
-- Edit
---- a forum
I just can't wrap my head around how to format this array to do that
Array
(
[0] => Array
(
[task] => view
[group] => news
[parent] =>
)
[1] => Array
(
[task] => edit
[group] => news
[parent] =>
)
[2] => Array
(
[task] => view
[group] => forums
[parent] =>
)
[3] => Array
(
[task] => a forum
[group] => forums
[parent] => view
)
)
Sorry for the confusing post!
Okay totally reformatting my answer now, as it was a bit ambigious what exactly is NOT working.
First rearrange the array like this:
while($result = $query->fetch_assoc())
{
$group = $result['group'];
foreach($result as $field => $value)
{
$data[$group][$field] = $value;
}
}
Then you can iterate through it:
foreach($data as $group)
{
echo $group;
foreach($group as $task => $value)
{
if($task == 'parent' && $task != '') { $indent = '----';}
else {$indent = '--'; }
echo $indent,$task;
}
}
All just sketched out of my head, so I hope it works and it is what you want this time.