Yii2 Kartik dependent dropdown - header already sent exception - php

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'=>'']);

Related

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.

magento - retrieve values from catalog/eav_attribute

Ive added a field to catalog/eav_attribute and managed to save data into it. I just cant figure out how to get the data out in the front end.
im using the event observer "catalog_product_load_after" and im trying to extract "is_featured_attribute" from the "catalog/eav_attribute" resouce, im fairly new to magento and just cant figure out how to get the data.
Any help would be greatly appreciated
Dave
It would help if you could show what your observer function looks like, but I'll hypothesize. Essentially you need to load the product from the observer to retrieve your attribute value;
public function yourClass($observer) {
// Get the observed product
$item = $observer->getProduct();
// Get value of your attribute (guessing Yes or No)
$myAttr = $item->getIsFeaturedAttribute();
if($myAttr == 'Yes') {
// Do something
$isItYes = true;
} else {
// Do something
$isItYes = false;
}
return $isItYes;
}

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

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

Why can't I see the database updates unless I refresh the page?

Hmmmmm I worked on some PHP code that pulls stock levels from my supplier and inserts the stock level into the database based on the product's SKU. I've inserted it into the class.product.php file which contains all the code used for the individual product page. The issue I'm having is that when the product page loads, it doesn't show the updated inventory levels unless you hit refresh. I've moved the code all over the place and can't get it to update the database and have the updated number loaded before the page is displayed.
Even when placed before all other code, I still have to refresh the page to see the update. I don't know what else to do about this. I feel like perhaps, I don't truly understand how PHP loads code. I've been working on this every day for weeks. I tried running it as an include file, on a separate page, at the top, in the middle, all over the place.
In the class file, it looks like I have the code before it calls the code to display the stock levels, that's why I'm so confused as to why it won't load the updates.
Any thoughts on why I'm unable to see the changes unless I refresh the page?
Thanks!
PHP loads the content when you request it ,
so opening a page gets the content ONCE,
The thing you want to do to get data updated is have AJAX calls to a php function that return data in JSON or XML format
Here you can see some examples but consider googling around for more detailed examples.
The problem was my code was not running until after the code to get and display the product data because I was using info from the product data that was only being called once. So the product data had be be called first in order for my code to run. So to fix this, I had to create a new function that would get the sku and pass it to my code before the code that called the product data to be displayed on the page. I copied the existing function to get the product data, renamed it to GetRealTimeStockLevels and added my code to the bottom of it. I put the call for the function above the call for the product data and it worked like I wanted. I'm glad I got this worked out, now I can add the same feature to the checkout page.
Below is the function call at the start of the page and then the function I created to run my update code.
public function __construct($productid=0)
{
// Get the stock level from supplier and update the database
$this->_GetRealtimeStockLevels($productid);
// Load the data for this product
$this->_SetProductData($productid);
public function _GetRealtimeStockLevels($productid=0)
{
if ($productid == 0) {
// Retrieve the query string variables. Can't use the $_GET array
// because of SEO friendly links in the URL
SetPGQVariablesManually();
if (isset($_REQUEST['product'])) {
$product = $_REQUEST['product'];
}
else if(isset($GLOBALS['PathInfo'][1])) {
$product = preg_replace('#\.html$#i', '', $GLOBALS['PathInfo'][1]);
}
else {
$product = '';
}
$product = $GLOBALS['ISC_CLASS_DB']->Quote(MakeURLNormal($product));
$productSQL = sprintf("p.prodname='%s'", $product);
}
else {
$productSQL = sprintf("p.productid='%s'", (int)$productid);
}
$query = "
SELECT p.*, FLOOR(prodratingtotal/prodnumratings) AS prodavgrating, pi.*, ".GetProdCustomerGroupPriceSQL().",
(SELECT COUNT(fieldid) FROM [|PREFIX|]product_customfields WHERE fieldprodid=p.productid) AS numcustomfields,
(SELECT COUNT(reviewid) FROM [|PREFIX|]reviews WHERE revstatus='1' AND revproductid=p.productid AND revstatus='1') AS numreviews,
(SELECT brandname FROM [|PREFIX|]brands WHERE brandid=p.prodbrandid) AS prodbrandname,
(SELECT COUNT(imageid) FROM [|PREFIX|]product_images WHERE imageprodid=p.productid) AS numimages,
(SELECT COUNT(discountid) FROM [|PREFIX|]product_discounts WHERE discountprodid=p.productid) AS numbulkdiscounts
FROM [|PREFIX|]products p
LEFT JOIN [|PREFIX|]product_images pi ON (pi.imageisthumb=1 AND p.productid=pi.imageprodid)
WHERE ".$productSQL;
if(!isset($_COOKIE['STORESUITE_CP_TOKEN'])) {
// ISC-1073: don't check visibility if we are on control panel
$query .= " AND p.prodvisible='1'";
}
$result = $GLOBALS['ISC_CLASS_DB']->Query($query);
$row = $GLOBALS['ISC_CLASS_DB']->Fetch($result);
if (!$row) {
return;
}
$this->_product = $row;
$this->_prodid = $row['productid'];
$this->_prodname = $row['prodname'];
$this->_prodsku = $row['prodcode'];
$GLOBALS['CurrentProductLink'] = ProdLink($this->_prodname);
$server_url = "http://ms.com/fgy/webservices/index.php";
$request = xmlrpc_encode_request("catalog.getStockQuantity", array($this->_prodsku));
$context = stream_context_create(array('http' => array(
'method' => "POST",
'header' => "Content-Type: text/xml",
'content' => $request
)));
$file = file_get_contents($server_url, false, $context);
$response = xmlrpc_decode($file);
$query = sprintf("UPDATE [|PREFIX|]products SET prodcurrentinv='$response' where prodcode='%s'", $GLOBALS['ISC_CLASS_DB']->Quote($this->_prodsku));
$result = $GLOBALS['ISC_CLASS_DB']->Query($query);
}

Categories