Generating JSON Query Result in Codeigniter - php

So i have database table named usermeta and have table structure like this :
-----------------------------------------------------------
| ummeta_id | user_id | meta_key | meta_value |
-----------------------------------------------------------
| 1 | 1 | fullname | John Doe |
| 2 | 1 | birthplace | New York |
| 3 | 1 | birthdate | 1990/01/01 |
| 4 | 1 | mobile | 0812-3456-7890 |
| 5 | 1 | email | john.doe#mail.com |
| 6 | 2 | fullname | Jon Wick |
| 7 | 2 | birthplace | Washington DC |
| 8 | 2 | birthdate | 1985/10/21 |
| 9 | 2 | mobile | 0890-1234-5678 |
| 10 | 2 | email | wickjohn#mail.com |
And i try to generate json data for all data from this database using Codeigniter (v 3.1.9) using Controller and Model.
This is my Model (model name: db_usermeta)
function userslist()
{
$query = $this->db->select('*')
->from('usermeta')
->get();
return $query->result();
}
This is my Controller
public function userlist()
{
header('Content-Type: application/json; charset=utf-8');
$query = $this->db_usermeta->userslist();
$json_data = array();
foreach ($query as $key)
{
$json_data[$key->meta_key] = $key->meta_value;
}
echo json_encode($json_data);
}
The result when i open using my browser to check the json data using web developer tool is only show last record, in this case only show data from user_id 2, like this:
{
"fullname":"John Wick",
"birthplace":"Washinton DC",
"birthdate":"1985/10/21",
"mobile":"0890-1234-5678",
"email":"wickjohn#mail.com"
}
What I want to achieve is to show all json data nested like this:
"data": [
{
"fullname":"John Doe",
"birthplace":"New York",
"birthdate":"1990/01/01",
"mobile":"0812-3456-7890",
"email":"john.doe#mail.com"
},
{
"fullname":"John Wick",
"birthplace":"Washinton DC",
"birthdate":"1985/10/21",
"mobile":"0890-1234-5678",
"email":"wickjohn#mail.com"
}
]
How can i achieve this? Did I make a mistake on my controller and model. I really appreciate your help.

your $key->meta_key is overwriting for every record. that's why only last record appeared. You don't actually need to loop through to get json data.
public function userlist()
{
header('Content-Type: application/json; charset=utf-8');
$query = $this->db_usermeta->userslist();
$json_data = array(array());
$user_id_map = array();
$index = 0;
foreach ($query as $key)
{
if(!isset($user_id_map[$key->user_id])){
$user_id_map[$key->user_id] = $index++;
}
$currentIndex = $user_id_map[$key->user_id];
$json_data[$currentIndex][$key->meta_key] = $key->meta_value;
}
echo json_encode($json_data);
}
just change your controller code to this and this will return json data.

Since the meta key fullname is same for both records, you need to change the key name to something unique
foreach ($query as $key)
{
$json_data[$key->meta_key] = $key->meta_value;
}
Change $json_data[$key->meta_key] to $json_data[$key->meta_key.$key->user_id]
or simply change it to $json_data[$key->ummeta_id]

Related

Query to group by the contents of the field

I need help to make query to group by content of field. I have the following Database:
+----+--------------+-----------------+------------------------------+
| id | depart_kode | depart_task | value |
+----+--------------+-----------------+------------------------------+
| 1 | 001 | Create Profil | Some Value |
| 2 | 001.12 | Create Profil | Some Value |
| 3 | 001.452 | Create Profil | Some Value |
| 4 | 002.914 | Create Profil | Some Value |
| 5 | 002 | Create Profil | Some Value |
| 6 | 003 | Create Profil | Some Value |
+----+--------------+-----------------+------------------------------+
I need to make a query where I group by depart_kode and I should print by the first 3 digits like this in format json
"001":[
{
"depart_kode":"001,
and other
},
{
"depart_kode":"001.12"
},
],
"002":[
{
"depart_kode":"002"
}
]
something like that, most importantly they will be grouped in an array based on the first 3 numbers like 001.
and json just an example, which I want to split into an array based on the first 3 digits
Something like this?
$departs = [];
foreach ($sqlRows as $row) {
$departKey = substr($row['depart_kode'], 0, 3);
if (!array_key_exists($departKey, $departs)) {
$departs[$departKey] = [];
}
$departs[$departKey][] = $row['depart_kode'];
}
Working example.
references
substr - get a specific part of a string (first 3 chars in our example)
array_key_exists - checks if the key in an array exists

