Redbeanphp - Getting data from foreign key index - php

Sorry for the vague title, if anyone would like to edit it to reflect more about what I am posting, please do so. Here is the situation. I have 3 tables:
support:
id | contact_id | title | problem | etc
supportlogin:
id | contact_id | login | pass | etc
contact:
id | first_name | last_name | email | etc
I am loading the support bean just fine, and am accessing the contact info:
$support=R::load('support',1);
echo $support->contact->first_name;
I want to echo the supportlogin information similarly:
echo $support->contact->ownSupportlogin->login;
Is this possible, and am I doing it the right way? I have tried the following ways with no success:
echo $support->contact->supportlogin->login;
echo $support->contact->ownSupportlogin->login;
echo $support->contact->ownSupportlogin[0]->login;
EDIT: MORE INFO
I did print_r($support->contact) and was given the data:
RedBean_OODBBean Object
(
[null:RedBean_OODBBean:private] =>
[properties:RedBean_OODBBean:private] => Array
(
[id] => 109
[phone] => 1234580970
[first_name] => Tim
[last_name] => Withers
)
[__info:RedBean_OODBBean:private] => Array
(
[type] => contact
[sys.id] => id
[tainted] =>
)
[beanHelper:RedBean_OODBBean:private] => RedBean_BeanHelperFacade Object
(
)
[fetchType:RedBean_OODBBean:private] =>
)
And then I did print_r($support->contact->ownSupportlogin) and this showed up:
Array
(
[13] => RedBean_OODBBean Object
(
[null:RedBean_OODBBean:private] =>
[properties:RedBean_OODBBean:private] => Array
(
[id] => 13
[link] => fecd4ef67e8c789efa1792f9ee0efff4
[login] =>
[password] =>
[receiveemails] => 1
[contact_id] => 109
[role] => 1
)
[__info:RedBean_OODBBean:private] => Array
(
[type] => supportlogin
[sys.id] => id
[tainted] =>
)
[beanHelper:RedBean_OODBBean:private] => RedBean_BeanHelperFacade Object
(
)
[fetchType:RedBean_OODBBean:private] =>
)
)
I can access it using: echo $support->contact->ownSupportlogin[13]->login;, but doing it dynamically seems to be a problem....

Figured it out, and will leave it up in case anyone else has a similar problem:
This will only work if you have a 1:1 relationship. Redbean populates the ownSupportlogin as an array of all supportlogin rows related to the contact. If one table can have many child tables, then you will need to loop through that array and pull out the data you want. If it is a 1:1 relationship, then you can use PHP's reset() to access the data of the first element in the array:
echo reset($support->contact->ownSupporlogin)->login;

Related

How do I get MySQL query result as nested array using PHP?

