Magento resource: custom selects with OR in where (select orders by status) - sql

I'm building a custom module and i'm trying get all orders with specific status:
$canceledQuery = Mage::getSingleton('core/resource')->getConnection('core_read')->select()
->from('mage_sales_flat_order', 'entity_id')
->where('status = ?', 'canceled');
This works very well. But now i'm trying use OR in where, without success.
I have been try this:
$whereCanceled = array();
foreach ($_status as $statusCode => $value) {
$whereCanceled[] = sprintf('%s=:%s', 'status', $statusCode);
}
$ordersQuery = Mage::getSingleton('core/resource')->getConnection('core_read')->select()
->from('mage_sales_flat_order', 'entity_id')
->where(implode(' OR ', $whereCanceled));
So, I don't know how use OR right in this case. I found no use for this with OR. Any idea?

instead of implode use join. magento use join itself.
->where(join(' OR ', $orWhere));//$orWhere array of condition
you can see in below function magento use join for OR condition in where clause
public function getSystemConfigByPathsAndTemplateId($paths, $templateId)
{
$orWhere = array();
$pathesCounter = 1;
$bind = array();
foreach ($paths as $path) {
$pathAlias = 'path_' . $pathesCounter;
$orWhere[] = 'path = :' . $pathAlias;
$bind[$pathAlias] = $path;
$pathesCounter++;
}
$bind['template_id'] = $templateId;
$select = $this->_getReadAdapter()->select()
->from($this->getTable('core/config_data'), array('scope', 'scope_id', 'path'))
->where('value LIKE :template_id')
->where(join(' OR ', $orWhere));
return $this->_getReadAdapter()->fetchAll($select, $bind);
}
for more reference open file located at [magento]/app/code/core/Mage/Core/Model/Resource/Email/Template.php
Hope this help you

Related

Query giving double result instead of single

