Codeigniter query within foreach loop - php

I am trying to write PHP MVC for area wise message blocking. Like user check's the area checkbox from where they want's to get messages while uncheck the area checkbox from where they dont want to get message. Details of this checkbox option of a user is store in "geo" table with user_id and area code like in_p1,in_p2,... upto in_p17. e.g. in_p1 field in db should be 1 for a user if he want's messages from that particular area otherwise in_p1 should 0 to avoid messages from that area , same logic for area in_p2 tp in_p17.
In another table 'individu' table "in_pays" is area id from 1 to 17.My current MVC code working fine on local host but on live site as db has has more 5 millions of user for each area it's not working.
so can you guy's help me out to avoid the query within foreach loop so that I can avoid the running of query millions of time? MY MVC code is as
My Controller is
$geo_arr=$this->settingmodel->get_geotable();
//echo '<br><pre>'; print_r($geo_arr); echo '</pre>';
foreach($geo_arr as $geo)
{
for($count=1;$count<18;$count++)
{
$in_p='in_p'.$count; //in_p1,in_p2..in_p17 is column name in `geo` table
if($geo->$in_p==1) // e.g. if in_p1=1 then messages from area code 1 is allowed
{
$this->settingmodel->unblock_messages($in_pays=$count);
}
else //e.g. if in_p1!=1 then messages from area code 1 is not allowed
{
$this->settingmodel->block_message($in_pays=$count);
}
}
}
My Model
function unblock_messages($in_pays)
{
$login_user=$this->session->userdata('in_pseudo');
$this->db->select('in_pseudo');
$this->db->from('individu');
$this->db->where('in_pays',$in_pays);
$query=$this->db->get();
$result=$query->result();
foreach($result as $res)
{
$me_from=$res->in_pseudo;
$arr=array('ME_VALID'=>'NULL');
$this->db->where('ME_FROM',$me_from);
$this->db->where('ME_TO',$login_user);
$this->db->update('message',$arr);
}
}
function block_message($in_pays)
{
$login_user=$this->session->userdata('in_pseudo');
$this->db->select('in_pseudo');
$this->db->from('individu');
$this->db->where('in_pays',$in_pays);
$query=$this->db->get();
$result=$query->result();
foreach($result as $res)
{
$me_from=$res->in_pseudo;
$arr=array('ME_VALID'=>'X');
$this->db->where('ME_FROM',$me_from);
$this->db->where('ME_TO',$login_user);
$this->db->update('message',$arr);
}
}
function get_geotable()
{
$in_num=$this->session->userdata('in_num');
$this->db->select('in_p1,in_p2,in_p3,in_p4,in_p5,in_p6,in_p7,in_p8,in_p9,in_p10,in_p11,in_p12,in_p13,in_p14,in_p15,in_p16,in_p17');
$this->db->from('geo');
$this->db->where('in_num',$in_num);
$query=$this->db->get();
$result=$query->result();
return $result;
}

Related

How to check if only specific table column affected in Codeigniter?

Currently, I have controller & model for form edit. If user submit different value, this will modify the value in database and if there is an affected rows, will set flash message as "success" and if same data is submitted by user without modify the value,then will set flash message as "nochange".
if($this->db->affected_rows() > 0 ) {
$this->session->set_flashdata('success','Database is updated');
redirect('registrar');
} else {
$this->session->set_flashdata('nochange','There is no changes in database');
redirect('registrar');
}
In Codeigniter, how can I check if only specific columns are affected?
For example, if my table in database have 12 columns, if user only change the value let say in column 10, then set flash message as "nochange".
If user changes values in other columns except column 10, set flash message as "success"
There is no in-built functionality in CodeIgniter or php to do this.
You would have to essentially get the entire entry before updating it. And then column by column compare the submitted value with the current value of the entry as per your required logic.
Example pseudo-code:
$q = $this->db->get_where('table', array('id' => $id))->row();
$change = false;
if ($this->input->post('col1') !== $q->col1) {
$change = true;
}
...
if ($this->input->post('col10') == $q->col10) {
$change = false;
}
$this->db->update('table', $data);

Yii2 Kartik dependent dropdown - header already sent exception