Let's say I have this simple table where pos_level is the level of the position and pos_under is that the PID of the position on top of it.
In level 1, I have 'General Manager' and 'Supervisor'.
In level 2, under 'General Manager(PID: 1)' : 'Asst. Manager', under 'Supervisor(PID: 2)' : 'Marketing'.
In level 3, under 'Asst. manager(PID: 3)' : 'Sales' & 'Purchase', under 'Marketing(PID:2) : none.
+-----+-----------------+-----------+-----------+
| PID | pos_name | pos_level | pos_under |
+-----+-----------------+-----------+-----------+
| 1 | General Manager | 1 | 0 |
| 2 | Supervisor | 1 | 0 |
| 3 | Asst. Manager | 2 | 1 |
| 4 | Sales | 3 | 3 |
| 5 | Purchase | 3 | 3 |
| 6 | Marketing | 2 | 2 |
+-----+-----------------+-----------+-----------+
Now how do I make the query so I get a nested array as the result like this:
Array
(
[0] => Array
(
[pos_level] => 1
[pos_name] => General Manager
[pos_under] => Array
(
[0] => Array
(
[pos_level] => 2
[pos_name] => Asst. Manager
[pos_under] => Array
(
[0] => Array
(
[pos_level] => 3
[pos_name] => Sales
)
[1] => Array
(
[pos_level] => 3
[pos_name] => Purchase
)
)
)
)
)
[1] => Array
(
[pos_level] => 1
[pos_name] => Supervisor
[pos_under] => Array
(
[0] => Array
(
[pos_level] => 2
[pos_name] => Marketing
[pos_under] => Array
(
)
)
)
)
)
I have tried using multiple queries and using array_push using the results, but I have like around 100+ pos_name and I think it is messy, I have also tried using loop to keep running queries for each level and under, also tried using multiple tables for each level, but I am hoping I can use only 1 table and able to query the result as the nested array above for further use in my application.
All answers, comments, and suggestions are very welcomed. Thank you.
As mentioned above in the comments I doubt in general that the approach you are following is a good one. That is because it will not scale! You try to take all entries from your database and pack them into a single, hierarchical array. That means you create several copies of each entry in memory. What will happen with a growing number of entries? You face a constantly raising memory consumption of your script which will obviously make it fail ultimately.
Nevertheless I accepted the challenge and implemented a small demonstration of how to cleverly construct such nested structures with the help of references. Such references not only simplify the creation of nested structures, they also reduce the memory footprint by preventing that entries are copied by value again and again. This however will not solve the general scaling issue with this approach mentioned above, it can only help to reduce it.
I also took the liberty to make a small modification to your approach and introduce a new property "pos_over" to hold entries under an entry. Two reasons for that:
it usually is not a good idea to remove original available data and especially not to replace it with an altered meaning
the meaning of the term "pos_under" is to describe under what other entry an given entry is (to be) placed. But from the "upper" entries point of view the ones "below" it should not be referenced by "pos_under", right? That would contradict the original meaning of that term.
The following code does not depend on a database for demonstration purpose. Instead it reads the raw data from a CSV string and parses that. The actual building of the desired structure structure is marked further down by a comment. Also it should be mentioned that the code expects the original data to reference other entries only after they have been declared. So if processed from top to bottom each entry under another one can expect that other one to already exist.
Note, that the actual code to build that nested structure consists of only a mere 12 clever lines...
<?php
// the raw CSV data
$csvText = <<<CSV
PID|pos_name|pos_level|pos_under
1|General Manager|1|0
2|Supervisor|1|0
3|Asst. Manager|2|1
4|Sales|3|3
5|Purchase|3|3
6|Marketing|2|2
CSV;
// praparation of CSV data
foreach (explode("\n", $csvText) as $csvRow) {
$csvData[] = str_getcsv($csvRow, '|');
}
$csvTitle = array_shift($csvData);
$table = [];
foreach ($csvTitle as $titleKey=>$titleValue){
foreach ($csvData as $csvRow=>$csvColumn) {
foreach ($csvColumn as $csvKey=>$csvValue) {
$table[$csvRow][$csvTitle[$csvKey]] = $csvValue;
}
}
}
// creation of the structure
$catalog = [];
$structure = [];
foreach ($table as $key=>&$entry) {
$entry['pos_over'] = [];
if ($entry['pos_under'] == 0) {
$structure[] = &$entry;
$catalog[$entry['PID']] = &$structure[count($structure)-1];
} else {
$catalog[$entry['pos_under']]['pos_over'][] = &$entry;
$catalog[$entry['PID']] = &$catalog[$entry['pos_under']]['pos_over'][count($catalog[$entry['pos_under']]['pos_over'])-1];
}
}
// demonstration output
print_r($structure);
The output of above experiment is:
Array
(
[0] => Array
(
[PID] => 1
[pos_name] => General Manager
[pos_level] => 1
[pos_under] => 0
[pos_over] => Array
(
[0] => Array
(
[PID] => 3
[pos_name] => Asst. Manager
[pos_level] => 2
[pos_under] => 1
[pos_over] => Array
(
[0] => Array
(
[PID] => 4
[pos_name] => Sales
[pos_level] => 3
[pos_under] => 3
[pos_over] => Array
(
)
)
[1] => Array
(
[PID] => 5
[pos_name] => Purchase
[pos_level] => 3
[pos_under] => 3
[pos_over] => Array
(
)
)
)
)
)
)
[1] => Array
(
[PID] => 2
[pos_name] => Supervisor
[pos_level] => 1
[pos_under] => 0
[pos_over] => Array
(
[0] => Array
(
[PID] => 6
[pos_name] => Marketing
[pos_level] => 2
[pos_under] => 2
[pos_over] => Array
(
)
)
)
)
)

How to save special array data into Three MySQL table in PHP

