How to update multiple rows sharing same foreign key in Codeigniter - codeigniter

I have 2 tables; db_file_acess and db_file_access_details. I have a column subjects_id in db_file_access_details table. From the UI, I can select several subjects[array] with other details and insert them to db_file_acess table, and subject_ids to the db_file_access_details. Insertion is OK but when I update the two tables, I can't seem to update all the rows. This is my update query
$result = array();
foreach ($subject_id as $key => $val) {
$result[] = array(
'file_access_id' =>$q_id,
'subjects_id' => $_POST['subject_id'][$key]
);
}
$this->db->update_batch('db_file_access_details', $result, 'file_access_id');
The query runs but it updates with only one id as seen in the screenshot below:
the result() array is as shared below:
Array
(
[0] => Array
(
[file_access_id] => 45
[subjects_id] => 1
)
[1] => Array
(
[file_access_id] => 45
[subjects_id] => 3
)
[2] => Array
(
[file_access_id] => 45
[subjects_id] => 4
)
)
after update_batch query, the resultant results is as shown below
What am I doing wrong?

According to the docs update_batch('db_file_access_details', $result, 'file_access_id') produces:
UPDATE `db_file_access_details` SET `subjects_id` = CASE
WHEN `file_access_id` = 45 THEN 1
WHEN `file_access_id` = 45 THEN 3
WHEN `file_access_id` = 45 THEN 4
ELSE `subjects_id` END
WHERE `file_access_id` IN (45, 45, 45)
For all three rows, the first case matches, so all subject_ids are set to 1.
For update_batch to work correctly you need to use the id column.
Depending on what you want to achieve, you could also consider deleting all rows for the file_access_id in db_file_access_details and then inserting the $result array with insert_batch instead.

Related

Inserting multipe rows from dynamic form fields using laravel 5

How can I store multiple form array data in laravel, as I need to create a new record against each array index.
[0] => Array
(
[make] => test
[model] => XYZ
)
[1] => Array
(
[make] => s4
[model] => BB
)
[2] => Array
(
[make] => 99
[model] => AX
)
This is what I am trying to, but here loop get executed 6 times instead of three
$results = $request->all();
foreach ($results as $key => $value) {
echo $key;
// insert operation
}
I believe you should specify the control/field because the Request contains other (non-data) information. Something like:
$results = $request['array_name'];
https://laravel.com/docs/5.4/queries#inserts
Model::insert($request->all())
This will mass insert each array into your database. insert do not automatically set datetime values for created_at and updated_at, note that the array keys should match your table columns, and make sure your model has these fields as $fillables.

I've assigned Laravel Query Builder to a variable. It changes when being used

it's a WHY-question, not How-to one:)
I have assigned a Query Bulder to a variable $query:
$query = table::where(['id'=>1, 'this_version'=> 1]);
$versions['slug1'] = $query->select('tourist_id', 'tourist_version')->get()->toArray();
print_r($versions);
outputs array with 2(!) sub-arrays:
Array
(
[slug1] => Array
(
[0] => Array
(
[tourist_id] => 1
[tourist_version] => 1
)
[1] => Array
(
[tourist_id] => 2
[tourist_version] => 1
)
)
)
But if I add another line using $query between my $query declaration and it's usage in getting $version[2] array, my $version[2] output is shortened to a 1-dimensional array:
$query = previoustour2_tourist::where(['tour2_id'=>$tour->id, 'this_version'=> 1]);
// Added line:
$versions['slug0'] = $query->select('version_created')->first()->version_created;
//
$versions['slug1'] = $query->select('tourist_id', 'tourist_version')->get()->toArray();
print_r($versions);
outputs (note slug1 now has only 1 nested array):
Array
(
[slug0] => 2017-08-08 08:25:26
[slug1] => Array
(
[0] => Array
(
[tourist_id] => 1
[tourist_version] => 1
)
)
)
it seems like the like this line:
$versions['slug0'] = $query->select('version_created')->first()->version_created;
has added "first()" method to the original $query . Am I right and, if yes, why does it happen?
Well, this is because by default an object (in your case is the Query builder object) in PHP is passed by reference. You can read more about this here: PHP OOP References.
I quote from the above reference:
A PHP reference is an alias, which allows two different variables to
write to the same value.
When you pass the query builder object to the $query variable, you actually just pass the reference to this object and not the copy of it.
$query = previoustour2_tourist::where(['tour2_id'=>$tour->id, 'this_version'=> 1]);
So when you call the first() method on the second line, it actually modifies the query builder object.
$versions['slug0'] = $query->select('version_created')->first()->version_created;
Thus causing the upcoming query result to be limited to 1. In order to work around this issue, you can clone the query object like this:
$query = previoustour2_tourist::where(['tour2_id'=>$tour->id, 'this_version'=> 1]);
$versions['slug0'] = (clone $query)->select('version_created')->first()->version_created;
$versions['slug1'] = (clone $query)->select('tourist_id', 'tourist_version')->get()->toArray();
print_r($versions);
Hope this help!

How to insert the array values in database using for each loop

I have array i want insert into the values in database using codeigniter, i don't know how to insert , i trying but i am not able to get the answer
My model
print_r($subjectHandling);
Array
(
[subjectId] => Array
(
[0] => 1
[1] => 2
)
)
now i want insert the values in database in this values.
I am trying like this
foreach($subjectHandling as $key=>$value) {
$reg_dat = array(
'statffId' => '1',
'subjectId' => $value,
);
$this->db->insert("subject_handling" , $reg_dat);
}
I m getting error ** Array to string conversion** , so how do this. i want to insert two roes in databse
This should work
$subjectHandling['subjectId'] = array(1, 2);
$reg_dat = array();
foreach($subjectHandling['subjectId'] as $key => $value) {
$reg_dat[] = array('staffId'=> 1, 'subjectId' => $value);
}
$this->db->insert_batch('subject_handling', $reg_dat);
https://www.codeigniter.com/userguide3/database/query_builder.html#inserting-data