In Yii2 I have integrated Kartik Depdrop widget.
When I am using the Indian state and city in the table, it is working fine.
but once I update the same table with US state and city,
the dependent field is not filled up and in firebug response is shown correctly but along with error - headers already sent exception like:
An Error occurred while handling another error:
yii\web\HeadersAlreadySentException: Headers already sent in
/var/www/clients/client2/web206/web/controllers/UserController.php on
line 159. in
/var/www/clients/client2/web206/web/vendor/yiisoft/yii2/web/Response.php:366
The relevant code is like this:
public function actionSubcat() {
$out = [];
if (isset($_POST['depdrop_parents'])) {
$parents = $_POST['depdrop_parents'];
if ($parents != null) {
$cat_id = $parents[0];
$out = UserProfile::GetCity($cat_id);
// the getSubCatList function will query the database based on the
// cat_id and return an array like below:
// [
// ['id'=>'<sub-cat-id-1>', 'name'=>'<sub-cat-name1>'],
// ['id'=>'<sub-cat_id_2>', 'name'=>'<sub-cat-name2>']
// ]
echo Json::encode(['output'=>$out,'selected'=>'']); // this is line 159
return;
}
}
echo Json::encode(['output'=>'','selected'=>'']);
}
So I am not able to make, what is causing the issue and how I can fix it.
only difference to me it looks like is the number of database entries are more compared to Indian state and city.
echo Json::encode(['output'=>$out,'selected'=>'']); // this is line 159
return;
ALTER FOR
return Json::encode(['output'=>$out,'selected'=>'']);

Ajax request takes too long to complete when working with large database

I am working on a website written in Yii framework (version 1.1.14) that allows uploading and displaying news. The admin of the site can select three news to promote to homepage and specify the order in which they are displayed. I am using Mysql database. The news table has two fields: isChecked (0 or 1) and homepagePos (integer) in addition to the other fields. The isChecked field determines whether the news is selected for displaying in homepage and the homepagePos field determines the order in which the news are displayed. I have used jquery's sortable plugin to sort the news. When the user selects which news to display and clicks save button, the news ids are sent to php via ajax.
The javascript portion to send the values to news controller is as follows:
$(document).on('click', '#saveToHomepage', function()
{
var url = ajaxRequestSendUrl; //ajaxRequestSendUrl contains url to news controller's promote to homepage method.
$.ajax({
method: "GET",
url: url,
data: {
contentIds: contentIds, //contentIds contains an array of news Ids in certain order
},
success: function() {
// Show success message
},
error: function() {
alert('Some error occured. Please reload the page and try again.');
}
});
});
Here's the promote to homepage method in news controller:
public function actionHomepage()
{
$allNews = News::model()->findAll();
$value = $_GET['contentIds'];
foreach ($allNews as $news) {
if($news->id == $value[0] ||$news->id == $value[1] ||$news->id == $value[2])
{
$news->isChecked = 1;
$news->homepagePos = array_search($news->id, $value); //Assign index of the array as the position
$news->save();
}
else
{
$news->isChecked = 0;
$news->homepagePos = -1;
$news->save();
}
}
}
My problem is that the news table I have has over 2k data. So the ajax call takes really long time (over a minute) to complete. Is there any way I can optimize the code or is there other way I can approach this to reduce the time taken to complete this operation?
Thanks in advance
Three queries: One first to set the whole table to not checked status, and the rest to set the checked status only in the row each selected id
public function actionHomepage()
{
$values = $_GET['contentIds'];
$sql = "UPDATE news SET idChecked=0,homepagePos = -1";
Yii::app()->db
->createCommand($sql)
->execute();
for($ii = 0; $ii < 3; $ii++) {
$sql = "UPDATE news SET idChecked = 1,homepagePos = ':homepagePos' WHERE id=:id";
Yii::app()->db
->createCommand($sql)
->bindValues(array(':homepagePos' => array_search($ii, $values), ':id' => $values[$ii]))
->execute();
}
}
i am not sure, but why don't you get the filtered records from the database itself by sending the id's of selected news. I don't know your backend language. Seems, you are getting all the records and applying filtering. which consumes time. Instead get the filtered news from the database.
Hope this helps!
Its taking a long time because you're fetching all the records and then updating those three id. You could try this:
$criteria = new CDbCriteria;
$criteria->addInCondition( "id" , $value ) ; // $value = array ( 1, 2, 3 );
News::model()->updateAll(array('isChecked'=>'1','homepagePos'=>'val2'), $criteria);
You could do an update before hand to reset all the homepagePos and then update only the ids you need.