I have JSON which need to insert into MySQL table.
What I already did is, convert it to array using:
$json_data = json_decode($geo_json, true);
and get an output of array but I do not know how to inset into second and third MySQL table.
My MySQL Table:
Table 1:
geo_id | user_id | geo_title | geo_description | geo_date |geo_status |geo_action |action_reason | geo_json | remote_ip | map_type |geo_snapshot
I can able to insert into above table easily but problem is in table two and Three listed below.
Table 2:
id | layer_id | map_id | layer_name | user_id | draw_type | latlng | radious
Table 3:
data_id | geo_key | geo_value | map_id | layer_id
Array I am getting:
Array
(
[type] => FeatureCollection
[features] => Array
(
[0] => Array
(
[type] => Feature
[properties] => Array
(
[action] => a
[poi_name] => a
[fac_type] => 17
[ph_number] => a
[hno] => a
[postcode] => a
[mail] => a
[str_nm] => a
[photo] => developer-page.png
[comment] => a
[url] => a
[sub_loc] => a
[employee] => a
)
[geometry] => Array
(
[type] => Point
[coordinates] => Array
(
[0] => 88.434448242188
[1] => 22.510971144638
)
)
)
[1] => Array
(
[type] => Feature
[properties] => Array
(
[action] => b
[poi_name] => b
[fac_type] => 18
[ph_number] => b
[hno] => b
[postcode] => b
[mail] => b
[str_nm] => b
[photo] => 1475131600_developer-page.png
[comment] => b
[url] => b
[sub_loc] => b
[employee] => b
)
[geometry] => Array
(
[type] => Point
[coordinates] => Array
(
[0] => 88.321151733398
[1] => 22.50906814933
)
)
)
)
)
Now problem is to insert above data into two separate tables:
Table 2: This is only require to insert draw_type | latlng from above php array.
Example: draw_ type: point and latlng : coordinates
Table 3:
This is require to insert geo_key | geo_value | map_id | layer_id from above PHP array.
Example:
geo_key : properties [action,poi_name,fac_type,ph_number,hno,postcode,mail,str_nm, photo, comment, url, sub_loc, employee]
geo_value : [properties values ]
map_id :[this will be table 1 insert id]
layer_id : [this can be blank]
Please guide me and show me how to start.
$json_data["features"][$array_index]["geometry"]["type"]
For table2:
foreach($json_data["features"] as $info){
$type = $info["geometry"]["type"];
$latlng_0 = $info["geometry"]["coordinates"][0];
$latlng_1 = $info["geometry"]["coordinates"][1];
// DO INSRET with $type, $latling_0, $latling_1
$sql = "INSERT INTO Table2 (draw_type, latlng0, latlng1) VALUES ('".$type."','".$latlng_0."','".$latlng_1."')";
....
}
For table3:
Is 'map_id' a auto increment key in table1?
You'll need to know map_id first by select * where (conditions)
after successful insert data to table1
And if 'layer_id' can accept blank (null) data, it'll be fine if you don't specific value in INSERT command. Just make sure your table have correct settings.

Howto make this relation work in MYSQL or Laravel

