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';
Related
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]
Here is my table structure:
// tickets
+----+------------+----------------------+--------+---------+-------------------+
| id | subject | content | closed | user_id | unique_product_id |
+----+------------+----------------------+--------+---------+-------------------+
| 1 | subject1 | question1 | 0 | 123 | 2 |
+----+------------+----------------------+--------+---------+-------------------+
// unique_product
+----+---------------+------------+
| id | serial_number | product_id |
+----+---------------+------------+
| 1 | 2342rd34fc | 3 |
| 2 | fg34gt4r5t | 1 |
| 3 | 34ffvv4et6 | 3 |
+----+---------------+------------+
// products
+----+--------------+
| id | name |
+----+--------------+
| 1 | Router-rb51 |
| 2 | Switch-sfx2 |
| 3 | Router-rb300 |
+----+--------------+
Now I have a collection of tickets like this:
$tickets = tickets::where(user_id, "$user_id")->get();
foreach( $tickets as $ticket ){
$ticket->{I need to get the name of product here}
}
I can write a relation in the tickets model like this:
public function unique_product()
{
return $this->hasOne(unique_product::class, 'id', 'unique_product_id');
}
And I need one more relation to the products table for getting the name of product (i.e. Switch-sfx2). How should I write that relation?
$tickets = tickets::where(user_id, "$user_id")->with('unique_product.product')->get();
You can take advantage eager loading using with().
but for using with('unique_product.product') You have to define the relation ships between unique_products and products.
In your UniqueProduct model create a new relationship
public function product()
{
return $this->BelongsTo(Product::class, 'id', 'product_id');
}
After that you can access the column of a name like
foreach( $tickets as $ticket ){
$ticket->unique_product->product->name
}
Whenever i try to insert data, the fields of the two of the columns are null. ONLY the auto incremented(of course)MainReqID and the last column had the fields.
Here's my Controller..
public function insert_main($data,$orgs){
$this->db->insert('insert_main',$data);
$getID = $this->db->insert_id();
$ctr=1;
$insertorg = array();
foreach($i=0; $i<count($orgs); $i++){
$insertorg[] = array(
'OrgID'=>$ctr[$i],
'MainID'=>$getID[$i],
'Level'=>'1234'[$i]
);
$ctr++;
}
$this->db->insert_batch('insert_mainreq',$insertorg);
}
here's what it looks like in database...
MainReqID | OrgID | MainID | Level
1 | null | null | 1234
2 | null | null | 1234
3 | null | null | 1234
4 | null | null | 1234
5 | null | null | 1234.. and so on..
i need something like this..
MainReqID | OrgID | MainID | Level
1 | 1 | 3 | 1234
2 | 2 | 3 | 1234
3 | 3 | 3 | 1234
4 | 4 | 3 | 1234
5 | 5 | 3 | 1234.. and so on..
It looks like $getID is not an array but you are adding $getID[i]. This surely will not work. The same with $ctr. This is an integer but you are trying $ctr[i]. The same thing is happening with Level.
public function insert_main($data,$orgs){
$this->db->insert('insert_main',$data);
**$getID** = $this->db->insert_id();
**$ctr=1;**
$insertorg = array();
foreach($i=0; $i<count($orgs); $i++){
$insertorg[] array(
'OrgID'=>**$ctr[$i]**,
'MainID'=>**$getID[$i]**,
'Level'=>**'1234'[$i]**
);
$ctr++;
}
$this->db->insert_batch('insert_mainreq',$insertorg);
}
You could try this, I am not sure what you are trying to do with OrgId and MainID but:
public function insert_main($data,$orgs){
$this->db->insert('insert_main',$data);
$getID = $this->db->insert_id();
$insertorg = array();
foreach($i=0; $i<count($orgs); $i++){
$insertorg[] array(
'OrgID'=> $i,
'MainID'=>$getID,
'Level'=>'1234'
);
}
$this->db->insert_batch('insert_mainreq',$insertorg);
}
Keep in mind that $this->db->insert_id(); will return the id of the last row inserted if there are more than one row.
Try This Code:
public function insert_main($data,$orgs){
$this->db->insert('insert_main',$data);
$getID = $this->db->insert_id();
$insertorg = array();
foreach($i=0; $i<count($orgs); $i++)
{
$insertorg[] = array(
'OrgID'=> $i,
'MainID'=>$getID,
'Level'=>'1234'
);
}
$this->db->insert_batch('insert_mainreq',$insertorg);
}
My Database table looks like this (rough outline):
+--------+-----------+-------------+---------+------------+------------+
| log_id | host_name | status | host_id | profile_id | event_date |
+--------+-----------+-------------+---------+------------+------------+
| 1 | site1 | Online | 2 | 1 | <*date*> |
+--------+-----------+-------------+---------+------------+------------+
| 2 | site1 | Online | 2 | 1 | <*date*> |
+--------+-----------+-------------+---------+------------+------------+
| 3 | site1 | Offline | 2 | 1 | <*date*> |
+--------+-----------+-------------+---------+------------+------------+
| 4 | site2 | Online | 4 | 1 | <*date*> |
+--------+-----------+-------------+---------+------------+------------+
| 5 | site2 | Maintenance | 4 | 1 | <*date*> |
+--------+-----------+-------------+---------+------------+------------+
Here are my codes:
VIEW:
<?php foreach($result as $row): ?>
['<?php echo $row->host_name;?>',<?php echo $this->help_model->filter_online($id,$row->host_id, 'Online');?>,
<?php echo $this->help_model->filter_online($id,$row->host_id, 'Offline');?>,
<?php echo $this->help_model->filter_online($id,$row->host_id,'Maintenance');?>],
<?php endforeach; ?>
CONTROLLER:
public function userreports()
{
$data['id']=$this->session->userdata('profile_id');
$this->session->set_userdata('from_date', '2015-01-01');
$from_date = $this->session->userdata('from_date');
$date = date('Y-m-d',now());
$this->session->set_userdata('to_date', $date);
$to_date = $this->session->userdata('to_date');
$data['result'] = $this->help_model->all_logs($this->session->userdata('profile_id'));
$this->load->view('squidtopus1-host-reports', $data);
}
MODEL:
function all_logs($id)
{
$id = $this->session->userdata('profile_id');
$this->db->select("*");
$this->db->from('server_log');
$this->db->where('profile_id',$id);
$query = $this->db->get()->result();
return $query;
}
function filter_online($data, $host_id, $status)
{
$from_date = $this->session->userdata('from_date');
$to_date = $this->session->userdata('to_date');
$id = $this->session->userdata('profile_id');
$this->db->select()->from('server_log');
$this->db->where('profile_id',$id);
$this->db->where('status',$status);
$this->db->where('host_id',$host_id);
$this->db->where('event_date >=',$from_date);
$this->db->where('event_date <=',$to_date);
$data = $this->db->get()->result();
$stat_count = 0;
foreach ($data as $row) {
$stat_count++;
}
return $stat_count;
}
The information that needs to displayed is shown properly, but the problem is that it repeatedly shows it for each row in the database that matches 'profile_id = $id'(in this case, profile_id=1).
Ideally it should show:
['site1', 2,1,0], ['site2', 1,0,1]
But instead it shows:
['site1', 2,1,0],['site1', 2,1,0],['site1', 2,1,0],['site2', 1,0,1],['site2', 1,0,1]
I can't determine where I've gone wrong... So any insight into solving this issue is greatly appreciated. Thanks ahead!
function all_logs($id)
{
$id = $this->session->userdata('profile_id');
$this->db->select("DISTINCT(host_id), host_name");
$this->db->from('server_log');
$this->db->where('profile_id',$id);
$query = $this->db->get()->result();
return $query;
}
try to change your function like above
Is there any MySQL function that will optimize this code? A child ID getting all parent ID
function get_parents() {
$ids = array();
while($id) :
$query = "SELECT placement_id FROM referrals WHERE user_id = $id";
$query = $this->db->query($query);
$result = $query->row();
if(!isset($result->placement_id)) :
break;
elseif(isset($result->placement_id) && $result->placement_id == 2) :
break;
endif;
$id = $result->placement_id;
array_push($ids, $id);
if($result) :
continue;
endif;
break;
endwhile;
return $ids;
}
The code above will return all parent ID of given user_id, this will stop if nothing is found. I found this code too slow and heavy load.
My Table
relations table
| id | user_id | placement_id |
| 1 | 2 | NULL |
| 2 | 3 | 2 |
| 3 | 4 | 2 |
| 4 | 5 | 3 |
| 5 | 6 | 4 |
| 6 | 7 | 3 |
| 7 | 8 | 3 |
| 8 | 9 | 3 |
| 9 | 10 | 6 |
| 10 | 11 | 5 |
| 11 | 12 | 6 |
| 12 | 13 | 4 |
| 13 | 14 | 3 |
| 14 | 15 | 9 |
| 15 | 16 | 10 |
user_id is the child and parent is placement_id
You can rewrite you code as:
function get_parents() {
$ids = array();
while($id){
$query = "SELECT placement_id FROM referrals WHERE user_id = $id";
$query = $this->db->query($query);
$result = $query->row();
if(isset($result->placement_id) && $result->placement_id !== 2)
{
$id = $result->placement_id;
array_push($ids, $id);
}
}
return $ids;
}
It excludes some additional function calls such continue,break etc. Also, Make sure you have INT as type of user_id with indexing on this column.
I would personally do something like this:
<?php
define('MAX_NEST_DEPTH', 15);
function get_parent($child_id) {
$child_id = (int) $child_id;
$parents = array();
$counter = 0;
do {
$sql = "SELECT placement_id
FROM referrals
WHERE user_id = {$child_id}";
$query = $this->db->query($query);
$result = $query->row();
$child_id = (int) $result->placement_id;
$parent[] = $child_id;
$counter++;
}
while ($child_id != 0 || $counter == MAX_NEST_DEPTH);
return $parents;
}
You wont get around the query in a loop here, mysql does not support n-level-nested SELECT, otherwise we could just do it in one go.