How to select from mysql array text and compare

I am collecting user selected "text" as array in mysql using PDO connection from php form there are let suppose 3 check boxes with names
1- Apple
2- Banana
3- Cherry
In DB stored values are as per shown
apple,banana,cherry
What i want : I want to display "Apple" users in certain "/offer.php" page
while i am using SELECT query and it's not working i am using pure php mvc framwork.
In Controller i done this
public function offer(){
$this->view->title = User Selection;
$this->view->offerUser = $this->model->offerUser();
$this->view->render('dashboard/offer');
}
In Model I done this
public function offerUser()
{
return $this->db->select('SELECT * FROM users WHERE selection = apple ORDER BY points DESC ');
}
In View i done this
<?php
foreach($this->offerUser as $key => $value) {?>
<tbody>
<tr>
<td></td>
<td><strong><?php echo $value['selection']?></strong></td>
</tr>
The issue is i am not able to select "Text" from stored array with model and even not able to display selection in "View" user end page.
This code format was working fine with single numeric digit selection or compare but failed with text array.
Please help me out with this i really appreciate this i am new with text array fetching.
Hope someone answer my question soon....
Regards,
james
query is not working : use single quotation around apple
public function offerUser()
{
return $this->db->select("SELECT * FROM users WHERE selection = 'apple' ORDER BY points DESC ");
}

How to display custom error messages instead of the default ones?

I'm creating a recommendation controller using PHP Yii framework, using a heuristic concept. My recommendation will only work if the user or other user with the same course have made a booking. But right now if my bookings is equal to null it is showing an error message like below:
Error 500 Invalid argument supplied for foreach()
Therefore I have made a condition where I created my own message:
We are sorry currently there are no recommendation of books at this moment
and it is working. Unfortunately, it also shows together with the error message. I just want to show only my own message. Below is my code:
//recommendation - use heuristic concept, more accurate result as more people same course recommendation
public function actionRecommendation() {
$user = User::model()->findByPk(Yii::app()->user->id);
//get course mates
$courseMates = User::model()->findAllByAttributes(array('course_id' => $user->course_id));
$popularity = array();
if($bookings==null){Yii::app()->user->setFlash('success', 'We are sorry currently there are no recommendation of books at this moment'); }
foreach ($courseMates as $courseMate) {
//identify all bookings made by user
$bookings = Booking::model()->findAllByAttributes(array('user_id' => $courseMate->id));
foreach ($bookings as $booking) {
//add hit into array as per book
$popularity[$booking->book_id] = (isset($popularity[$booking->book_id])) ? $popularity[$booking->book_id] + 1 : 1;
}
}
//sort according to popular count
arsort($popularity, SORT_NUMERIC);
$display = 10;
foreach ($popularity as $bookId => $popular) {
//if display is 0, break the foreach, only display up 10
if ($display == 0) {
break;
}
//create book object array
$books[] = Book::model()->findByPk($bookId);
//reduce book count
$display--;
}
$this->render('recommendation',array(
'books'=>$books,
));
}()
How can I modify it so it displays just the custom error message?
For Input Fields
*In your Model*
array('gender','required','message'=>'Please select gender.'),
Or can call Function too.
array('gender', 'ownFunction'),
public function ownFunction() {
{
if (empty($this->gender))
$this->addError("gender", 'Please select gender.');
}
}
Using this you can display custom error message on input fields
For Error Page
for Custom message in Error Page .
In your Controller
if(Your Condition)
{
//Show Error form.
throw new CHttpException(500,'We are sorry currently there are no recommendation of books at this moment. ');
}
else
{
/* rest of code goes Here */
}
Hope this Helps You

Categories