I'm no amazing with MYSQL at all, however laravel framework has made it very easy for me to get what i need as long as i know the basics.
So this question will first aim towards the MYSQL people, because i would rather figure out how to achieve this in plain MYSQL, and then convert it into laravel queries after.
I have 4 tables that need to be used in this query, as seen below:
1. products
id | name | description | price
2. customers
id | fname | lname | email | telephone
3. orders
id | customer_id | total_price | status
4. order_items
id | order_id | product_id | quantity | price
So i am creating an orders page on my web application. On this page it will show a list of all orders, including the order_items to that particular order. It will also include which customer this order belongs to.
I have managed to achieve the above using laravel, and i get the array seen below:
Array
(
[0] => Array
(
[id] => 9
[customer_id] => 16
[total_price] => 103.96
[status] => new
[created_at] => 2016-02-24 03:06:41
[customer] => Array
(
[id] => 16
[fname] => firstname
[lname] => lastname
[email] => firstname.lastname#gmail.com
[telephone] => 07707707707
[address_line_1] => Warstone Rd, walsall
[address_line_2] => Wolverhampton
[postcode] => WV10 7LX
)
[order_item] => Array
(
[0] => Array
(
[id] => 1
[order_id] => 9
[product_id] => 44
[quantity] => 1
[price] => 50.00
)
[1] => Array
(
[id] => 2
[order_id] => 9
[product_id] => 46
[quantity] => 2
[price] => 31.98
)
[2] => Array
(
[id] => 3
[order_id] => 9
[product_id] => 48
[quantity] => 1
[price] => 7.99
)
[3] => Array
(
[id] => 4
[order_id] => 9
[product_id] => 51
[quantity] => 1
[price] => 13.99
)
)
)
)
Now the part i am having trouble with is getting the products that relate to the order_items.
So far it has worked for me because i have been doing thinking like this
$order = Order::find($id)->with('customer','orderItem')->get()->toArray();
This works easy because an order has a customer_id field and an order_items has an order_id. But for me to get the products i need to join products to order_items.
If any one is good at MYSQL and can provide me a query to study and then convert into laravel that would be great.
If anyone knows laravel 5, well this is all the laravel stuff below:
Order.php
public function customer(){
return $this->belongsTo('App\Customer');
}
public function orderItem(){
return $this->hasMany('App\OrderItem');
}
OrderItem.php
public function order(){
$this->belongsTo('App\Order');
}
public function product(){
$this->hasOne('App\Product');
}
Product.php
public function orderitem(){
$this->hasOne('App\OrderItem');
}
Customer.php
public function orders(){
$this->belongsTo('App\Order');
}
As you can see above are my modal relationships i have set up.
This is my controller where i try to get the full array.
public function show($id)
{
$order = Order::find($id)->with('customer','orderItem','product')->get()->toArray();
echo "<pre>";
print_r($order);
echo "</pre>";
}
The error i receive is:
call to undefined method Illuminate\Database\Query\Builder::product()
If i remove the ->with('customer','orderItem','product') and change it to ->with('customer','orderItem') i get the array posted above.
Does anyone know how i can achieve this please?
You are on the right part the only mistake you are doing is you are calling product on the order model which has no direct relation with it. You have to call the product model through the orderitem model like this
Order::find($id)->with('customer','orderItem.product')->get()->toArray()

Display Two tables data in Php