Inner join 3 different tables codeigniter

I need to join three tables that acquires each other (not centralized to just a table)
1st table: attendance
---------------------------------------------------------------
| id | emp_code | emp_name | date | time |
| 001 | TNY | Tony |01.01.2001| 07.00 |
| 002 | PPR | Pepper |01.01.2001| 07.50 |
---------------------------------------------------------------
2nd table: employee
---------------------------------------------------------
| emp_code | emp_name |division_code| address |
| TNY | Tony | D001 | New york |
| PPR | Pepper | D002 | California|
---------------------------------------------------------
3rd table: division
-----------------------------
|division_code|division_name|
| D001 | Finance |
| D002 | Marketing |
-----------------------------
The result i want to get would be:
-----------------------------------------------------------------------------
| id | emp_code | emp_name |division_name| date | time |
| 001 | TNY | Tony | Finance |01.01.2001| 07.00 |
| 002 | PPR | Pepper | Marketing |01.01.2001| 07.50 |
-----------------------------------------------------------------------------
My code from my model:
function ShowData()
{
$this->db->select('attendance.emp_code, attendance.emp_name,division.division_name,attendance.date,attendance.time');
$this->db->from('attendance');
$this->db->join('employee', 'employee.emp_code = attendance.emp_code');
$this->db->join('division', 'employee.division_code = division.division_code');
$query = $this->db->get();
}
The result of my code is nothing, no data is shown, and i think it is because of my query
Your method isn't returning anything:
$this->db->selct('a.id, a.emp_code, a.emp_name, d.divison_node, a.date, a.time');
$this->db->join('employee AS e', 'e.emp_code = a.emp_code');
$this->db->join('division AS d', 'd.division_code = e.division_code');
return $this->db->get('attendance AS a')->result();
Your code is missing the final data getter:
function ShowData()
{
$this->db->select('attendance.emp_code, attendance.emp_name,division.division_name,attendance.date,attendance.time');
$this->db->from('attendance');
$this->db->join('employee', 'employee.emp_code = attendance.emp_code');
$this->db->join('division', 'employee.division_code = division.division_code');
$query = $this->db->get();
$data = $query->result_array(); // here will be stored the selected data as an array
}
The $this->db->get(); just creates an SQL statement using the CI query builder and executes it, it does not return the SQL output data, you just receive an object of the query itself.
But $query->result_array(); gets the SQL output data and formates the data for you - to an array in this case.
If you want to return the data, just add this line to your function body:
return $data;

How can I join into insert statement?

