I need to set the pagination order of my register based on field ($results[$key]['Movimento']['status']) created in afterFind callback.
afterFind:
public function afterFind($results, $primary = false) {
foreach ($results as $key => $val) {
if(isset($val['Movimento']['data_vencimento'])) {
$data = $val['Movimento']['data_vencimento'];
$dtVc = strtotime($data);
$dtHj = strtotime(date('Y-m-d'));
$dtVencendo = strtotime("+7 day", $dtHj);
if ($dtVc < $dtHj) {
$results[$key]['Movimento']['status'] = 'vencido';
} elseif ($dtVc <= $dtVencendo) {
$results[$key]['Movimento']['status'] = 'vc15dias';
} else {
$results[$key]['Movimento']['status'] = 'aberto';
}
}
if(isset($val['Movimento']['data_pagamento'])) {
$results[$key]['Movimento']['status'] = 'quitado';
}
}
return $results;
Pagination:
$options = array(
...
'order' => array('Movimento.status' => 'ASC')
);
$this->controller->paginate = $options;
$movimentos = $this->controller->paginate('Movimento');
I know this does not work because the field is created after the paginator call.
Can I make it work?
as I understand, you want to sort by data_pagamento and than by data_vencimento (has it the mysql-type date?)
so you don't need your afterFind-function for ordering, simply use:
'order' => array(
'Movimento.data_pagamento DESC',//first all rows with not-empty data_pagamento
'Movimento.data_vencimento DESC',// first all dates in the furthest future
)
Related
I have this php function in codeigniter where it fetches the data from my database:
function fetch_data()
{
$data = $this->projectionchart_model->make_query();
$array = array();
foreach($data as $row)
{
$array[] = $row;
}
$output = array(
'current' => intval($_POST["current"]),
'rowCount' => 10,
'total' => intval($this->projectionchart_model->count_all_data()),
'rows' => $array
);
echo json_encode($output);
}
I want to use the number_format function to some of columns and right now it's building everything in an array. How could I remove the array and list the data individually as variables so I can apply a function to some of them and then output them?
Thank you
Edit: explaining in more detail
This function fetch_data() calls the make_query() function stored in the projectionchart_model file which contains the following:
function make_query()
{
if(isset($_POST["rowCount"]))
{
$this->records_per_page = $_POST["rowCount"];
}
else
{
$this->records_per_page = 10;
}
if(isset($_POST["current"]))
{
$this->current_page_number = $_POST["current"];
}
$this->start_from = ($this->current_page_number - 1) * $this->records_per_page;
$this->db->select("*");
$this->db->from("projection_chart");
if(!empty($_POST["searchPhrase"]))
{
$this->db->like('ae', $_POST["searchPhrase"]);
$this->db->or_like('client', $_POST["searchPhrase"]);
$this->db->or_like('product', $_POST["searchPhrase"]);
$this->db->or_like('week_of', $_POST["searchPhrase"]);
$this->db->or_like('month', $_POST["searchPhrase"]);
$this->db->or_like('type', $_POST["searchPhrase"]);
}
if(isset($_POST["sort"]) && is_array($_POST["sort"]))
{
foreach($_POST["sort"] as $key => $value)
{
$this->db->order_by($key, $value);
}
}
else
{
$this->db->order_by('id', 'DESC');
}
if($this->records_per_page != -1)
{
$this->db->limit($this->records_per_page, $this->start_from);
}
$query = $this->db->get();
return $query->result_array();
}
So the output currently is this:
I want to format the Planned Spend, Cleared and Total Commission with the number_format php function but right now it's all in an array.
How could I accomplish this?
Am trying to update multiple records in the database but my case I have a column total, which I want to update to different values. I haven't tried much here but hope I could get a clue on how to go about this.
My controller
public function update_record()
{
$id = ["19821", "19923", "19966", "19967"];
$total = ["8", "118", "90", "100"];
if ($this->some_model->batch_data('records', $total, $id) == true) {
echo "yes";
} else {
echo "no";
}
}
The Model
public function batch_data($table, $data, $where)
{
$this->db->where_in('id',$where);
$this->db->set('total',$data);
$this->db->update($table);
return true;
}
I have not tested this yet but currently looking for a more and efficient way of doing this.
If you still want to update multiple records using the update_batch method, you could first assign the id and total as key-value arrays, then use the update_batch method.
Controller :
public function update_record()
{
$id = ["19821", "19923", "19966", "19967"];
$total = ["8", "118", "90", "100"];
$update_data = [];
foreach ($id as $key => $value) {
$update_data[] = [
'id' => $value,
'total' => $total[$key]
];
}
if ($this->some_model->batch_data('records', $update_data) == true) {
echo "yes";
} else {
echo "no";
}
}
Model :
public function batch_data($table, $data)
{
$this->db->update_batch($table, $data, 'id'); // this will set the id column as the condition field
return true;
}
Output :
// preview query output :
// UPDATE `records`
// SET
// `total` =
// CASE
// WHEN `id` = '19821' THEN 8
// WHEN `id` = '19923' THEN 118
// WHEN `id` = '19966' THEN 90
// WHEN `id` = '19967' THEN 100
// ELSE `total`
// END
// WHERE `id` IN ('19821', '19923', '19966', '19967')
As per my comment. This is a method that combines the array in to key/value pairs and updates them 1x1 wrapped in a transaction (so if one query fails nothing changes).
This is the method I would personally use as I don't like update_batchs internal workings (cases).
$id = ["19821", "19923", "19966", "19967"];
$total = ["8", "118", "90", "100"];
$combined = array_combine($id, $total);
if (count($combined) > 0) {
$this->db->trans_start();
foreach ($combined as $id => $total) {
$this->db->set('total', $total);
$this->db->where('id', $id);
$this->db->update('sometable');
}
$this->db->trans_complete();
return $this->db->trans_status();
}
return true;
Try this, Only for single where condition
Controller:
public function update_record()
{
$tableName = "records";
$id = ["19821", "19923", "19966", "19967"];
$total = ["8", "118", "90", "100"];
$update_data = [];
foreach ($id as $key => $value) {
$update_data[] = [
'id' => $value,
'total' => $total[$key]
];
}
$whereKey = 'id';
$this->$this->some_model->batch_data($tableName, $updateData, $whereKey);
}
Model:
public function batch_data($tableName, $updateData, $whereKey)
{
$this->db->update_batch($tableName, $updateData, $whereKey);
}
I tried to find solutions
but i always get this error
You must specify an index to match on for batch updates.
public function editcompanionship()
{
$companionship_id = $this->input->post('companionship_id[]');
$missionary_one_id = $this->input->post('missionary_one_id[]');
$missionary_two_id = $this->input->post('missionary_two_id[]');
$missionary_three_id = $this->input->post('missionary_three_id[]');
$value_batch_update = array();
for($i=0; $i<count($companionship_id); $i++):
$value_batch_update[$i] = array(
'missionary_one_id' => $missionary_one_id[$i],
'missionary_two_id' => $missionary_two_id[$i],
'missionary_three_id' => $missionary_three_id[$i],
'modified' => date('Y-m-d H:i:s', time()),
);
endfor;
$this->db->where('companionship_id',$companionship_id[$i]);
$this->db->update_batch('pcdom_companionship',$value_batch_update);
$this->session->set_flashdata("success",alert("alert-success","Updated Successfully!"));
redirect(base_url('mrec/companionship'));
exit();
}
Can Any body knows?
The 3rd param of method update_batch() is required.
public function update_batch($table, $set = NULL, $index = NULL, $batch_size = 100)
{
....
if ($index === NULL)
{
return ($this->db_debug) ? $this->display_error('db_must_use_index') : FALSE;
}
...
I am currently running a wordpress backend and want to display some tweets based on hastags on my website. For the general API request and database storage, I use this function:
private function parseRequest($json) {
$tmp = $json;
$result = array();
if (isset($json['statuses'])) {
$tmp = $json['statuses'];
}
if (isset($tmp) && is_array($tmp)){
foreach ($tmp as $t) {
$this->image = null;
$this->media = null;
$tc = new \stdClass();
$tc->feed_id = $this->id();
$tc->id = $t['id_str'];
$tc->type = $this->getType();
$tc->nickname = '#'.$t['user']['screen_name'];
$tc->screenname = (string)$t['user']['name'];
$tc->userpic = str_replace('.jpg', '_200x200.jpg', str_replace('_normal', '', (string)$t['user']['profile_image_url']));
$tc->system_timestamp = strtotime($t['created_at']);
$tc->text = $this->getText($t);
$tc->userlink = 'https://twitter.com/'.$t['user']['screen_name'];
$tc->permalink = $tc->userlink . '/status/' . $tc->id;
$tc->media = $this->getMedia($t);
#$tc->additional = array('shares' => (string)$t['retweet_count'], 'likes' => (string)$t['favorite_count'], 'comments' => (string)$t['reply_count']);
if ($this->isSuitablePost($tc)) $result[$tc->id] = $tc;
}
}
return $result;
}
Now I am looking for a function that counts all the variable in the "additional array together e.g. shares + likes + comments and sorts all posts based on the resulting number.
I am using the standard wordpress sql database. I cannot find a solution or I am just blind.
Thanks in regards
You could use a simple usort function:
usort($tc, function($a, $b) {
$a_sum = array_sum($a->additional);
$b_sum = array_sum($b->additional);
if ($a_sum == $b_sum) {
return 0;
}
return ($a_sum < $b_sum) ? -1 : 1;
});
This has been bugging me for quite a while. Basically, what we are trying to achieve is in the bestsellers on our front page, to have the products listed in the amount sold. For simple products this works fine, however for configurable products they will be displayed as a quantity ordered of 0.
I somehow need to find a way to get the configurable products, find the simple products attached to them, sum the amount sold of these simple products, add this back to the configurable products ID and feed this information back in so it will list the configurable product with the right amount that has been sold.
I have placed, what I believe, the areas of code that require changing. If anyone could help it would be very much appreciated!
Collection.php
class Luxe_Bestsellers_Model_Mysql4_Product_Collection extends Mage_Reports_Model_Mysql4_Product_Collection
{
public function addOrderedQty($from = '', $to = '', $getComplexProducts=false)
{
$qtyOrderedTableName = $this->getTable('sales/order_item');
$qtyOrderedFieldName = 'qty_ordered';
$productIdFieldName = 'product_id';
if (!$getComplexProducts) {
$compositeTypeIds = Mage::getSingleton('catalog/product_type')->getCompositeTypes();
$productTypes = $this->getConnection()->quoteInto(' AND (e.type_id NOT IN (?))', $compositeTypeIds);
} else {
$productTypes = '';
}
if ($from != '' && $to != '') {
$dateFilter = " AND `order`.created_at BETWEEN '{$from}' AND '{$to}'";
} else {
$dateFilter = "";
}
$this->getSelect()->reset()->from(
array('order_items' => $qtyOrderedTableName),
array('ordered_qty' => "SUM(order_items.{$qtyOrderedFieldName})")
);
$_joinCondition = $this->getConnection()->quoteInto(
'order.entity_id = order_items.order_id AND order.state<>?', Mage_Sales_Model_Order::STATE_CANCELED
);
$_joinCondition .= $dateFilter;
$this->getSelect()->joinInner(
array('order' => $this->getTable('sales/order')),
$_joinCondition,
array()
);
$this->getSelect()
->joinInner(array('e' => $this->getProductEntityTableName()),
"e.entity_id = order_items.{$productIdFieldName} AND e.entity_type_id = {$this->getProductEntityTypeId()}{$productTypes}")
->group('e.entity_id')
->having('ordered_qty > 0');
return $this;
}
}
List.php
class Luxe_Bestsellers_Block_List extends Mage_Catalog_Block_Product_List
{
protected $_defaultToolbarBlock = 'bestsellers/list_toolbar';
protected function _beforeToHtml() {
$this->addPriceBlockType('bundle', 'bundle/catalog_product_price', 'bundle/catalog/product/price.phtml');
return parent::_beforeToHtml();
}
public function _toHtml()
{
if ($this->_productCollection->count()) {
return parent::_toHtml();
} else {
return '';
}
}
public function getTimeLimit()
{
if ($this->getData('time_limit_in_days')) {
return intval($this->getData('time_limit_in_days'));
} else {
return intval(Mage::getStoreConfig('bestsellers/bestsellers/time_limit_in_days'));
}
}
public function getBlockTitle()
{
if ($this->getData('title')) {
return $this->getData('title');
} else {
return Mage::getStoreConfig('bestsellers/bestsellers/title');
}
}
public function isShowOutOfStock() {
return (bool)Mage::getStoreConfig('bestsellers/bestsellers/show_out_of_stock');
}
public function getProductsLimit()
{
if ($this->getData('limit')) {
return intval($this->getData('limit'));
} else {
return $this->getToolbarBlock()->getLimit();
}
}
public function getDisplayMode()
{
return $this->getData('display_mode');
}
/**
* Retrieve loaded category collection
*
* #return Mage_Eav_Model_Entity_Collection_Abstract
*/
protected function _getProductCollection()
{
if (is_null($this->_productCollection)) {
$layer = Mage::getModel('catalog/layer');
$bestsellers = Mage::getResourceModel('reports/product_collection');
if ($this->getTimeLimit()) {
$product = Mage::getModel('catalog/product');
$todayDate = $product->getResource()->formatDate(time());
$startDate = $product->getResource()->formatDate(time() - 60 * 60 * 24 * $this->getTimeLimit());
$bestsellers->addOrderedQty($startDate, $todayDate, true);
} else {
$bestsellers->addOrderedQty('', '', true);
}
$bestsellers->addStoreFilter()
->setOrder('ordered_qty', 'desc')
->setPageSize($this->getProductsLimit());
Mage::getSingleton('catalog/product_status')->addVisibleFilterToCollection($bestsellers);
if ($layer->getCurrentCategory()->getId() != Mage::app()->getStore()->getRootCategoryId()) {
$bestsellers->addCategoryFilter($layer->getCurrentCategory());
Mage::getSingleton('catalog/product_visibility')->addVisibleInCatalogFilterToCollection($bestsellers);
}
if (!$this->isShowOutOfStock()) {
Mage::getModel('cataloginventory/stock')->addInStockFilterToCollection($bestsellers);
}
$bestsellers->getSelect()->where('order.store_id = ?', Mage::app()->getStore()->getId());
$productIds = array();
foreach ($bestsellers as $p) {
$productIds[] = $p->getId();
}
$collection = Mage::getResourceModel('catalog/product_collection');
Mage::getModel('catalog/layer')->prepareProductCollection($collection);
$attributes = Mage::getSingleton('catalog/config')->getProductAttributes();
$collection->addIdFilter($productIds)
->addAttributeToSelect($attributes)
->addMinimalPrice()
->addFinalPrice();
$this->_productCollection = $collection;
}
return $this->_productCollection;
}
/**
* Translate block sentence
*
* #return string
*/
public function __()
{
$args = func_get_args();
$expr = new Mage_Core_Model_Translate_Expr(array_shift($args), 'Mage_Catalog');
array_unshift($args, $expr);
return Mage::app()->getTranslator()->translate($args);
}
}
Thanks for posting that sample code! I was able to use it to create a solution which should work well for both of us.
I found that configurable product sales are being summed correctly but aren't being included in the results; their child products appear instead. My solution was to include configurable products, do a left join on the catalog_product_super_link table, and filter out anything that has a parent_id. Here are the changes you'll need to make:
Collection.php:
public function addOrderedQty($from = '', $to = '', $getComplexProducts=false, $getComplexChildProducts = true, $getRemovedProducts = true)
{
$qtyOrderedTableName = $this->getTable('sales/order_item');
$qtyOrderedFieldName = 'qty_ordered';
$productIdFieldName = 'product_id';
if (!$getComplexProducts) {
$compositeTypeIds = Mage::getSingleton('catalog/product_type')->getCompositeTypes();
$productTypes = $this->getConnection()->quoteInto(' AND (e.type_id NOT IN (?))', $compositeTypeIds);
} else {
$productTypes = '';
}
if ($from != '' && $to != '') {
$dateFilter = " AND `order`.created_at BETWEEN '{$from}' AND '{$to}'";
} else {
$dateFilter = "";
}
$this->getSelect()->reset()->from(
array('order_items' => $qtyOrderedTableName),
array(
'ordered_qty' => "SUM(order_items.{$qtyOrderedFieldName})",
'order_items_name' => 'order_items.name'
)
);
$_joinCondition = $this->getConnection()->quoteInto(
'order.entity_id = order_items.order_id AND order.state<>?', Mage_Sales_Model_Order::STATE_CANCELED
);
$_joinCondition .= $dateFilter;
$this->getSelect()->joinInner(
array('order' => $this->getTable('sales/order')),
$_joinCondition,
array()
);
// Add join to get the parent id for configurables
$this->getSelect()->joinLeft(
array('cpsl' => $this->getTable('catalog/product_super_link')),
'cpsl.product_id = order_items.product_id',
'cpsl.parent_id'
);
if(!$getComplexChildProducts)
$this->getSelect()->having('parent_id IS NULL');
if($getRemovedProducts)
{
$this->getSelect()
->joinLeft(array('e' => $this->getProductEntityTableName()),
"e.entity_id = order_items.{$productIdFieldName} AND e.entity_type_id = {$this->getProductEntityTypeId()}{$productTypes}")
->group('order_items.product_id');
}
else
{
$this->getSelect()
->joinInner(array('e' => $this->getProductEntityTableName()),
"e.entity_id = order_items.{$productIdFieldName} AND e.entity_type_id = {$this->getProductEntityTypeId()}{$productTypes}")
->group('e.entity_id');
}
$this->getSelect()->having('ordered_qty > 0');
// This line is for debug purposes, in case you'd like to see what the SQL looks like
// $x = $this->getSelect()->__toString();
return $this;
}
List.php - Find the following two lines...
$bestsellers->addOrderedQty($startDate, $todayDate, true);
$bestsellers->addOrderedQty('', '', true);
... and change them to:
$bestsellers->addOrderedQty($startDate, $todayDate, true, false, false);
$bestsellers->addOrderedQty('', '', true, false, false);
My changes added two new optional parameters, which both default to true, as to not break existing functionality.
When $getComplexChildProducts is set to false, all child items of the configurable product will be removed from the results.
$getRemovedProducts determines whether or not previously ordered products (which have since been deleted from Magento) should also appear.
Please note that your report statistics will need to be up-to-date in order to get accurate results.
Hope this helps! Let me know if you have any questions.
You can use the following piece of code to get the simple products attached to the configurable product. I'm not sure if this is 100% correct, I haven't tried it myself.
$simpleProducts = Mage::getModel('catalog/product_type_configurable')->getUsedProducts(null, $product);