I have two tables: products and current_product_attribute_values
I have tried a join query to filter them as per attribute selected by the user but when I try this with an additional condition it gives me 2 results instead of one it is including the first one which is not matching as per query:
select * from `products` inner join `current_product_attribute_values` on `products`.`id` = `current_product_attribute_values`.`product_id` where `current_product_attribute_values`.`attribute_id` = ? or `current_product_attribute_values`.`attribute_value_id` = ? and `current_product_attribute_values`.`attribute_id` = ? or `current_product_attribute_values`.`attribute_value_id` = ? and `product_name` LIKE ?
here is my laravel Controller code :
$all = Input::all();
$q = Input::get('search_text');
$att_val = Input::get('attribute_value');
$subcat = Input::get('subcat_id');
$subcat_name = DB::table('subcategories')->where('id', $subcat)->value('subcategory_name');
$brandname = DB::table('brands')->where('subcat_id', $subcat)->value('brand_name');
$brand_id = DB::table('brands')->where('subcat_id', $subcat)->value('id');
$product_count = DB::table('products')->where('brand_id', $brand_id)->count();
if ($q != "") {
// getting multiple same name params
$query = DB::table('products');
$query->join('current_product_attribute_values', 'products.id', '=', 'current_product_attribute_values.product_id');
$j = 0;
foreach ($all as $key => $values) {
//echo 'my current get key is : ' . urldecode($key). '<br>';
if ($key == $name[$j]) {
$query->where('current_product_attribute_values.attribute_id', '=', $att_id_value[$j]);
echo'<br>';
print_r($query->toSql());
echo'<br>';
//echo '<br> key matched and have some value : <br>';
//echo count($values);
if (count($values) >= 1) {
//echo '<br> it has array inside <br>';
foreach ($values as $val) {
// or waali query in same attribute
echo'<br>';
$query->orwhere('current_product_attribute_values.attribute_value_id', '=', $val);
print_r($query->toSql());
echo'<br>';
}
}
$j++;
}
}
$records = $query->toSql();
$query->where('product_name', 'LIKE', '%' . $q . '%');
$records = $query->toSql();
print_r($records);
$products = $query->paginate(10)->setPath('');
$pagination = $products->appends(array(
'q' => Input::get('q')
));
if (count($products) > 0) {
$filters = DB::table('product_attributes')->where('subcategory_id', $subcat)->get(['attribute_title']);
} else {
$filters = array();
}
$categories = categories::where('add_to_menu', 1)->with('subcategories')->with('brands')->get();
$categoryhome = categories::where('add_to_menu', 1)->with('subcategories')->get();
return view('searchfilter')
->with('productsdata', $products)
->with('filtersdata', $filters)
->with('categories', $categories)
->with('categorieshome', $categoryhome)
->with('subcat_name', $subcat_name)
->with('subcat_id', $subcat)
->with('brandname', $brandname)
->with('product_count', $product_count)
->with('querytext', $q);
}
return 'No Details found. Try to search again !';
its easier if you use raw sql as calling db select function. ex:
$query=DB::select("select * from `products` inner join `current_product_attribute_values` on `products`.`id` = `current_product_attribute_values`.`product_id` where `current_product_attribute_values`.`attribute_id` = ? or `current_product_attribute_values`.`attribute_value_id` = ? and `current_product_attribute_values`.`attribute_id` = ? or `current_product_attribute_values`.`attribute_value_id` = ? and `product_name` LIKE ?
");
indeed you can concat vars in raw sql if you need to, ex:
$queryBrands = "select id from brands where subcat_id =".$subcat;
//echo $queryBrands
$queryBrands = DB::select($queryBrands);
By looking at your tables, product table with id value 17 has two records in table current_product_attribute_values in column product_id (I assume this column is used as foreign key to product table).
With select *, you select all of the columns from both tables. So it would most likely cause your query to return multiple records.
My suggestions:
Only select the columns you need. Avoid using select * in the long run, i.e. select product.id, product.description, current_product_attribute_values.attribute_values ......
Make use of GROUP BY
Hope these helps.

update some rows in code igniter

i'm new to codeigniter.
i need some help to update some rows.
here is my model:
public function change()
{
$aa = $this->input->post('id');
$bb = $this->input->post('app');
$query = $this->db->query('select kodeunit from user where email = "hehe#gmail.com"');
foreach ($query->result() as $row)
{
$kode = $row->kodeunit;
}
for($i=0;$i<sizeof($aa);$i++)
{
$data = array(
'approval' => $bb[$i]
);
$this->db->where('id_team', $aa[$i]);
$this->db->where('kodeunit', $kode);
$this->db->update('detail_tim', $data);
}
}
when i tried to update only one row, it worked with this way. but when im trying to update some rows, it doesnt change at all.
please help me to fix this problem thanks
Don't use sizeof() in your for loop, instead use $aa directly if it's an integer or count($aa) if it's an array
for($i=0;$i<count($aa);$i++)
it'll be better if you make it to other variable
$max = count($aa);
for($i=0;$i<$max;$i++)

Zend Framework 2 Zend\Db\Select how to join another Select

How can I make a join with another Select Object? I need make a query like this
$select->join(array('alias' => $subSelect), 'on clause', 'array('*'), 'left');
Something like this was possible in ZF1.x.
In ZF2 first argument of join method is name of table or array with alias but i can't put there \Select. Even if i put here
$select->getSqlString($this->adapter->platform);
string is quoted, and query is not valid. Join doesn't add brackets too. It's really confusing.
Maybe this will help you. This is a working example I have in my TableGateway:
public function Profile($params)
{
$result = $this->select(function (Select $select) use ($params) {
$select
->columns(array(
'ipaddress_type',
'ipaddress',
'domain'
))
->join('product_hosting_profile', 'product_hosting_profile.productid = webaccount.productid', array(
'servers',
'services'
))
->where(array(
$this->adapter->getPlatform()->quoteIdentifierChain(array('webaccount', 'accountid')) . ' = ' . $this->adapter->getPlatform()->quoteValue($params['accountid']),
$this->adapter->getPlatform()->quoteIdentifierChain(array('webaccount', 'productid')) . ' = ' . $this->adapter->getPlatform()->quoteValue($params['productid']),
$this->adapter->getPlatform()->quoteIdentifierChain(array('webaccount', 'webaccountid')). ' = ' . $this->adapter->getPlatform()->quoteValue($params['webaccountid'])
))
->limit(1);
});
return $result->current();
}
$subSelect=new Select(array('A'=>new TableIdentifier('target','CAT')));
$subSelect->columns(array('fk_w','TI'=>'id','mtarget_f'=>new Expression('sum(F)'),
'mcost'=>new Expression('round(sum(F*D.mcost),2)')))
->join(array('B'=>new TableIdentifier('item','CAT')),'B.id=A.fk_w',
array())
->join(array('D'=>new TableIdentifier('rate','CAT')),'A.dat=D.year and D.fk_c=B.CCODE and D.fk_b=A.fk_b',
array())
->where->equalTo('Year', $year);
$select=new Select(array('A'=>new TableIdentifier('item','CAT')));
$select->columns(array('WID'=>'id','AID'=>'AID',
'item'=>'ITEM_ID','Wtitle'=>'WTITLE'))
->join(array('B'=>new TableIdentifier('cn','CAT')),'B.id=A.CCODE',
array('Ct'=>'name'))
->join(array('S'=>$subSelect),'S.fk_w=A.id',array('Mtarget'=>'mcost',
'MTarget'=>'m_target',
'TID'),'left');

Yii: adding custom fields

Is there a simple way of adding custom fields to a model? Say I have a table "user" with 3 fields: id, name and surname. I want this:
$user = User::model()->findByPk(1);
$echo $user->fullName; // echoes name and surname
Please note: I want this custom field to be added via sql, smth like
$c = new CDbCriteria();
$c->select = 'CONCAT("user".name, "user".surname) as fullName';
$user = User::model()->find($c);
Problem is that fullName property is not set.
UPD:
here is the code for a little bit trickier problem -- custom field from another table. This is how it's done:
$model = Application::model();
$model->getMetaData()->columns = array_merge($model->getMetaData()->columns, array('fullName' => 'CONCAT("u".name, "u".surname)'));
$c = new CDbCriteria();
$c->select = 'CONCAT("u".name, "u".surname) as fullName';
$c->join = ' left join "user" "u" on "t".responsible_manager_id = "u".id';
$model->getDbCriteria()->mergeWith($c);
foreach ($model->findAll() as $o) {
echo '<pre>';
print_r($o->fullName);
echo '</pre>';
}
You can add a function to the User class:
public function getFullName() { return $this->name.' '.$this->surname; }
This will return the full name as if it were an attribute from the database. This is much easier than adding a calculated column to the SQL.
In model
public function getMetaData(){
$data = parent::getMetaData();
$data->columns['fullName'] = array('name' => 'fullName');
return $data;
}
Thus not recommended

Piwik plugins

I'm building a plugin, and I want to have a Subtable, so that my users can click on the overview data, and display the data from there.
Following the code that I've been able to glean:
public function getCompanyList($idSite, $period, $date )
{
$dataTable = new Piwik_DataTable();
$query = Piwik_Query("SELECT cl.id, cl.company_name name, sf.id sf_id FROM sitedb.company_lookup cl INNER JOIN sitedb.storefronts sf ON cl.id = sf.company_id");
while ($row = $query->fetch()) {
$piwik_row = new Piwik_DataTable_Row;
$piwik_row->setSubTable( $this->getProductsForCompany($idSite, $period, $date, $row['id']) );
$piwik_row->setColumns( array('id' => $row['id'], 'Company Name' => $row['name']) );
$dataTable->addRow($piwik_row);
}
return $dataTable;
}
public function getProductsForCompany($idSite, $period, $date, $company_id )
{
if (!defined('PIWIK_ENABLE_DISPATCH')) define('PIWIK_ENABLE_DISPATCH', false);
if (!defined('PIWIK_ENABLE_ERROR_HANDLER')) define('PIWIK_ENABLE_ERROR_HANDLER', false);
require_once PIWIK_INCLUDE_PATH . "/index.php";
require_once PIWIK_INCLUDE_PATH . "/core/API/Request.php";
Piwik_FrontController::getInstance()->init();
$request = new Piwik_API_Request('
method=Actions.getActions
&idSite=' . $idSite . '
&date=' . $date . '
&period=' . $period . '
&format=PHP
&filter_column=label
&filter_pattern=product.php
&filter_sort_column=nb_visits
&filter_sort_order=desc
&token_auth=anonymous
');
$result = $request->process();
// contains an array of visits to storefront.php
$result = unserialize($result);
$query = Piwik_Query("SELECT sp.product_id id, sp.name, sp.storefront_id sf_id, cl.company_name FROM sitedb.storefront_products sp INNER JOIN sitedb.storefronts sf ON sp.storefront_id = sf.id INNER JOIN sitedb.company_lookup cl ON sf.company_id = cl.id WHERE cl.id = {$company_id}");
$dataTable = new Piwik_DataTable();
while ($row = $query->fetch()) {
// piwik returns & escaped to & -- make sure that's what you use to search!
$this->array_search_in_level("/product.php?id=" . $row['id'] . "&sf_id=" . $row['sf_id'], $result, 'label', $storefront_array, 1);
if (is_array($storefront_array) && array_key_exists('nb_visits', $storefront_array)) {
$piwik_row = new Piwik_DataTable_Row;
$piwik_row->setColumns( array('id' => $row['id'], 'Product Name' => $row['name'], 'Page Views' => $storefront_array['nb_visits']) );
$dataTable->addRow($piwik_row);
}
}
return $dataTable;
}
However, the subTable never shows up. Am I doing something wrong?
Maybe you need to add the 'expanded=1' parameter to your API request?
http://piwik.org/docs/analytics-api/reference/#toc-optional-api-parameters
If you are looking for example code on how to use the piwik framework to plot custom data in plugins, it looks like they have a bit of doc: Piwik plugins docs