Magento - Blank white screen search results. Many things broken - php

Whenever a user searches, I get this error:
2012-06-26 11:05:21.671 [NOTICE] [208.69.120.120:48175-0#hostname] [STDERR] PHP Fatal error: Call to undefined method Mage_Catalog_Model_Resource_Product_Flat::getEntityTablePrefix() in /chroot/home/SITENAME/DOMAIN.COM/html/app/code/core/Mage/Eav/Model/Entity/Attribute/Abstract.php on line 505
And instead of the user's results appearing, they get a blank white page- no error on their end, no UI, just white. This was the first issue I noticed, but on the same day the following issues started coming up:
White Search Results
Sub-category product count for all sub-categories in layered nav is showing 0.
Some customers can not view orders from their front-end UI when logged in.
Our order export script is returning blank fields (1.7mb instead of 4.3).
Our "Made-in-the-usa" and "best sellers" pages are returning more products than they should.
Now, I know these are all incorrect because if I reindex the entire site, for some period while it is processing the index, all of the above works. However, when the index is complete, it all breaks again. The same day this happened we had an error page appear that stated one of the tables had broken and should be repaired. We ran PHPMyAdmin's repair and optimize functions on all tables and it fixed that error- but all of these are still broken.
Any ideas at all? Any ideas of what could be tried to fix this? I cant find this error anywhere- and the guys over at Nexcess haven't been able to find anything for this, either.
Thank you for your time.

As per the comments above, Magento's telling you that it's trying to call the method getEntityTablePrefix on an object whose classes don't have that method defined. Specifically in this method
#File: app/code/core/Mage/Eav/Model/Entity/Attribute/Abstract.php
public function getBackendTable()
{
if ($this->_dataTable === null) {
if ($this->isStatic()) {
$this->_dataTable = $this->getEntityType()->getValueTablePrefix();
} else {
$backendTable = trim($this->_getData('backend_table'));
if (empty($backendTable)) {
$entityTable = array($this->getEntity()->getEntityTablePrefix(), $this->getBackendType());
$backendTable = $this->getResource()->getTable($entityTable);
}
$this->_dataTable = $backendTable;
}
}
return $this->_dataTable;
}
Given this happens from the following class
Mage_Catalog_Model_Resource_Product_Flat
It says to me that you have an extension and/or customization done that assumes you're not using the flat catalog data tables and wasn't coded to work with the flat table.
Dropping in a debugging call like this
if(!is_callable(array($this->getEntity()),'getEntityTablePrefix'))
{
mageDebugBacktrace();
//debug_print_backtrace();
exit;
}
right before the offending call (in a local code pool override, of course), will print out a call-stack that should point the offending code.

The seems that problem is in Mage_CatalogSearch_Model_Resource_Search_Collection::_getSearchEntityIdsSql that is not compatible with using the product flat index.
You can rewrite class Mage_CatalogSearch_Model_Resource_Search_Collection and do two little modifications.
1) Add new function _getSearchEntityIdsSqlUsingFlatIndex to rewrited class. This new function (I hope) does exactly the same thing as original _getSearchEntityIdsSql, but with using the product flat index.
2) Modify function _getSearchEntityIdsSql so that it calls new _getSearchEntityIdsSqlUsingFlatIndex if the catalog product flat index is enabled and built.
See source code:
class VENDOR_MODULE_Model_PATHTOREWRITECLASS extends Mage_CatalogSearch_Model_Resource_Search_Collection {
/**
* Retrieve SQL for search entities using product flat index.
*
* #param $query
* #return Varien_Db_Select
*/
protected function _getSearchEntityIdsSqlUsingFlatIndex($query)
{
/* #var $coreHelper Mage_Core_Model_Resource_Helper_Abstract */
$coreHelper = Mage::getResourceHelper('core');
$likeOptions = array('position' => 'any');
$flatTableName = $this->getTable('catalog/product_flat').'_'.$this->getStoreId();
/** #var Varien_Db_Select $select */
$select = $this->getConnection()
->select()
->from($flatTableName, array('entity_id'));
foreach ($this->_getAttributesCollection() as $attribute) {
/** #var Mage_Catalog_Model_Entity_Attribute $attribute */
if ($this->_isAttributeTextAndSearchable($attribute)) {
$attributeCode = $attribute->getAttributeCode();
$dbFieldName = in_array($attribute->getFrontendInput(), array('select', 'multiselect'))
? $attributeCode.'_value'
: $attributeCode;
if ($this->getConnection()->tableColumnExists($flatTableName, $dbFieldName)) {
$select->where($coreHelper->getCILike($dbFieldName, $this->_searchQuery, $likeOptions));
} else {
Mage::log(__METHOD__.": Attribute '$attributeCode' is missing in flat index.", Zend_Log::NOTICE);
}
}
}
return $select;
}
/**
* Retrieve SQL for search entities
*
* #param unknown_type $query
* #return string
*/
protected function _getSearchEntityIdsSql($query)
{
// HACK - make compatibility with flat index
/** #var Mage_Catalog_Helper_Product_Flat $flatHelper */
$flatHelper = Mage::helper('catalog/product_flat');
if ($this->getStoreId() > 0
&& $flatHelper->isEnabled($this->getStoreId())
&& $flatHelper->isBuilt($this->getStoreId())
) {
return $this->_getSearchEntityIdsSqlUsingFlatIndex($query);
}
// END HACK
return parent::_getSearchEntityIdsSql($query);
}
}