Here is my table structure:
// pages
+----+-----------------------+--------+
| id | path | method |
+----+-----------------------+--------+
| 1 | list_role | get |
| 2 | make_role | post |
| 3 | edit_role/id | get |
| 4 | list_voucher/activate | get |
| 5 | list_voucher/activate | post |
| 6 | expire_voucher/id | get |
+----+-----------------------+--------+
// role_page
+---------+---------+
| role_id | page_id |
+---------+---------+
Now I want to insert multiple rows into role_page table according to this array: (noted that I have $role_id)
$arr = [['list_role', 'get'], ['list_voucher/activate', 'get']]
$role_id = 4; // for example
So the expected output is:
// role_page
+---------+---------+
| role_id | page_id |
+---------+---------+
| 4 | 1 |
| 4 | 4 |
+---------+---------+
How can I do that by a join?
Currently I do that by a loop on $arr like this:
$role_id = 4;
foreach($arr as $row) {
// match the page id
$page_id = pages::where('path', row[0])->where('method', row[1])->first();
// insert
$role_page = new role_page;
$role_page->role_id = $role_id;
$role_page->page_id = $page_id;
}
Try this
Page Model (you may have to customize this relation)
public function roles(){
return $this->belongsToMany(Role::class, 'role_page', 'page_id', 'role_id')
}
Then
$arr = [['list_role', 'get'], ['list_voucher/activate', 'get']]
$role_id = 4; // for example
$query = Page::query();
foreach ($arr as $page){
$query = $query->orWhere(function($query){
$query->where('path', $page[0])->where('method', $page[1]);
}
}
$pages =$query->get();
foreach($pages as $page){
$page->roles()->attach($role_id);
}
$page_id = pages::where('path', row[0])->where('method', row[1])->first();
This returns an object.
$page_id = pages::where('path', row[0])->where('method', row[1])->first()->id;
This will return just the id.
And then in your foreach you can:
role_page::create([
'page_id' => $page_id,
'role_id' => $role_id
]);
You do have to explicitly state in your role_page model that it's not plural if your not refering to it in a relationship way:
protected $table = 'role_page';

Eloquent Relations With Multiple Columns

So I have the following match table which contains the numbers of the teams that participated in that match. I want to set up a relationship with the teams which looks something like this:
Teams Table
| id | number | name | etc |
| 1 | 1234 | Example | etc |
| 2 | 2345 | Example | etc |
etc...
Matches Table
| id | match | red1 | red2 | blue1 | blue2 |
| 1 | 1 | 1234 | 1710 | 673 | 2643 |
| 2 | 2 | 2345 | 1677 | 4366 | 246 |
etc...
I want to have something like $this->match->where("match", "=", "2")->first()->teams();.
I have tried using hasMany() but I can't seem to get to use the red1, red2, blue1, blue3 columns.
What I have tried:
class Matches extends Model
{
protected $table = "match_table";
protected $fillable = [
"match_id",
"time",
"bluescore",
"redscore",
"red1",
"red2",
"red3",
"blue1",
"blue2",
"blue3",
];
public function teams()
{
return $this->hasMany("App\Models\Teams", "number", ["red1", "red2", "blue1", "blue2"]);
}
}
What I ended up doing was just looping through each column I wanted and then just returning a new Collection with the results in it.
public function teams()
{
$result = [];
foreach($this::$teamColumns as $column) {
$result[] = $this->hasMany("App\Models\Teams", "number", $column)->first();
}
return new Collection($result);
}

Json encode for nested data using PDO PHP

I have following tables:
+---------+-----------+ +----------+---------+-------------+
| item_id | item_name | | image_id | item_id | image_url |
+---------+-----------+ +----------+---------+-------------+
| 1 | phone | | 1 | 1 | http://url1 |
| 2 | computer | | 2 | 1 | http://url2 |
| 3 | keyboard | | 3 | 2 | http://url2 |
+---------+-----------+ +----------+---------+-------------+
What should I do in php using PDO and json encode to have the following ouput:
[
{
"item_id":"1",
"name":"phone",
"images": [
{
"image_id":"1",
"url":"http://url1"
},
{
"image_id":"2",
"url":"http://url2"
}
]
},
{
"item_id":"2",
"name":"computer",
"images": [
{
"image_id":"3",
"url":"http://url3"
}
]
},
{
"item_id":"3",
"name":"keyboard",
"images": []
}
]
Do I HAVE to use foreach inside foreach loop to get this result?
No, use a single loop, and a single SQL query.
Firstly the SQL query is
SELECT im.image_id, im.image_url, im.item_id
it.item_name
FROM images im
LEFT JOIN items it ON it.item_id=im.item_id
ORDER BY im.item_id, im.image_id
And your PHP (paraphrased) is:
$lastItemId = -1;
$aJson = array();
while ($row = GetNextRow()) { // Depends on your class
$itemID = $row['item_id'];
if (!isset($aJson[$itemID])) {
$aJson[$itemID] = array('item_id'=$itemID, 'item_name'=$row['item_name'], images=>array());
}
$aJson[$itemID]['images'] = array('image_id'=>$row['image_id'], 'image_url'=>$row['image_url']);
}
echo json_encode($aJson);
You should be able to tweak from there?

Categories