Essentially, I am trying to format the follow:
I have a series of users, that are part of different communities and each community has a series of tasks to complete BUT some of the tasks within the community are only related to some users. Like so:
Community 1
Members: Joe, James
Tasks: Task 1, Task 2, Task 3
Assigned: Task 1 -> Joe, Task 3 -> James
Community 2:
Members: James
Tasks: Talk 1, Task 14, Task 15
Assigned: Task 1 -> Joe, Task 14 -> James
So essentially. Joe has to complete Task 1, and James has to complete Task 3.
I need a array (that can be encoded to json) that stores the community ID as well as all of the tasks that they have completed but, it should be easily accessible to get the community and the tasks that they have completed.
I have a list of communities that currently exist, and I would like to show all of tasks that have been completed (by the specific user) depending on the community id, as well as this, I also want to add and delete things from the "tasks" category, so need a way to easily get access to these members
I have come up with the following so far:
$progress = array (
"communities" => array(
"id" => 1,
"tasks" => array(
1 => "completed",
2 => "completed"
),
"id" => 2,
"tasks" => array(
150 => "completed",
140 => "completed"
)
),
);
But I don't know if this is the right style of array for this, since, I don't know how complex it will be when I need to add/remove or show the total amount of tasks left for a communities
UPDATE:
This array I'm working with now:
$x = array(
1 => array(
1,
2,
3,
4,
),
2 => array(
3,
5,
6,
10
)
);
Then produces this kind of JSON:
{"1":[1,2,3,4],"2":[3,5,6,10]}
Is this somewhere right? Will I be able to add and delete nodes, as well as add top layer sections to this?
Code sample as a reply to your comment
$progress = array (
"communities" => array(
1 => array(
"tasks" => array(
1 => array("status" => "completed", "assigned_users" => array("James", "Joe")),
2 => array("status" => "pending", "assigned_users" => array("James"))
),
),
2 => array(
//Content of task2
)
)
);
With an extended model like this, you'll be able to:
assign a task to one user or more
remove a user from a specific task
know which users are busy or available
count tasks and getting resources (users) assigned
Getting the task 1 of the first community
echo $progress['communities'][1]['tasks'][1];
Walk the communities collection
foreach ($progress['communities'] as $c) {
//Browse the tasks
foreach ($c['tasks'] as $t) {
var_dump($t);
}
}
Related
I am trying to merge two results of two queries in MYSQL using PHP, but I am puzzled how to do it! I am using PDO. I am programming for a hobby and am trying to make a to do list app just like a Trello board. However, I just can't figure out how to merge two results from different tables in a database.
The idea is as follows:
I have a table called 'task_lists' with the content:
'list_id => 1, list_name = 'listOne'
'list_id => 2, list_name = 'listTwo'
And a table called 'tasks':
task_id => 1, list_id => 1, task_name => 'taskOfListOne', duration => 5, is_done => 1
task_id => 2, list_id => 1, task_name => 'anotherTaskOfListOne', duration => 5, is_done => 1
task_id => 3, list_id => 2, task_name => 'taskOfListTwo', duration => 10, is_done => 0
And I am trying to create an array that is merged between the two results as something like:
(I know this is a rough picture of how the array is supposed to look like)
$result = [array]
[list_id] = 1, [list_name] = 'listOne' =>
[array][list_id] = 1, ['task_name] = taskOfListOne,[duration] = 5, ['is_done'] => 1
[array][list_id] = 1, ['task_name] = anotherTaskOfListOne,[duration] = 5, ['is_done'] => 1
[list_id] = 2, [list_name] = 'listTwo' =>
[array][list_id] = 2, ['task_name] = taskOfListTwo,[duration] = 5, ['is_done'] => 1
Is this even possible? I have tried a Union sql query and methods like nested foreach statements, but none of them worked for me. Am I missing something here?
PS: Sorry for my bad english.
Have you tried a left join?
SELECT TL.`list_id`, TL.`list_name`, T.`task_name`, T.`duration`
FROM task_lists AS TL
LEFT JOIN tasks as T ON TL.`list_id` = T.`list_id`
And then in PHP you build the array in the format you want.
Later edit:
Simple PHP example to parse SQL data as you asked (to remove duplicated info):
<?php
// $mysql_rows -> here is your query result, fetched as associative array
$filtered_array = array();
foreach ($mysql_rows as $row){
// Initiate record if is not already initiated
if (!isset($filtered_array[ $row['list_id'] ])){
$filtered_array[ $row['list_id'] ] = array(
'list_id' => $row['list_id'],
'list_name' => $row['list_name'],
'tasks' => array()
);
}
// Add tasks
$filtered_array[ $row['list_id'] ]['tasks'][] = array(
'task_name' => $row['task_name'],
'duration' => $row['duration'],
'is_done ' => $row['is_done ']
);
}
// Optional: if you want to remove list_id from $filtered_array key names, uncomment the next line
// $filtered_array = array_values($filtered_array);
?>
How can I convert the data I send with post to php code?
I have 3 select fields. adult, child, baby.
I want to create the following json structure up to the number of rooms when I post. The number of children and babies is not correct by area. How can I do it?
foreach ($this->input->post('adult') as $key => $value) {
$rooms[] = array(
'adult' => $_POST['adult'][$key],
'child' => array(
'child_total' => $_POST['child'][$key],
'child_date' => $_POST['child_date']
),
'baby' => array(
'baby_total' => $_POST['baby'][$key],
'baby_date' => null
)
);
}
I want to this json...
rooms: [
{
adult: 2,
child: [
child_total: 1
child_date: [
"2017-08-10"
],
],
baby: [
baby_total: 1
baby_date: [
"2017-07-01"
],
],
},
{
adult: 1,
child: [
child_total: 2
child_date: [
"2017-08-08",
"2017-08-09"
],
],
baby: [
baby_total: 2
baby_date: [
"2017-06-08",
"2017-05-09"
],
],
}
],
To figure out the data structure needed to make you json encoded string, let's start by defining the objects you're working with. Assuming this is something like a hotel booking system, let's map it out:
A hotel has rooms. They are identified by room number. This can be illustrated in code by $room[$room_number]. Using the room number as the key allows you to uniquely identify a particular room.
Each room has occupants: adults, children, and babies. This can be illustrated in code by
$room[$room_number]['adults']
$room[$room_number]['children']
$room[$room_number]['babies']
The set of babies can be illustrated as $baby[]. We really don't need to identify the baby with a unique identifier other that the index number; we're just interested in the list.
So, let's replace ['babies'] with ['baby'][]
$room[$room_number]['adults']
$room[$room_number]['children']
$room[$room_number]['baby'][]
Each baby has attributes. We're only going to use one, but for the sake of example, let's say we want to record two: birthdate and name. Another way of saying that would be each $baby = array('birthday'=>$birthdate, 'name'=>$name);
This is a little harder to illustrate, since you have to gather all the babies information before you assign it to $room[$room_number]['baby'][]. So I will show it using the index number:
$room[$room_number]['adults']
$room[$room_number]['children']
$room[$room_number]['baby'][0]['birthdate']
$room[$room_number]['baby'][0]['name']
The same functionality is desired for children:
$room[$room_number]['adults']
$room[$room_number]['children'][0]['birthdate']
$room[$room_number]['children'][0]['name']
$room[$room_number]['baby'][0]['birthdate']
$room[$room_number]['baby'][0]['name']
See a pattern? [identifier][attribute][identifier][attribute]
With this data structure, we can build your html inputs, assuming 2 children and 2 babies:
<?php
// assuming room number is 123
$room_number = '123';
?>
<!-- child 1 name -->
<label><input name="room[<?= $room_number ?>]['child'][0]['name']">Child 1 name</label>
<!-- child 1 birthdate -->
<label><input name="room[<?= $room_number ?>]['child'][0]['birthdate']">Child 1 birthdate</label>
<!-- child 2 name -->
<label><input name="room[<?= $room_number ?>]['child'][1]['name']">Child 2 name</label>
<!-- child 2 birthdate -->
<label><input name="room[<?= $room_number ?>]['child'][1]['birthdate']">Child 2 birthdate</label>
When you receive these inputs in your php script, it will already be properly formed as an array (I'm excluding adults and filled in sample values):
php > $room_number='123';
php > $room[$room_number]['child'][0]['birthdate'] = '20010-01-01';
php > $room[$room_number]['child'][0]['name'] ='Junior';
php > $room[$room_number]['child'][1]['birthdate'] = '2019-01-01';
php > $room[$room_number]['child'][1]['name'] = 'Bubba';
php > print_r($room);
Array
(
[123] => Array
(
[child] => Array
(
[0] => Array
(
[birthdate] => 20010-01-01
[name] => Junior
)
[1] => Array
(
[birthdate] => 2019-01-01
[name] => Bubba
)
)
)
)
This can easily be fed into json_encode: print json_encode($room);
However, you might ask what about the counts (totals)?
Those can easily be figured from the array structure, so they don't really need to be included:
php > print count($room[$room_number]['child']);
2
php >
You can use the json_encode function like this:
json_encode(['rooms' => $rooms])
i.e : i have 2 tables
Product ( id, name )
Photo ( id, name, photo_id )
And I need to get result in array like this:
array(
'id' => 1,
'name' => product,
'photos' => array(
array('id' => 1, 'name' => 'photo1')
array('id' => 2, 'name' => 'photo2')
)
}
Is it possible in PHP using clear SQL?
I know that is possible to get 2 arrays and connect it but I have many records and I dont want to wase time to quering.
You have to add a foreign_key in your photo table "product_id".
Then create a method getPhotos() in your Product class with will collect all photos for your product.
Is it possible in PHP using clear SQL?
Not in a single SQL call. With a single call, this is the closest you can get:
array(
'id' => 1,
'name' => product,
'photo_id' => 1,
'photo_name' => 'photo1')
),
array(
'id' => 1,
'name' => product,
'photo_id' => 2,
'photo_name' => 'photo2')
)
Your only choice for the format you want is to run queries separately or to combine them into the data structure you want.
As mentioned, this is not possible with SQL. SQL is based on the relational model which is a 1-Normal-Form data model. That means, the result relation is also flat (no nested relations in a relation).
However, there are good frameworks which generate intermediary models in your corresponding target language (e.g. Python, Java, ...) that circumvent the impression of a flat data model. Check for example Django.
https://docs.djangoproject.com/en/1.8/topics/db/models/
Moo
Continuing this question,
in my web app, I want to allow users to add friends, like facebook, in my previous question, I finally decided to have the database structure as #yiding said:
I would de-normalize the relation such that it's symmetric. That is,
if 1 and 2 are friends, i'd have two rows (1,2) and (2,1).
The disadvantage is that it's twice the size, and you have to do 2
writes when forming and breaking friendships. The advantage is all
your read queries are simpler. This is probably a good trade-off
because most of the time you are reading instead of writing.
This has the added advantage that if you eventually outgrow one
database and decide to do user-sharding, you don't have to traverse
every other db shard to find out who a person's friends are.
So, now if user 1 adds user 2, and user 5 adds 2, something like this will go into the db:
ROW_ID USER_ID FRIEND_ID STATUS
1 1 2 0
2 2 1 0
3 5 2 0
4 2 5 0
As you see, we insert the row of the "REQUEST SENDER" first, so now imagine that user 5 is logged in, and we want to show him the friendship requests, here is my query:
$check_requests = mysql_query("SELECT * FROM friends_tbl WHERE FRIEND_ID = '5'");
the above query, will fetch ROW_ID = 4, this means with the above query shows us that user 2 has added 5, but he has NOT, actually the user 5 added user 2, so here we should not show any friendship requests for user 5, instead we need to show it for user 2.
How I'm supposed to check this correctly?
This is an edited answer.
Your SQL query should look like this:
SELECT USER_ID, FRIEND_ID FROM friends_tbl WHERE FRIEND_ID = '5' OR USER_ID = '5'
Then you have to parse your result in this way. Assuming you have got a php array like this:
$result = array(
0 => array(
'USER_ID' => 5,
'FRIEND_ID' => 2
),
1 => array(
'USER_ID' => 2,
'FRIEND_ID' => 5
)
2 => array(
'USER_ID' => 5,
'FRIEND_ID' => 8
),
3 => array(
'USER_ID' => 8,
'FRIEND_ID' => 5
)
)
You just have to get the even rows:
$result_final = array();
for($i = 0; $i < count($result); $i++) {
if($i % 2 == 0) $result_final[] = $result[$i];
}
Then you will have an array like this:
$result = array(
0 => array(
'USER_ID' => 5,
'FRIEND_ID' => 2
),
1 => array(
'USER_ID' => 5,
'FRIEND_ID' => 8
)
)
Alternative method: Make your SQL look like this:
SELECT FRIEND_ID FROM friends_tbl WHERE USER_ID = '5'
That's all.
Friendship query notifies should be placed in something like message inbox. Relation you described is meant to hold, well, friendship relations, not the fact of the event happening itself. You should consider create relation to hold notifies and fill it properly alongside with two inserts on friends_tbl
You'll need to hold a temporary table (or fixed - for data mining) which has all the requests made from one user to another, for example:
table: friendRequest
inviterId inviteeId status tstamp
2 5 0 NOW()
5 8 0 NOW()
assuming that 0 is unapproved.
Than you'll query for all pending requests
SELECT * FROM friendRequest WHERE invitee_id = :currentLoggedUserId AND status = 0
Once a user approved a user, you'll create a transaction, describing this newly formed relation and updating the friendRequests table
You could also query this way assymetric relations, where a user has many followers, by looking for un-mutual friendships.
I have a HABTM relationship between two tables: items and locations, using the table items_locations to join them.
items_locations also stores a bit more information. Here's the schema
items_locations(id, location_id, item_id, quantity)
I'm trying to build a page which shows all the items in one location and lets the user, through a datagrid style interface, edit multiple fields at once:
Location: Factory XYZ
___________________________
|___Item____|___Quantity___|
| Widget | 3 |
| Sprocket | 1 |
| Doohickey | 15 |
----------------------------
To help with this, I have a controller called InventoryController which has:
var $uses = array('Item', 'Location'); // should I add 'ItemsLocation' ?
How do I build a multidimensional form to edit this data?
Edit:
I'm trying to get my data to look like how Deceze described it below but I'm having problems again...
// inventory_controller.php
function edit($locationId) {
$this->data = $this->Item->ItemsLocation->find(
'all',
array(
"conditions" => array("location_id" => $locationId)
)
);
when I do that, $this->data comes out like this:
Array (
[0] => Array (
[ItemsLocation] => Array (
[id] => 16
[location_id] => 1
[item_id] => 1
[quantity] => 5
)
)
[1] => Array (
[ItemsLocation] => Array (/* .. etc .. */)
)
)
If you're not going to edit data in the Item model, it probably makes most sense to work only on the join model. As such, your form to edit the quantity of each item would look like this:
echo $form->create('ItemsLocation');
// foreach Item at Location:
echo $form->input('ItemsLocation.0.id'); // automatically hidden
echo $form->input('ItemsLocation.0.quantity');
Increase the counter (.0., .1., ...) for each record. What you should be receiving in your controllers $this->data should look like this:
array(
'ItemsLocation' => array(
0 => array(
'id' => 1,
'quantity' => 42
),
1 => array(
...
You can then simply save this like any other model record: $this->Item->ItemsLocation->saveAll($this->data). Adding an Item to a Location is not much different, you just leave off the id and let the user select the item_id.
array(
'location_id' => 42, // prepopulated by hidden field
'item_id' => 1 // user selected
'quantity' => 242
)
If you want to edit the data of the Item model and save it with a corresponding ItemsLocation record at the same time, dive into the Saving Related Model Data (HABTM) chapter. Be careful of this:
By default when saving a HasAndBelongsToMany relationship, Cake will delete all rows on the join table before saving new ones. For example if you have a Club that has 10 Children associated. You then update the Club with 2 children. The Club will only have 2 Children, not 12.
And:
3.7.6.5 hasAndBelongsToMany (HABTM)
unique: If true (default value) cake will first delete existing relationship records in the foreign keys table before inserting new ones, when updating a record. So existing associations need to be passed again when updating.
Re: Comments/Edit
I don't know off the top of my head if the FormHelper is intelligent enough to autofill Model.0.field fields from a [0][Model][field] structured array. If not, you could easily manipulate the results yourself:
foreach ($this->data as &$data) {
$data = $data['ItemsLocation'];
}
$this->data = array('ItemsLocation' => $this->data);
That would give you the right structure, but it's not very nice admittedly. If anybody has a more Cakey way to do it, I'm all ears. :)