Related

symfony/doctrine: cannot use object without refreshing

It's the first time I run into this problem. I want to create a doctrine object and pass it along without having to flush it.
Right after it's creation, I can display some value in the object, but I can't access nested object:
$em->persist($filter);
print_r($filter->getDescription() . "\n");
print_r(count($filter->getAssetClasses()));
die;
I get:
filter description -- 0
(I should have 19 assetClass)
If I flush $filter, i still have the same issue (why oh why !)
The solution is to refresh it:
$em->persist($filter);
$em->flush();
$em->refresh($filter);
print_r($filter->getDescription() . " -- ");
print_r(count($filter->getAssetClasses()));
die;
I get:
filter description -- 19
unfortunately, you can't refresh without flushing.
On my entities, I've got the following:
in class Filter:
public function __construct()
{
$this->filterAssetClasses = new ArrayCollection();
$this->assetClasses = new ArrayCollection();
}
/**
* #var Collection
*
* #ORM\OneToMany(targetEntity="FilterAssetClass", mappedBy="filterAssetClasses", cascade={"persist"})
*/
private $filterAssetClasses;
public function addFilterAssetClass(\App\CoreBundle\Entity\FilterAssetClass $filterAssetClass)
{
$this->filterAssetClasses[] = $filterAssetClass;
$filterAssetClass->setFilter($this);
return $this;
}
in class FilterAssetClass:
/**
* #var Filter
*
* #ORM\ManyToOne(targetEntity="App\CoreBundle\Entity\Filter", inversedBy="filterAssetClasses")
*/
private $filter;
/**
* #var Filter
*
* #ORM\ManyToOne(targetEntity="AssetClass")
*/
private $assetClass;
public function setFilter(\App\CoreBundle\Entity\Filter $filter)
{
$this->filter = $filter;
return $this;
}
Someone else did write the code for the entities, and i'm a bit lost. I'm not a Doctrine expert, so if someone could point me in the good direction, that would be awesome.
Julien
but I can't access nested object
Did you set those assetClasses in the first place?
When you work with objects in memory (before persist), you can add and set all nested objects, and use those while still in memory.
My guess is that you believe that you need to store objects to database in order for them to get their IDs assigned.
IMHO, that is a bad practice and often causes problems. You can use ramsey/uuid library instead, and set IDs in Entity constructor:
public function __construct() {
$this->id = Uuid::uuid4();
}
A database should be used only as a means for storing data. No business logic should be there.
I would recommend this video on Doctrine good practices, and about the above mentioned stuff.
Your problem is not related to doctrine nor the persist/flush/refresh sequence; the problem you describe is only a symptom of bad code. As others have suggested, you should not be relying on the database to get at your data model. You should be able to get what you are after entirely without using the database; the database only stores the data when you are done with it.
Your Filter class should include some code that manages this:
// Filter
public function __contsruct()
{
$this->filterAssetClasses = new ArrayCollection();
}
/**
* #ORM\OneToMany(targetEntity="FilterAssetClass", mappedBy="filterAssetClasses", cascade={"persist"})
*/
private $filterAssetClasses;
public function addFilterAssetClass(FilterAssetClass $class)
{
// assuming you don't want duplicates...
if ($this->filterAssetClasses->contains($class) {
return;
}
$this->filterAssetClasses[] = $class;
// you also need to set the owning side of this relationship
// for later persistence in the db
// Of course you'll need to create the referenced function in your
// FilterAssetClass entity
$class->addFilter($this);
}
You may have all of this already, but you didn't show enough of your code to know. Note that you should probably not have a function setFilterAssetClass() in your Filter entity.

Yii2 multiple orFilterWhere

I am working on a dynamic search module in yii2 and todays task is to create the filter for lists. For example Dropdown lists where you can select multiple conditions. In our case it is a state of a car. So you can select if a car is Active or Inactive or Sold. But there is a scenario where the user wants to search both.
The filter works well if you search only the state of the car, it generates the following SQL:
SELECT * FROM `gepkocsi` WHERE (((`allapot`='A')) OR ((`allapot`='F'))) AND (`torolt` IS NULL) LIMIT 20
It works because there aren't any further condition like licence plate. Now lets se what happens if we add that condition into our search.
So at this time we search for cars where the licence plat contain the i letter and the status is Active or Saled. The following SQL is generated:
SELECT * FROM `gepkocsi` WHERE (((`rendszam` LIKE '%i%') OR ((`allapot`='A'))) OR ((`allapot`='E'))) AND (`torolt` IS NULL) LIMIT 20
The problem is that after the licence plate (rendszam) shuold be a AND insted of OR. This is generated by the following method. And this leads us to the main source of the problem.
/**
* #param $fieldName
*/
public function filterList($fieldName) {
if (isset($fieldName) && !empty($this->$fieldName)) {
foreach ($this->$fieldName as $singleFieldName) {
$this->query->orFilterWhere(['or',
[$fieldName => $singleFieldName]]);
}
}
}
I think if I add separatly all the fieldnames as a parameter of orFilterWhere it should work. What do you think what is the best practice to do it? Or Yii2 has someting magical to do that?
Thank you for your answers!
I found the solution how to append all the OR conditions. Simply the Yii2 generates an IN caluse.
/**
* #param $fieldName
*/
public function filterList($fieldName) {
if (isset($fieldName) && !empty($this->$fieldName)) {
//$this->debug($this->$fieldName);
$tomb = [];
foreach ($this->$fieldName as $singleFieldName) {
$tomb[$fieldName][] = $singleFieldName;
}
$this->query->andFilterWhere($tomb);
}
}

wordpress plugin WPdeposit, how to use the functions

I have installed the plugin WPdeposit on my wordpress site, it allows users to deposit into their account balance. I am trying to manipulate users balances when they press an anchor tag on the page.
In the directory plugins/models/user.php there are many functions, I think im interested in this one:
/**
* Update Regular balance to given amount (Will overwrite whatever value is in the db!)
*
* #param int $amount
* #return boolean
*/
public function updateRegularBalance($amount) {
if (floatval($amount)) {
return (bool) update_user_meta($this->_id, WPDEPOSIT_NAME.self::USER_AMOUNT, $amount);
} else {
throw new \Exception(__('Amount is not a number', WPDEPOSIT_NAME));
}
}
when I try to call this function to the page on the theme's index.php like so:
updateRegularBalance(5);
but I receive this error.
Fatal error: Call to undefined function updateRegularBalance()
is there a way to access the use of this function so I can pass in the value I want to update the balance to?
$class = new UserModel();
$class->updateRegularBalance(9999);
it was never a function I was trying to use, it was a method.

How to Delete/Remove Graphs(charts), Pictures(Images) from excel file loaded into PHPExcel?

I am using PHPExcel class and i am loading template speadsheets and then modifying data and so forth.
Depending on what i pass my script dynamically, certain images in the template should be remove and certain graphs(charts) should be removed.
I have used the getChartCollection() and the getDrawingCollection() to get everything but i havent figured out a way to modify the collections so that i can remove charts, and/or images from a
loaded template.
Thanks for any help.
Jason K.
UPDATE - Thanks to info from Mark Baker below.
I wrote the following code that needs to be added to worksheet class until 1.7.9 is released.
My code is below.
/**
* Remove drawing from collection
*
* #return PHPExcel_Worksheet_BaseDrawing[]
*/
public function removeImageByIDs($IDs)
{
if(!is_array($IDs)) $IDs = array($IDs);
$drawing_collection = $this->_drawingCollection;
$drawing_collection_copy = $drawing_collection->getArrayCopy();
foreach($IDs as $ID){
unset($drawing_collection_copy[$ID]);
}
$drawing_collection_copy = array_values($drawing_collection_copy);
$drawing_collection->exchangeArray($drawing_collection_copy);
$this->_drawingCollection = $drawing_collection;
unset($drawing_collection_copy);
unset($drawing_collection);
return $this->_drawingCollection;
}
/**
* Remove chart from collection
*
* #return PHPExcel_Worksheet_BaseDrawing[]
*/
public function removeChartByIDs($IDs)
{
if(!is_array($IDs)) $IDs = array($IDs);
$chart_collection = $this->_chartCollection;
$chart_collection_copy = $chart_collection->getArrayCopy();
foreach($IDs as $ID){
unset($chart_collection_copy[$ID]);
}
$chart_collection_copy = array_values($chart_collection_copy);
$chart_collection->exchangeArray($chart_collection_copy);
$this->_chartCollection = $chart_collection;
unset($chart_collection_copy);
unset($chart_collection);
return $this->_chartCollection;
}
Enjoy. Jason K.
Believe it or not, this is the first time that anybody has ever asked about removing charts or images from a spreadsheet. PHPExcel doesn't actually have any methods for this, but they'd be easy enough for you to add yourself. The methods to add entries in these collections are in the PHPExcel_Worksheet class; and as the collection is simply an array, then it's simply a case of using unset(), array_splice() or similar to remove the entries you don't want.

Magento Community 1.7.0.2 - Export Products CSV

Quite a new install of Magento, Products are setup etc and was just about to export a product CSV and once I submitted the normal form, The error "No valid data sent" I started doing some debug to see what was going off. First stop was the exception.log
Notice: Undefined index: in /app/code/core/Mage/ImportExport/Model/Export/Entity/Product.php on line 539' in /app/code/core/Mage/Core/functions.php:245
The function thats causing the problem is:
/**
* Update data row with information about categories. Return true, if data row was updated
*
* #param array $dataRow
* #param array $rowCategories
* #param int $productId
* #return bool
*/
protected function _updateDataWithCategoryColumns(&$dataRow, &$rowCategories, $productId)
{
if (!isset($rowCategories[$productId])) {
return false;
}
$categoryId = array_shift($rowCategories[$productId]);
$dataRow[self::COL_ROOT_CATEGORY] = $this->_rootCategories[$categoryId];
if (isset($this->_categories[$categoryId])) {
$dataRow[self::COL_CATEGORY] = $this->_categories[$categoryId];
}
return true;
}
For somereason, $categoryId doesn't get set as $rowCategories isn't an Array.
I've re-run the index management just incase, but it seems to me like theres something wrong with the Categories or something. I know a quick fix is to check that the $categoryId is set before continuing, but I'd like to know what's causing the error in the first place.
Until a fix from magento, you can duplicate the file under
local/Mage/ImportExport/Model/Export/Entity/Product.php
and change line 534:
if (!isset($rowCategories[$productId])) {
return false;
}
to
if (!isset($rowCategories[$productId]) or empty($rowCategories[$productId])) {
return false;
}
I had the same problem. As I was only trying to export one product - the fix was easy: I just added the product to a category.
There seems to be something wrong with the filters on the export products' form. The simple fix for this, on magento 1.7.0.2:
Copy the file app/code/core/Mage/ImportExport/Model/Export.php to app/code/local/Mage/ImportExport/Model/Export.php.
Around line 145, on the export() method, comment out the if, and the else. There is never a filter on the form.
Copy the file app/code/core/Mage/ImportExport/controllers/Adminhtml/ExportController.php to app/code/local/Mage/ImportExport/controllers/Adminhtml/ExportController.
Around line 77, on the exportAction() method, comment out the if and the else. Same reason as above
That did it for me.

Categories