I'm trying to create small application on Yii framework but can't understand one moment. I have Order model that extends from CActiveRecord and in index action I trying to use Order model twice but having some troubles.
The reason is to show paginated records in table and in last row I wish to show average totals for some fields, and this totals must be calculated for all records filtered by sort/filter criteria
Here is code of action:
public function actionIndex()
{
$model = new Order('search');
$model->unsetAttributes();
if (isset($_GET['Order']))
$model->attributes = $_GET['Order'];
// Get average totals by current filters
$totals = array();
$tm = clone $model;
$tmdp = $tm->search();
$tmdp->criteria->select = array('avg(price) as avgPrice', 'avg(cost) as avgCost');
$data = $tmdp->getData(true);
$totals['cost'] = number_format($data[0]->avgCost, 0, '.', ' ');
$totals['price'] = number_format($data[0]->avgPrice, 0, '.', ' ');
$totals['marja'] = Order::getMarjaVal(round($data[0]->avgCost, 0), round($data[0]->avgPrice, 0));
$this->render('index', array(
'model' => $model,
'totals' => $totals
));
}
In my view I'm getting data in the same way $data = $model->search()->getData();
So if I view first page - all working good, but if I change page then $data = $tmdp->getData(true); getting empty array. I also tried to set page for $tmdp like:
$tmdp->criteria->select = array('avg(price) as avgPrice', 'avg(cost) as avgCost');
$tmdp->pagination->setCurrentPage(0);
$data = $tmdp->getData(true);
but after this I getting data in my view only from first page.
Please can someone tell me how to do this correctly???
When we change current page in pagination Yii automatically updates $_GET['Order_page'] value (if this value wasn't setted - it will create it), and pagination automatically gets this value when we getting data from data provider. So for this code i made such changes:
public function actionIndex()
{
$model = new Order('search');
$model->unsetAttributes();
if (isset($_GET['Order']))
$model->attributes = $_GET['Order'];
// Get average totals by current filters
$totals = array();
$tm = clone $model;
$tdp = $tm->search();
$tdp->criteria->select = array('avg(price) as avgPrice', 'avg(cost) as avgCost');
if (isset($_GET['Order_page'])) {
$curPage = $_GET['Order_page'] - 1;
} else {
$curPage = 0;
}
$tdp->pagination->currentPage = 0;
$data = $tdp->getData(true);
$totals['cost'] = number_format($data[0]->avgCost, 0, '.', ' ');
$totals['price'] = number_format($data[0]->avgPrice, 0, '.', ' ');
$totals['marja'] = Order::getMarjaVal(round($data[0]->avgCost, 0), round($data[0]->avgPrice, 0));
$tdp->pagination->currentPage = $curPage;
$this->render('index', array(
'model' => $model,
'totals' => $totals
));
}
So we trying to get page from $_GET global array and after owr operation we just update this value back
Related
I would like to give the cart object a new id, I have the following code:
if ($payment->order_result->return->failures->failure == 'field.ordernumber.exists') {
$dup = $this->context->cart->duplicate();
$this->context->cart->delete();
$this->context->cart = new Cart($dup['cart']->id);
}
The cart isn’t “replaced”, I tried several things: use the $GLOBALS of global keyword, but nothing really replaces or changes the cart object. What is the best approach?
Try with :
if ($payment->order_result->return->failures->failure == 'field.ordernumber.exists') {
$context = Context::getContext();
$cart_products = $context->cart->getProducts();
$this->context->cart->delete();
$newCart = new Cart();
if (!$context->cart->id) {
$guest = new Guest();
$context->cart->mobile_theme = $guest->mobile_theme;
$context->cart->add();
if ($context->cart->id)
$context->cookie->id_cart = (int)$context->cart->id;
}
foreach ($cart_products as $product) {
Db::getInstance()->insert('cart_product', array(
'id_product' => (int)$product->id,
'id_product_attribute' => (int)0,
'id_cart' => (int)$newCart->id,
'quantity' => (int)$product->quantity,
'date_add' => date('Y-m-d H:i:s')
));
}
}
Inspired by the answer of #ethercreation, I changed the following to solve my problem:
From
$dup = $this->context->cart->duplicate();
$this->context->cart->delete();
$this->context->cart = new Cart($dup['cart']->id);
To
$dup = $this->context->cart->duplicate();
$this->context->cart->delete();
$this->context->cookie->id_cart = $dup['cart']->id;
The essential part is $this->context->cart cannot be changed. The cart needs to be copied, then the current cart in the cookie should be changed. Therefore the cookie $this->context->cookie->id_cart should be changed to the id_cart of the newly created cart!
I am developing a module that would save a custom field from product admin.. but my code is not inserting data into database.. below is my code.
public function hookActionProductUpdate($params)
{
if(Tools::isSubmit('submitDimension'))
{
$name = Tools::getValue('name');
$length = Tools::getValue('custom_length');
$width = Tools::getValue('custom_width');
if(empty($name) || !Validate::isGenericName($name))
$this->errors[] = $this->module->l('Invalid name');
if(empty($length) || !Validate::isGenericName($length))
$this->errors[] = $this->module->l('Invalid length');
if(empty($width) || !Validate::isGenericName($width))
$this->errors[] = $this->module->l('Invalid width');
if(!$this->errors)
{
$dimension = array(
'name' => $name,
'custom_length' => $length,
'custom_width' => $width
);
if(!Db::getInstance()->insert('product', $dimension));
$this->errors[] = Tools::displayError('Error while updating database');
}
}
}
Anyone can help me please..
Here is my install function
function install()
{
if (!parent::install() ||
!$this->alterProductTable() ||
!$this->registerHook('extraright') ||
!$this->registerHook('displayAdminProductsExtra') ||
!$this->registerHook('actionProductSave') ||
!$this->registerHook('actionProductUpdate') ||
!$this->registerHook('header')
)
return false;
return true;
}
Here is my alter table function
private function alterProductTable($method = 'add')
{
if($method = 'add')
$sql = '
ALTER TABLE '._DB_PREFIX_.'product
ADD COLUMN `custom_length` decimal(20,6) NOT NULL,
ADD COLUMN `custom_width` decimal(20,6) NOT NULL,
ADD COLUMN `name` VARCHAR(64) NOT NULL';
if(!Db::getInstance()->Execute($sql))
return false;
return true;
}
.. the columns are there..
And here is my display admin hook
public function hookDisplayAdminProductsExtra($params)
{
$name = Db::getInstance()->getValue('SELECT `name` FROM '._DB_PREFIX_.'product WHERE id_product = '.Tools::getValue('id_product'));
$length = Db::getInstance()->getValue('SELECT custom_length FROM '._DB_PREFIX_.'product WHERE id_product = '.(int)Tools::getValue('id_product'));
$width = Db::getInstance()->getValue('SELECT custom_width FROM '._DB_PREFIX_.'product WHERE id_product = '.(int)Tools::getValue('id_product'));
$this->context->smarty->assign(array(
'name' => $name,
'length' => $length,
'width' => $width
));
return $this->display(__FILE__, 'views/templates/hook/adminProductsExtra.tpl');
}
I have been looking at this for 2 days.. and I cant seem to find what I did wrong.. I have gone to prestashop forum but no help so far.. I hope I can get something from good people here. thanks in advance!
Do you check the Prestashop db best practice guide if not than please check first.
This is not the correct way to insert data you also need to mention fields in which you want to insert data particular table.
Best Practices of the Db Class - Prestashop
All is wrong, you are trying to insert data in a table which have many other fields required, and you are trying also to insert data in columns that doesn't exist in that table. The best way to create new products by code is using their object, like this...
$product = new Product()
$product->id_tax_rules_group = 1;
$product->redirect_type = '404';
$product->name = array(
$id_lang => 'Product name in this lang',
$id_lang => 'Product name in this lang',
);
/*
* And so on all the mandatory fields
*/
$product->save();
I want to insert many record to database in one action.
In this controller I used foreach for insert to database, but just the last record inserts to database, I don't know why. I want to insert all the record to database.
My controller:
if (isset($_POST['month'])) {
$name = $_POST['month'];
$price = $_POST['Request'];
$i = 0;
foreach ($name as $month) {
$model->month = $month;
$model->price = $price['price'];
$model->save(false);
$i++;
}
$pay_info = [
'cost' => $price['price'],
'title' => 'title'];
return $this->render('payment', ['pay_info' => $pay_info]);
}
A simple way is based on the fact you should create a new model in you foreach for each instance you want save
(your controller code is not complete so i can't know your model )
if (isset($_POST['month'])) {
$name = $_POST['month'];
$price = $_POST['Request'];
$i = 0;
foreach ($name as $month) {
$model = new YourModel(); /* here */
$model->month = $month;
$model->price = $price['price'];
$model->save(false);
$i++;
}
$pay_info = [
'cost' => $price['price'],
'title' => 'title'];
return $this->render('payment', ['pay_info' => $pay_info]);
}
but i siggest to explore also the batchInsert command http://www.yiiframework.com/doc-2.0/yii-db-command.html#batchInsert()-detail
For batch insert you can build an asscociative array with month and price eg:
$my_array= [
['January', 30],
['Febrary', 20],
['March', 25],
]
\Yii::$app->db->createCommand()->
batchInsert('Your_table_name', ['month', 'price'],$my_array)->execute();
I'm developing a module for prestashop 1.5.3. I need to create a custom admin tab during the module installation. I make the install like this
public function install()
{
if( (parent::install() == false)||(!$this->_createTab()) )
return false;
return true;
}
And the _createTab method is:
private function _createTab()
{
$tab = new Tab();
$tab->id_parent = 7; // Modules tab
$tab->class_name='AdminWarranty';
$tab->module='fruitwarranty';
$tab->name[(int)(Configuration::get('PS_LANG_DEFAULT'))] = $this->l('Warranty');
$tab->active=1;
if(!$tab->save()) return false;
return true;
}
And nothing happens.. What am I doing wrong.. and where to find good prestashop developer reference.?
To create a custom tab for a module during installation you can use the following code.
Note: I am considering a test module called News.
private function _createTab()
{
/* define data array for the tab */
$data = array(
'id_tab' => '',
'id_parent' => 7,
'class_name' => 'AdminNews',
'module' => 'news',
'position' => 1, 'active' => 1
);
/* Insert the data to the tab table*/
$res = Db::getInstance()->insert('tab', $data);
//Get last insert id from db which will be the new tab id
$id_tab = Db::getInstance()->Insert_ID();
//Define tab multi language data
$data_lang = array(
'id_tab' => $id_tab,
'id_lang' => Configuration::get('PS_LANG_DEFAULT'),
'name' => 'News'
);
// Now insert the tab lang data
$res &= Db::getInstance()->insert('tab_lang', $data_lang);
return true;
} /* End of createTab*/
I hope the above code will help
Thanks
Well, I'm myself developing a PrestaShop module so in case someone lands here, the proper way.
For root tabs:
$rootTab = new Tab();
$rootTab->active = 1;
$rootTab->class_name = 'YourAdminControllerName';
$rootTab->name = array();
foreach (Language::getLanguages(true) as $lang) {
$rootTab->name[$lang['id_lang']] = $this->l("Root tab");
}
$rootTab->id_parent = 0; // No parent
$rootTab->module = $this->name;
$rootTab->add();
Note for version 1.5: When creating a root tab, the system will look for a YourAdminControllerName.gif in your module's folder as the tab icon. Also please note that root tabs don't work as links, despite them requiring a class_name.
For non-root tabs:
$tab = new Tab();
$tab->active = 1;
$tab->class_name = 'YourAdminControllerName';
$tab->name = array();
foreach (Language::getLanguages(true) as $lang) {
$tab->name[$lang['id_lang']] = $this->l("Non-root tab");
}
$tab->id_parent = $rootTab->id; // Set the root tab we just created as parent
$tab->module = $this->name;
$tab->add();
If you want to set an existing tab as parent, you can use the getIdFromClassName function. For example, in your case:
$tab->id_parent = (int)Tab::getIdFromClassName('AdminModules');
The add() function returns false if it fails, so you can use it in the if() as you were trying to do with the save() function.
Sadly PrestaShop is by far the worst documented CMS system I've had to work with, and the only way to really code for it is reading code, so I hope it helps someone.
So far found plenty of help to get the pagination working for a get(table) command.
What I need is to pick only few of the entries from a couple of linked tables based on a sql where statement.
I guess the query command is the one to use but in this case how do I do the pagination since that command does not take extra parameters such $config['per_page']
Thanks for the help
Without any more info to go on I think that what you're looking for is something like the following.
public function pagination_example($account_id)
{
$params = $this->uri->ruri_to_assoc(3, array('page'));
$where = array(
'account_id' => $account_id,
'active' => 1
);
$limit = array(
'limit' => 10,
'offset' => (!empty($params['page'])) ? $params['page'] : 0
);
$this->load->model('pagination_model');
$data['my_data'] = $this->pagination_model->get_my_data($where, $limit);
foreach($this->uri->segment_array() as $key => $segment)
{
if($segment == 'page')
{
$segment_id = $key + 1;
}
}
if(isset($segment_id))
{
$config['uri_segment'] = $segment_id;
}
else
{
$config['uri_segment'] = 0;
}
$config['base_url'] = 'http://'.$_SERVER['HTTP_HOST'].'/controller_name/method_name/whatever_your_other_parameters_are/page/';
$config['total_rows'] = $this->pagination_model->get_num_total_rows();// Make a method that will figure out the total number
$config['per_page'] = '10';
$this->load->library('pagination');
$this->pagination->initialize($config);
$data['pagination'] = $this->pagination->create_links();
$this->load->view('pagination_example_view', $data);
}
// pagination_model
public function get_my_data($where = array(), $limit = array())
{
$this->db
->select('whatever')
->from('wherever')
->where($where)
->limit($limit['limit'], $limit['offset']);
$query = $this->db->get();
if($query->num_rows() > 0)
{
$data = $query->result_array();
return $data;
}
return FALSE;
}
This should at least get you on the right track
If this isn't what you're asking I'd happy to help more if you can be a little more specific. How about some of your code.
The only other options that I can think of would be to either code a count in your select statement or not limit the query and use array_slice to select a portion of the returned array.