i have following tables
Author
id | author_name | author_detail | author_bio
books
id | author_id | book_name | book_detail
i want to display data in following way
Author Name ::
Author Detail ::
books :: 1.book1
2.book2
3.book3
4.book4
i have tried following query but didnt worked as per my requirement
select * from authors left join books on author.id=books.author_id
i have tried group concat but it gives books name with coma seperate.so i want to books detail in array
select author.author_name,author.author_detail,author.author_bio,group_concat(books.book_name) eft join books on author.id=books.author_id
i am expexting output like
Array
(
[0] => Array
(
[id] => 1
[name] => Norm
[books] => Array
(
[0] =>Array
(
[id] => 4
[book_name] => great wall
[created_at] => 2015-09-11 04:45:07
[updated_at] => 2015-09-11 04:45:07
)
[1] =>Array
(
[id] => 6
[book_name] =>new book
[created_at] => 2015-09-11 04:45:07
[updated_at] => 2015-09-11 04:45:07
)
)
)
[1] => Array
(
[id] => 2
[name] => Norm
[books] => Array
(
[0] =>Array
(
[id] => 2
[book_name] => amazing star
[created_at] => 2015-09-11 04:45:07
[updated_at] => 2015-09-11 04:45:07
)
[1] =>Array
(
[id] => 3
[book_name] =>way of journy
[created_at] => 2015-09-11 04:45:07
[updated_at] => 2015-09-11 04:45:07
)
)
)
i have checked this question also
displaying php mysql query result with one to many relationship
Can any one help me how to display data like above ?
thank you
Try this:
SELECT
A.id
A.author_name,
A.author_detail,
A.author_bio,
B.book_name,
B.created_at,
B.updated_at
FROM books AS B
LEFT JOIN author AS A
ON (A.id=B.author_id)
you will get result like this:
id | author_name | author_detail | author_bio | book_name
1 | ari | some detail | some bio | book_ari_1
1 | ari | some detail | some bio | book_ari_2
1 | ari | some detail | some bio | book_ari_3
2 | tester | some detail | some bio | book_tester_1
etc..
to make array as your expecting result you need to restructure your array result. i will asume your result array will be in $result variable
$new_result = array();
foreach ($result as $key => $value) {
if (empty($new_result[$value['id']]))
{
$new_result[$value['id']] = array(
'id' => $value['id'],
'name' => $value['name'],
'books' => array(
array(
'id' => $value['id'],
'book_name' => $value['book_name'],
'created_at' => $value['created_at'],
'updated_at' => $value['updated_at']
),
)
)
}
else
{
$new_result[$value['id']]['id'] = $value['id'];
$new_result[$value['id']]['name'] = $value['name'];
$new_result[$value['id']]['books'][] = array(
'id' => $value['id'],
'book_name' => $value['book_name'],
'created_at' => $value['created_at'],
'updated_at' => $value['updated_at']
);
}
}
the result will look like your expected. but the key number will be formated as id.
to reset key of $new_result as increment number you need to get only value use array_values() function
$new_result = array_values($new_result);
You could do it with your first query...but you'd have to check the author_id inside the record loop and show the author details only whenever the value changed (by comparing it with a value stored in a variable)...otherwise only show the book details.
So your code might (very roughly) look like this:
$query = "select whatever whatever...";
$records = $database->Execute($query);
foreach ($records as $fields) {
if ($fields['id'] != $previous_id) echo "Author ...";
echo "Book whatever whatever ...";
$previous_id = $fields['id'];
}
A more straightforward (although slightly longer) way would be to have a second query: a sub-query. And it would take place inside the loop through the results of the first (outer) query. So your outer query gets the authors and, after you show the author details, you have this separate query for books of the author...and you have a loop-within-the-outer-loop to show the details of each book.
So your code (very roughly) looks something like this:
$query = "select id, author_name, whatever from author";
$author_records = $database->Execute($query);
foreach ($author_records as $fields) {
echo "Author: {$fields['author_name']} whatever <br/>";
$subquery = "select whatever from books where id = whatever";
$book_records = $database->Execute($subquery);
foreach ($book_records as $otherfields) {
echo "Book whatever whatever";
}
}
you can do this in php no need to go in query itself but take both data in separate query i.e. books and author data
Remember i assumed $result as authors data and $result2 as books data
$item=array();
while($row=mysql_fetch_array($result))
{
$id=$row['id'];
$item[$id]['name']=$row['name'];
$item[$id]['id']=$row['id'];
$item[$id]['books']=array();
$temp=array();
while($row1=mysql_fetch_array($result2))
{
if($id==$row1['author_id'])
{
$temp['id']=$row1['id'];
$temp['book_name']=$row1['book_name'];
$temp['created_at']=$row1['created_at'];
$temp['updated_at']=$row1['updated_at'];
array_push($item['id']['books'],$temp);
}
}
}
Now here id is formatted as author's id. To get like array keys you can use array_values($item)

mySQL select with conditions replyTo

I know how to retrieve the comments for each posts, but now I'm trying to do my own system 'reply to'. When someone replying, I store the comment id as reply_id in new comment.
$sql = 'SELECT cid, cname, user_uid, reply_id,
published, content, avatar
FROM comments, users
WHERE report < 3 AND (uid = user_uid AND post_pid='.$id.')
OR ( user_uid ="_'.$id.'" AND post_pid='.$id.')';
this request return me this list of comments:
Array
(
[0] => stdClass Object
(
[cid] => 101
[cname] => ramzan
[user_uid] => 1
[reply_id] => 100
[published] => 2013-12-08 01:44:56
[content] => why?
[avatar] => users/anonyme.png
)
[1] => stdClass Object
...
but I want to get something like this :
Array
(
[0] => stdClass Object
(
[cid] => 101
[cname] => ramzan
[user_uid] => 1
[reply_id] => array() // the reply if exist
[published] => 2013-12-08 01:44:56
[content] => why?
[avatar] => users/anonyme.png
)
maybe this is a bad idea to do like this, but I don't know how to do otherwise!!!
maybe someone can help this, I resolved my problem like this :
lvl1, lvl2 have to be declare as null, only set the value of field when someone reply to a comment
...SELECT field FROM table where ...
ORDER BY COALESCE (lvl1, lvl2, id ), lvl1, lvl2, id
...
Thank you,
Best regards

Categories