I have been using K2 Scroller module developed by Land of Coder. When I use this module to display same category items in the items view the module displays items in the ascending order of the date created and it is the default and only setting available in the module parameter settings in the back-end. However, I want the module to display the items in date wise descending order. So I chose to edit the default code in the helper which I suppose is used to process items based on the back-end settings. And this is the part of the code in the helper file which I think controls the order:
public function __getList( $params ){
global $mainframe;
/*some irrelevant code removed*/
$condition = $this->buildConditionQuery( $params );
$limitDescriptionBy = $params->get('limit_description_by','char');
$ordering = $params->get( 'k2_ordering', 'created_desc');
$limit = $params->get( 'limit_items', 5 );
$ordering = str_replace( '_', ' ', $ordering );
$my = &JFactory::getUser();
$aid = $my->get( 'aid', 0 );
/*some irrelevant code removed*/
$extraURL = $params->get('open_target')!='modalbox'?'':'&tmpl=component';
$excludeIds = $params->get('exclude_ids', '');
$db = &JFactory::getDBO();
$date =& JFactory::getDate();
$now = $date->toMySQL();
$dateFormat = $params->get('date_format', 'DATE_FORMAT_LC3');
$limitDescriptionBy = $params->get('limit_description_by','char');
$isAuthor= $params->get('itemAuthor',0);
require_once ( JPath::clean(JPATH_SITE.'/components/com_k2/helpers/route.php') );
$query = "SELECT a.*, cr.rating_sum/cr.rating_count as rating, c.name as categoryname,
c.id as categoryid, c.alias as categoryalias, c.params as categoryparams, cc.commentcount as commentcount".
" FROM #__k2_items as a".
" LEFT JOIN #__k2_categories c ON c.id = a.catid" .
" LEFT JOIN #__k2_rating as cr ON a.id = cr.itemid".
" LEFT JOIN (select cm.itemid as id, count(cm.id) as commentcount from #__k2_comments as cm
where cm.published=1 group by cm.itemid) as cc on a.id = cc.id";
$query .= " WHERE a.published = 1"
. " AND a.access get('featured_items_show','0') == 0 ){
$query.= " AND a.featured != 1";
} elseif( $params->get('featured_items_show','0') == 2 ) {
$query.= " AND a.featured = 1";
}
if( trim($excludeIds) ){
$query .= " AND a.id NOT IN(".$excludeIds.") ";
}
$query .= $condition . ' ORDER BY ' . $ordering;
$query .= $limit ? ' LIMIT ' . $limit : '';
$db->setQuery($query);
$data = $db->loadObjectlist();
/*some irrelevant code removed*/
return $data;
}
/**
* build condition query base parameter
*
* #param JParameter $params;
* #return string.
*/
public function buildConditionQuery( $params ){
$source = trim($params->get( 'k2_source', 'k2_category' ) );
if( $source == 'k2_category' ){
$catids = $params->get( 'k2_category','');
if( !$catids ){
return '';
}
$catids = !is_array($catids) ? $catids : '"'.implode('","',$catids).'"';
$condition = ' AND a.catid IN( '.$catids.' )';
} else {
$ids = preg_split('/,/',$params->get( 'k2_items_ids',''));
$tmp = array();
foreach( $ids as $id ){
$tmp[] = (int) trim($id);
}
$condition = " AND a.id IN('". implode( "','", $tmp ) ."')";
}
return $condition;
}
Am I editing the right part of the code or am I missing something else.
I am looking forward to your help
Thanks.
Maybe the best way would be to modify the xml file of the module.
I looked at the code of Lof K2Scroller (v 2.2 for Joomla 2.5) and the different ordering options are there.
However if you want to modify the default option, you are in the right file, just replace 'created_desc' for 'created_asc' .
Related
I'm trying to update a table containing a slug value with random slugs for each record.
$vouchers = Voucher->get(); // assume 10K for example
foreach ($vouchers as $voucher) {
$q .= "UPDATE vouchers set slug = '" . Str::random(32) . "' WHERE id = " . $voucher->id . ";";
}
DB::statement($q);
There are about 2 million records so I need to perform this as a bulk. Doing it as separate records is taking way too long. I can't seem to find a way to bulk run them, say in groups of 10K or something.
Tried a bunch of variations of ->update() and DB::statement but can't seem to get it to go.
In case someone land in this page like me, laravel allows a bulk update as:
$affectedRows = Voucher::where('id', '=', $voucher->id)->update(array('slug' => Str::random(32)));
See "Updating A Retrieved Model" under http://laravel.com/docs/4.2/eloquent#insert-update-delete
I have created My Custom function for Multiple Update like update_batch in CodeIgniter.
Just place this function in any of your model or you can create helper class and place this function in that class:
//test data
/*
$multipleData = array(
array(
'title' => 'My title' ,
'name' => 'My Name 2' ,
'date' => 'My date 2'
),
array(
'title' => 'Another title' ,
'name' => 'Another Name 2' ,
'date' => 'Another date 2'
)
)
*/
/*
* ----------------------------------
* update batch
* ----------------------------------
*
* multiple update in one query
*
* tablename( required | string )
* multipleData ( required | array of array )
*/
static function updateBatch($tableName = "", $multipleData = array()){
if( $tableName && !empty($multipleData) ) {
// column or fields to update
$updateColumn = array_keys($multipleData[0]);
$referenceColumn = $updateColumn[0]; //e.g id
unset($updateColumn[0]);
$whereIn = "";
$q = "UPDATE ".$tableName." SET ";
foreach ( $updateColumn as $uColumn ) {
$q .= $uColumn." = CASE ";
foreach( $multipleData as $data ) {
$q .= "WHEN ".$referenceColumn." = ".$data[$referenceColumn]." THEN '".$data[$uColumn]."' ";
}
$q .= "ELSE ".$uColumn." END, ";
}
foreach( $multipleData as $data ) {
$whereIn .= "'".$data[$referenceColumn]."', ";
}
$q = rtrim($q, ", ")." WHERE ".$referenceColumn." IN (". rtrim($whereIn, ', ').")";
// Update
return DB::update(DB::raw($q));
} else {
return false;
}
}
It will Produces:
UPDATE `mytable` SET `name` = CASE
WHEN `title` = 'My title' THEN 'My Name 2'
WHEN `title` = 'Another title' THEN 'Another Name 2'
ELSE `name` END,
`date` = CASE
WHEN `title` = 'My title' THEN 'My date 2'
WHEN `title` = 'Another title' THEN 'Another date 2'
ELSE `date` END
WHERE `title` IN ('My title','Another title')
Chunking results is the best way to do this kind of stuff without eating all of your RAM and Laravel support chunking results out of the box.
For example:
Voucher::chunk(2000, function($vouchers)
{
foreach ($vouchers as $voucher)
{
//
}
});
I made a bulk update function to use in my Laravel projects. It may be useful for anyone who wants to use the batch update query in Laravel. Its first parameter is the table name string, second is the key name string based on which you want to update the row or rows and most of the times it will be the 'id' and the third parameter is a data array in the following format:
array(
array(
'id' => 1,
'col_1_name' => 'col_1_val',
'col_2_name' => 'col_2_val',
//...
),
array(
'id' => 2,
'col_1_name' => 'col_1_val',
'col_2_name' => 'col_2_val',
//...
),
//...
);
The function will return the number of affected rows. Function definition:
private function custom_batch_update(string $table_name = '', string $key = '', Array $update_arr = array()) {
if(!$table_name || !$key || !$update_arr){
return false;
}
$update_keys = array_keys($update_arr[0]);
$update_keys_count = count($update_keys);
for ($i = 0; $i < $update_keys_count; $i++) {
$key_name = $update_keys[$i];
if($key === $key_name){
continue;
}
$when_{$key_name} = $key_name . ' = CASE';
}
$length = count($update_arr);
$index = 0;
$query_str = 'UPDATE ' . $table_name . ' SET ';
$when_str = '';
$where_str = ' WHERE ' . $key . ' IN(';
while ($index < $length) {
$when_str = " WHEN $key = '{$update_arr[$index][$key]}' THEN";
$where_str .= "'{$update_arr[$index][$key]}',";
for ($i = 0; $i < $update_keys_count; $i++) {
$key_name = $update_keys[$i];
if($key === $key_name){
continue;
}
$when_{$key_name} .= $when_str . " '{$update_arr[$index][$key_name]}'";
}
$index++;
}
for ($i = 0; $i < $update_keys_count; $i++) {
$key_name = $update_keys[$i];
if($key === $key_name){
continue;
}
$when_{$key_name} .= ' ELSE ' . $key_name . ' END, ';
$query_str .= $when_{$key_name};
}
$query_str = rtrim($query_str, ', ');
$where_str = rtrim($where_str, ',') . ')';
$query_str .= $where_str;
$affected = DB::update($query_str);
return $affected;
}
It will produce and execute the query string like this:
UPDATE table_name SET col_1_name = CASE
WHEN id = '1' THEN 'col_1_value'
WHEN id = '2' THEN 'col_1_value'
ELSE col_1_name END,
col_2_name = CASE
WHEN id = '1' THEN 'col_2_value'
WHEN id = '2' THEN 'col_2_value'
ELSE col_2_name END
WHERE id IN('1','2')
I'm trying to save a lot of CActiveRecord model objects in a loop.
I have something like this:
foreach ($array_of_items as $item) {
$values = array(
"title" => $item->title,
"content" => $item->content,
);
$object = new MyModel;
$object->attributes = $values;
$object->save();
}
In my case, this creates about 400 CActiveRecord objects. The saving process is really slow, because each save() queries the database.
Is there a way to save all those objects in one go?
Something like:
$objects = array();
foreach ($array_of_items as $item) {
$values = array(
"title" => $item->title,
"content" => $item->content,
);
$object = new MyModel;
$object->attributes = $values;
$objects[] = $object;
}
save_all_objects($objects);
I could not find anything on the subject. Anyone?
you can validate() your model, and if it was ok you can append it so a sql text for insert,
and after your loop, just use databases commandBuilder() and execute your prepared text
$sql = '';
if($object->validate())
{
$sql .= ',("' . $object->attr1 . '")'// append to script,(you get the idea, you need to also make a correct values)
}
...
if(!empty($sql))
{
$sql = 'INSERT INTO table (attr1) Values' . $sql;// make complete script
// execute that command
}
Since v1.1.14, the method createMultipleInsertCommand() of CDbCommandBuilder class is available.
For insert multi rows, Put this code in components folder under GeneralRepository.php file name.
<?php
class GeneralRepository
{
/**
* Creates and executes an INSERT SQL statement for several rows.
* By: Nabi K.A.Z. <www.nabi.ir>
* Version: 0.1.0
* License: BSD3
*
* Usage:
* $rows = array(
* array('id' => 1, 'name' => 'John'),
* array('id' => 2, 'name' => 'Mark')
* );
* GeneralRepository::insertSeveral(User::model()->tableName(), $rows);
*
* #param string $table the table that new rows will be inserted into.
* #param array $array_columns the array of column datas array(array(name=>value,...),...) to be inserted into the table.
* #return integer number of rows affected by the execution.
*/
public static function insertSeveral($table, $array_columns)
{
$connection = Yii::app()->db;
$sql = '';
$params = array();
$i = 0;
foreach ($array_columns as $columns) {
$names = array();
$placeholders = array();
foreach ($columns as $name => $value) {
if (!$i) {
$names[] = $connection->quoteColumnName($name);
}
if ($value instanceof CDbExpression) {
$placeholders[] = $value->expression;
foreach ($value->params as $n => $v)
$params[$n] = $v;
} else {
$placeholders[] = ':' . $name . $i;
$params[':' . $name . $i] = $value;
}
}
if (!$i) {
$sql = 'INSERT INTO ' . $connection->quoteTableName($table)
. ' (' . implode(', ', $names) . ') VALUES ('
. implode(', ', $placeholders) . ')';
} else {
$sql .= ',(' . implode(', ', $placeholders) . ')';
}
$i++;
}
$command = Yii::app()->db->createCommand($sql);
return $command->execute($params);
}
}
And usage anywhere:
$rows = array(
array('id' => 1, 'name' => 'John'),
array('id' => 2, 'name' => 'Mark')
);
GeneralRepository::insertSeveral(User::model()->tableName(), $rows);
https://www.yiiframework.com/extension/yii-insert-multi-rows
How i can get some parameters from a disabled/not yet actived plugin in joomla 1.6/2.5?
$module = JPluginHelper::getPlugin('system','myplugin');
$moduleParams = new JParameter($module->params);
$val = $moduleParams->get("key");
This method didn't work becouse i need to use within an element JFormField generator.
Thanks for help!
With JPluginHelper::getPlugin it's possible to access only enabled plugins, so here's the code for direct access to database.
// Build query
$db = JFactory::getDbo();
$query = $db->getQuery(true);
$query
->select( 'params' )
->from( '#__extensions' )
->where( 'type = ' . $db->q('plugin') )
->where( 'folder = ' . $db->q('authentication') ) // Plugin type
->where( 'element = ' . $db->q('gmail') ) // Plugin element
;
// Execute query
$db->setQuery($query);
try
{
$result = $db->loadResult();
}
catch (RuntimeException $e)
{
return false;
}
// Parse parameters
if (!empty($result))
{
$params = new JRegistry($result);
$val = $params->get('key', 'defaultValue');
}
You may store query results in in the JFormField Object so save database queries in case field is availabile multiple times.
protected $results = null;
Perhaps you may want to try this:
// Get plugin parameters
$db = JFactory::getDBO();
$query = $db->getQuery(true);
$query->select('`params`')
->from ('`#__extensions`')
->where ("`type` = 'plugin'")
->where ("`folder` = 'system'")
->where ("`element` = 'myplugin'");
$db->setQuery($query);
$res = json_decode($db->loadResult(), true);
$val = $res['key'];
Just find the answer by myself.
$data = null;
foreach ((array) $this->form as $k => $v) {
if($val instanceof JRegistry){
$data = &$v;
break;
}
}
$data = $data->toArray();
$val = $data['params']['key'];
Thanks! Bye!
So, I changed the default Magento search engine slightly, and it works close to how I want it. (i.e. OR term search to AND). However, there is one more thing that I'd like to implement. When a person searches for a series of terms, like Green Apple A, I'd like the product Green Apple A to show up first. Right now, with the AND operator, the results are in the order they were pulled from the DB. So, the Green Apple A might show up in anywhere.
Here is the function that prepares the results.. It is a bit complicated for me, and I'm wondering if there's an easy way to "append" a search result that looks for the specific sequence of the inputted terms and concatenates the results, giving this priority, so it shows up first.
(Sorry for the long code. I typically don't like posting large amount of code)
From Fulltext.php in /stores/my_website/app/code/local/Mage/CatalogSearch/Model/Resource
public function prepareResult($object, $queryText, $query)
{
$adapter = $this->_getWriteAdapter();
if (!$query->getIsProcessed()) {
$searchType = $object->getSearchType($query->getStoreId());
$preparedTerms = Mage::getResourceHelper('catalogsearch')
->prepareTerms($queryText, $query->getMaxQueryWords());
$bind = array();
$like = array();
$likeCond = '';
if ($searchType == Mage_CatalogSearch_Model_Fulltext::SEARCH_TYPE_LIKE
|| $searchType == Mage_CatalogSearch_Model_Fulltext::SEARCH_TYPE_COMBINE
) {
$helper = Mage::getResourceHelper('core');
$words = Mage::helper('core/string')->splitWords($queryText, true, $query->getMaxQueryWords());
foreach ($words as $word) {
$like[] = $helper->getCILike('s.data_index', $word, array('position' => 'any'));
}
if ($like) {
$likeCond = '(' . join(' AND ', $like) . ')';
}
}
$mainTableAlias = 's';
$fields = array(
'query_id' => new Zend_Db_Expr($query->getId()),
'product_id',
);
$select = $adapter->select()
->from(array($mainTableAlias => $this->getMainTable()), $fields)
->joinInner(array('e' => $this->getTable('catalog/product')),
'e.entity_id = s.product_id',
array())
->where($mainTableAlias.'.store_id = ?', (int)$query->getStoreId());
if ($searchType == Mage_CatalogSearch_Model_Fulltext::SEARCH_TYPE_FULLTEXT
|| $searchType == Mage_CatalogSearch_Model_Fulltext::SEARCH_TYPE_COMBINE
) {
$bind[':query'] = implode(' ', $preparedTerms[0]);
$where = Mage::getResourceHelper('catalogsearch')
->chooseFulltext($this->getMainTable(), $mainTableAlias, $select);
}
if ($likeCond != '' && $searchType == Mage_CatalogSearch_Model_Fulltext::SEARCH_TYPE_COMBINE) {
$where .= ($where ? ' AND ' : '') . $likeCond;
} elseif ($likeCond != '' && $searchType == Mage_CatalogSearch_Model_Fulltext::SEARCH_TYPE_LIKE) {
$select->columns(array('relevance' => new Zend_Db_Expr(0)));
$where = $likeCond;
}
if ($where != '') {
$select->where($where);
}
$sql = $adapter->insertFromSelect($select,
$this->getTable('catalogsearch/result'),
array(),
Varien_Db_Adapter_Interface::INSERT_ON_DUPLICATE);
$adapter->query($sql, $bind);
$query->setIsProcessed(1);
}
return $this;
}
I think you can try this free extension for default search
http://www.magentocommerce.com/magento-connect/catalog/product/view/id/12202/s/enhanced-default-search-9697
How to get specific product attribute value if i know product ID without loading whole product?
Mage::getResourceModel('catalog/product')->getAttributeRawValue($productId, 'attribute_code', $storeId);
A way that I know of:
$product->getResource()->getAttribute($attribute_code)
->getFrontend()->getValue($product)
you can use
<?php echo $product->getAttributeText('attr_id') ?>
Please see Daniel Kocherga's answer, as it'll work for you in most cases.
In addition to that method to get the attribute's value, you may sometimes want to get the label of a select or multiselect. In that case, I have created this method which I store in a helper class:
/**
* #param int $entityId
* #param int|string|array $attribute atrribute's ids or codes
* #param null|int|Mage_Core_Model_Store $store
*
* #return bool|null|string
* #throws Mage_Core_Exception
*/
public function getAttributeRawLabel($entityId, $attribute, $store=null) {
if (!$store) {
$store = Mage::app()->getStore();
}
$value = (string)Mage::getResourceModel('catalog/product')->getAttributeRawValue($entityId, $attribute, $store);
if (!empty($value)) {
return Mage::getModel('catalog/product')->getResource()->getAttribute($attribute)->getSource()->getOptionText($value);
}
return null;
}
It seems impossible to get value without loading product model. If you take a look at file app/code/core/Mage/Eav/Model/Entity/Attribute/Frontend/Abstract.php you'll see the method
public function getValue(Varien_Object $object)
{
$value = $object->getData($this->getAttribute()->getAttributeCode());
if (in_array($this->getConfigField('input'), array('select','boolean'))) {
$valueOption = $this->getOption($value);
if (!$valueOption) {
$opt = new Mage_Eav_Model_Entity_Attribute_Source_Boolean();
if ($options = $opt->getAllOptions()) {
foreach ($options as $option) {
if ($option['value'] == $value) {
$valueOption = $option['label'];
}
}
}
}
$value = $valueOption;
}
elseif ($this->getConfigField('input')=='multiselect') {
$value = $this->getOption($value);
if (is_array($value)) {
$value = implode(', ', $value);
}
}
return $value;
}
As you can see this method requires loaded object to get data from it (3rd line).
First we must ensure that the desired attribute is loaded, and then output it. Use this:
$product = Mage::getModel('catalog/product')->load('<product_id>', array('<attribute_code>'));
$attributeValue = $product->getResource()->getAttribute('<attribute_code>')->getFrontend()->getValue($product);
Try this
$attribute = $_product->getResource()->getAttribute('custom_attribute_code');
if ($attribute)
{
echo $attribute_value = $attribute ->getFrontend()->getValue($_product);
}
You don't have to load the whole product.
Magentos collections are very powerful and smart.
$collection = Mage::getModel('catalog/product')->getCollection();
$collection->addAttributeToFilter('entity_id', $product->getId());
$collection->addAttributeToSelect('manufacturer');
$product = $collection->getFirstItem();
$manufacturer = $product->getAttributeText('manufacturer');
At the moment you call getFirstItem() the query will be executed and the result product is very minimal:
[status] => 1
[entity_id] => 38901
[type_id] => configurable
[attribute_set_id] => 9
[manufacturer] => 492
[manufacturer_value] => JETTE
[is_salable] => 1
[stock_item (Varien_Object)] => Array
(
[is_in_stock] => 1
)
This one works-
echo $_product->getData('ATTRIBUTE_NAME_HERE');
You can get attribute value by following way
$model = Mage::getResourceModel('catalog/product');
$attribute_value = $model->getAttributeRawValue($productId, 'attribute_code', $storeId);
$orderId = 1; // YOUR ORDER ID
$items = $block->getOrderItems($orderId);
foreach ($items as $item) {
$options = $item->getProductOptions();
if (isset($options['options']) && !empty($options['options'])) {
foreach ($options['options'] as $option) {
echo 'Title: ' . $option['label'] . '<br />';
echo 'ID: ' . $option['option_id'] . '<br />';
echo 'Type: ' . $option['option_type'] . '<br />';
echo 'Value: ' . $option['option_value'] . '<br />' . '<br />';
}
}
}
all things you will use to retrieve value product custom option cart order in Magento 2: https://www.mageplaza.com/how-get-value-product-custom-option-cart-order-magento-2.html
You could write a method that would do it directly via sql I suppose.
Would look something like this:
Variables:
$store_id = 1;
$product_id = 1234;
$attribute_code = 'manufacturer';
Query:
SELECT value FROM eav_attribute_option_value WHERE option_id IN (
SELECT option_id FROM eav_attribute_option WHERE FIND_IN_SET(
option_id,
(SELECT value FROM catalog_product_entity_varchar WHERE
entity_id = '$product_id' AND
attribute_id = (SELECT attribute_id FROM eav_attribute WHERE
attribute_code='$attribute_code')
)
) > 0) AND
store_id='$store_id';
You would have to get the value from the correct table based on the attribute's backend_type (field in eav_attribute) though so it takes at least 1 additional query.
If you have an text/textarea attribute named my_attr you can get it by:
product->getMyAttr();