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

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

Related

How do I mark content entities as dirty in Drupal 7 Search API module

I am using Drupal 7 with the search api. I understand that one of the 'common pitfalls' of the search api is 'Changes in related entities don't lead to re-indexing'. I am bringing in a field called 'Collection Reference' in my search api index as 'type = content' . So when the title of a collection changes the search API doesn't realise it changes.
I have tried to sort this using the rules module as discussed - https://www.drupal.org/docs/7/modules/search-api/getting-started/common-pitfalls#indirect-changes - but I have not been able to get it working. Has anybody had any luck with this technique?
I solved the issue.
In my case I have photographs in an index and they have a gallery as an entity field and the galleries were not updating if they were modified in the photo index. So grabbed all of the photos relating to that gallery using SQL then put into a dirty ids array. So the code below:
function hook_entity_presave($entity, $type) {
if ($entity->type == 'MYCONTENTTYPE') {
if ($entity->original->title !== $entity->title) {
$dirty_ids = array();
$nid = $entity->nid;
$result = db_query('SELECT g.entity_id FROM {gallery} g WHERE c.id = :nid', array(':nid' => $nid));
foreach($result as $record) {
$dirty_ids[] = $record->entity_id;
}
if(!empty($dirty_ids)) {
search_api_track_item_change('node', $dirty_ids);
}
}
}
}

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 validate form post in the controller and also check if the product collection filter matched

I have created a simple product selector. In the phtml, I created a form that post data and these data are received by controller to be validated before registering to a registry.
I also have product collection that gets the data to be filter coming from the registry. I have several filters and if one fails, the system should display a message.
This is what I have done so far.
My Controller:
public function indexAction() {
if ($data = $this->getRequest()->getPost()) {
$data['ta'] = $this->getRequest()->getPost('torqueAction');
$data['tr'] = $this->getRequest()->getPost('torqueRequired');
$data['tm'] = $this->getRequest()->getPost('torqueMetric');
$data['tmax'] = $data['tr'] / 80 * 100;
if (validation is equal to true) {
Mage::register('t-action', $data['ta']);
Mage::register('t-req', $data['tr']);
Mage::register('t-metric', $data['tm']);
Mage::register('t-max', $data['tmax']);
$this->_redirect('productselector/index/result');
}else {
// Display message about the error
}
}
}
My Collection located in the phtml:
$collection = Mage::getModel('catalog/product')
->getCollection()
->addFieldTofilter($attr_name, array(
'eq' => Mage::getResourceModel('catalog/product')
->getAttribute($attr_name)
->getSource()
->getOptionId($attr_val)
))
->addAttributeToSelect('*')
->addFieldTofilter($metric, array('gteq' => $metric_val_min))
->addFieldTofilter($metric, array('lteq' => $metric_val_max))
->load();
if ($collection == NULL) { // not sure how to validate it if one filter fails
echo "sorry, no product available";
}else {
//Display some errors
}
QUESTIONS:
How to validate form post in the controller and checks if empty and no malicious code?
How to check product collection if one filter was not met?
How do I display these errors from controller and product collection?
Thanks
How to validate form post in the controller and checks if empty and no malicious code?
You can check an empty post like this.
if ($this->getRequest()->getPost('field_name', false)) {
//yes 'fiel_name' is not empty. do something with it.
}
This is because getPost() will accept two parameters. If the parameter-1 is not set, then it will return the default value that we specified as parameter-2. In this case, default value is false and hence condition fails if field_name is empty.
I didn't get the "malicious" part in the question. The answer for is, it depends from situation to situation.
How to check product collection if one filter was not met?
Honestly, question is not clear for me. However if the filters that you have applied using addFieldToFilter fails, then you will get an empty collection. You can check the count of a collection like this.
if ($collection->getSize() > 0) {
//do something with collection
} else {
//show some error
}
How do I display these errors from controller and product collection?
Errors, warning, success messages are setting on session variable and thus you can get the session in the redirecting page and show them in frontend.
These are the avaialble notifications in Magento.
$session = Mage::getSingleton('customer/session');
//use to show error
$session->addError('add some error message');
//use to show warning
$session->addWarning('add some warning message');
//use to show notice
$session->addNotice('add some notice message');
//use to show success message
$session->addSuccess('add some success message');
You can set them in controller. Now this is how you can grab all these items and show in frontend. Use them in the form template wisely.
$messages = Mage::getSingleton('customer/session')->getMessages();
foreach ($messages as $message) {
echo $message;
}
Hope that makes sense.

Codeigniter query within foreach loop

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;
}

Categories