codeigniter form_validation is_unique compare data between tables

I have a from which lists several items that can be selected by check box and a dropdown permitter added. In a separate part of the form is have another check box. This is submitted as two arrays.
The arrays look like this
Array
(
[1] => Array
(
[num_copy] => 1
[dwg_rev] => B
[dwg_id] => 1
)
[2] => Array
(
[num_copy] => 1
[dwg_rev] => B
[dwg_id] => 2
)
)
Array
(
[1] => Array
(
[client_id] => 1
)
)
I need to pass these two arrays to a form_validation that can check is dwg_rev has already been added to the database for the selected client_id.
I tried to use is_unique, but it can only check in one table to see if this already exists in it.
This is what my form validation currently looks like
$rows = array();
if(!empty($_POST['result']))
{
$rows = $_POST['result'];
$temp_dwg_array = array_column($rows, 'temp_dwg_id');
foreach($temp_dwg_array as $key => $temp_dwg_id)
{
$this->form_validation->set_rules('result['.$temp_dwg_id.'][dwg_rev]', 'Revision' , 'required|callback_check_issued_rev');
}
} else $this->form_validation->set_rules('result[][temp_dwg_rev]', 'Revision' , 'required');
if(!empty($_POST['client']))
{
$temp_client_array = array_column($_POST['client'],'client_id');
foreach($temp_client_array as $key => $client_id)
{
$this->form_validation->set_rules('client['.$client_id.'][client_id]', 'Please make a selection from the distribution list' , 'required|callback_check_issued_rev');
}
}
else $this->form_validation->set_rules('client[][client_id]', 'Distribution' , 'required');
I want to create a callback function, but I can't figure out how to pass two variables to the callback function to compare to the db.

Joomla user management

I got a Joomla ticketing module, that displays at a certain part of the page, the current tickets of the current user. I want to create user groups, in which the group members can view all of the tickets belongin to that group. I thought the easiest way is to create Joomla groups, assign the users to those, and to when a user loges in, it can see all of the tickets in its group. I added my code to the start of the function, but something is wrong... For every user (currently the "Registered" ones) displays the same result, that of the last users tickets, and I don't know why: Here is the code:
function gTickets()
{
$user =& JFactory::getUser();
$user_id = (int) $user->get('id');
//get user_group_id from db based on current users id
{...}
//get all users with that user_group_id
$db1->setQuery($db1->getQuery(true)
->select('*')
->from("#__user_usergroup_map")
->where("group_id = '$groupss'")
);
$groupss1=$db1->loadRowList();
$return1=array();
// for every user_id
foreach ($groupss1 as $keya)
{
$user_id = $keya[0]; // the id of users
$where = "";
if ($this->is_staff)
$where .= " AND t.`staff_id`='".$user_id."'";
else
$where .= " AND t.`customer_id`='".$user_id."'";
$tickets = $this->_getList(
"SELECT t.id, t.subject, t.last_reply_customer, s.name AS status_name FROM
#__rsticketspro_tickets t LEFT JOIN #__rsticketspro_statuses s ON
(t.status_id=s.id) WHERE 1 $where ORDER BY `last_reply` DESC", 0,
$this->params->get('tickets_limit', 3));
print_r($tickets);
return $tickets;
}
I got some questions, that I didn't know how to seach for...
what is the letter dot fieldname in the sql query? eg:
SELECT m.ticket_id, m.message FROM #__ticket_messages m WHERE m.user_id !='".$user_id."
what does the "m" mean before the WHERE?
what does the "1" do here: WHERE 1 $where
Also, I looked in the ACL managers, but could not make it work with this code.
Edit: Thanks for the fast answers! I got 1 more, and I think it's an easy one, but I can't get it to work...
If I print the content of the $ticket array into another array, I get an array with multiple arrays. That is why my code is not working... The array i'm getting is:
Array (
[0] => stdClass Object (
[id] => 1
[subject] => use1
[last_reply_customer] => 1
[status_name] => open
)
)
Array (
[0] => stdClass Object (
[id] => 3
[subject] => use2
[last_reply_customer] => 1
[status_name] => open
)
[1] => stdClass Object (
[id] => 2
[subject] => use2
[last_reply_customer] => 1
[status_name] => open
)
)
I would like the array to look like this:
Array (
[0] => stdClass Object (
[id] => 1
[subject] => use1
[last_reply_customer] => 1
[status_name] => open
)
[1] => stdClass Object (
[id] => 3
[subject] => use2
[last_reply_customer] => 1
[status_name] => open
)
[2] => stdClass Object (
[id] => 2
[subject] => use2
[last_reply_customer] => 1
[status_name] => open
)
)
Thanks!
Edit: is all of this complicated to achieve?
Look into ACL to get that part working, but to answer the 3 questions you posted at the bottom of your question:
1) the letter.field_name in the query represents the table alias.field_name in the query. The alias (m) makes it easier so you don't have to keep typing the full table name each time.
2) The m before the WHERE is actually setting the table alias, but with lazy syntax. It should say:
SELECT m.ticket_id, m.message FROM #__ticket_messages AS m
3) The "WHERE 1" is the SQL way of saying "if (true)". Since they are immediately appending the $where clause afterwards "WHERE 1 $where", the resulting query looks like this:
WHERE 1 AND t.staff_id = '" . $user_id . "'
Did you code this originally? or is it a component that you picked up somewhere? It should be using the query builder instead of direct SQL like it currently is, to make it more portable and more clear as to what it is doing.

Resources