Yii Pagination Variables from DataProvider - yii

I need certain pagination variables in my controller action.
such as:
1.Current Page Number
2.Current Page offset
3.total records displayed
i.e. 31 to 40 of 2005 records displayed
I tried the following:
$dataProvider = NodesTerms::getNodesDataFromTerms($nodeId) ;
$pagination = $dataProvider->getPagination();
var_dump($pagination->getPageCount());
//var_dump($pagination->currentPage);
I can get the Pagination Object, but zero (0) in $pagination->currentPage or $pagination->offset etc....
I need this information to dynamically generate meta page title and description on actions with page listings such as pagetitle: page 3 of 10 for American Recipes...
Appreciate any help with this.

Try setting the itemCount explicitly in your dataProvider:
'pagination'=>array(
'pageSize'=>10,
'itemCount'=>$count
)
Or use a new CPagination object:
$pagination = new CPagination($count);
$dataProvider = new CSqlDataProvider($sql, array(
// ... other config
'pagination' => $pagination
));
How this works:
The pagination's itemCount is set during creation of the data-provider and again in CSqlDataProvider's fetchData function:
$pagination->setItemCount($this->getTotalItemCount());
During creation of data-provider only the values passed to the pagination property are used, and if we don't pass itemCount value, then the default of 0 is used.
So if we want to access offset or pageCount or currentPage or itemCount before the call to fetchData we have to set the itemCount explicitly.
However if we want those values after the call to fetchData then the values are already correctly populated due to the call to setItemCount within fetchData.
An example for clarity (without passing itemCount during data-provider creation):
$dataProvider = NodesTerms::getNodesDataFromTerms($nodeId);
$pagination = $dataProvider->getPagination();
var_dump($pagination->getPageCount()); // this will be zero
$data=$dataProvider->getData(); // getData calls fetchData()
var_dump($pagination->getPageCount()); // now this will be correct value

getCurrentPage returns "the zero-based index of the current page"
http://www.yiiframework.com/doc/api/1.1/CPagination#getCurrentPage-detail
so if you're on the first page, it should be returning 0.
And as you know the page size and the total number of records that will be enough for you to generate your page title.

Related

getProduct()->getTag() return null, when it should return tags associated to the Product

In my project, we have products that has tag called serviceItem. Those item with that tag when ordered should be separated by the quantity into individuals order.
It issue is that getTags() returns null, and getTagIds gets "Call to a member function getTagIds() on null" when it gets to the next loop.
Is there a reason for why getTags() returns null?
private function transformOrderLines(OrderEntity $order): array
{
/**
* TODO: If we need to send advanced prices,
* the price value of the the lines array should be changed to caldulate the advanced price,
* with the built in quantity calculator
*/
$lines = [];
foreach ($order->getLineItems() as $orderLine) {
$hasDsmServiceItemTag = $orderLine->getProduct()->getTags();
$lines[] = [
'name' => $orderLine->getLabel(),
'sku' => substr($orderLine->getProduct()->getProductNumber(), 0, 19),
'price' => (string) ($orderLine->getProduct()->getPrice()->first()->getNet()
* $order->getCurrencyFactor()), //gets original price, calculates factor
'quantity' => (string) $orderLine->getQuantity()
];
}
$shipping = $this->transformShipping($order);
if ($shipping) {
$lines = array_merge($lines, $shipping);
}
return $lines;
}`
I also tried $orderLine->getProduct()->getTags()->getName() it also return "Call to a member function getTags() on null"
The problem is wherever the $order is fetched from the DB the orderLineItem.product.tag association is not included in the criteria.
For performance reasons shopware does not lazily load all association when you access them on entities, but you have to exactly define which associations should be included when you fetch the entities from the database.
For the full explanation take a look at the docs.

PayPal Api Patch on Itemlist doesn't work

I want to add an item to my transaction.
$json = '
[
{
"name": "Voucher",
"description":"Voucher",
"price":"50.00",
"currency":"EUR",
"quantity":"1"
}
]';
$patchAddItem = new \PayPal\Api\Patch();
$patchAddItem->setOp('add')
->setPath('/transactions/0/item_list/items')
->setValue(json_decode($json));
$patchReplace = new \PayPal\Api\Patch();
$patchReplace->setOp('replace')
->setPath('/transactions/0/amount')
->setValue(json_decode('{
"total": "159.00",
"currency": "EUR",
}'));
$patchRequest = new \PayPal\Api\PatchRequest();
$patchRequest->setPatches(array($patchAddItem, $patchReplace));
try {
$this->payment->update($patchRequest, $this->apiContext);
} catch (PayPal\Exception\PayPalConnectionExceptio $ex) {
echo '<pre>';print_r(json_decode($ex->getData()));exit;
}
But I get following Error
Eception: Got Http response code 400 when accessing https://api.sandbox.paypal.com/v1/payments/payment/PAY... in PayPal-PHP-SDK/paypal/rest-api-sdk-php/lib/PayPal/Core/PayPalHttpConnection.php on line 154
PayPal-PHP-SDK/paypal/rest-api-sdk-php/lib/PayPal/Transport/PayPalRestCall.php on line 73: PayPal\Core\PayPalHttpConnection->execute("[{"op":"add","path":"/transactions/0/item_list/ite"... )
PayPal-PHP-SDK/paypal/rest-api-sdk-php/lib/PayPal/Common/PayPalResourceModel.php on line 102: PayPal\Transport\PayPalRestCall->execute(array[1],"/v1/payments/payment/PAY-1S151200BX2478240LEAG3CI","PATCH","[{"op":"add","path":"/transactions/0/item_list/ite"... ,null)
PayPal-PHP-SDK/paypal/rest-api-sdk-php/lib/PayPal/Api/Payment.php on line 615: PayPal\Common\PayPalResourceModel::executeCall("/v1/payments/payment/PAY-1S151200BX2478240LEAG3CI","PATCH","[{"op":"add","path":"/transactions/0/item_list/ite"... ,null,object,null)
At this moment I didn't execute the payment object. Do I have to edit the total attribut from amount too? Well, I tried this too, with same issue...
Even if you are sending only one item to PayPal you still have to set them as an item list with setItemList().
That array should be visible if you json_decode in your payment array:
[item_list] => Array
(
[items] => Array
(
[0] => Array
(
[name] => Ground Coffee 40 oz
[sku] => 123123
[price] => 52.80
[currency] => USD
[quantity] => 1
)
)
I had not run a patch for an item yet. I attempted to send an 'add' similar to your code and tried changing the path to '/transactions/0/item_list/items/1' using the next number in the items array. But could not get an add to work.
The only way I could modify the item_list was to do a complete 'replace' of the item_list, so in a running shopping cart would have to include all the items being purchased, not just the new item.
To do this I prefer to use the functions from the PayPal sdk vs building the json arrays. Their examples of how to create and execute a payment are fairly good and use the SDK functions. http://paypal.github.io/PayPal-PHP-SDK/sample/
However the example on updating a payments builds the json arrays outright.
Below is a testing function to modify the item_list using the Paypay PHP SDK Class Functions. I hard coded the Subtotal and Total to match the values coming form the shopping cart plus the increase from the new item. The item_list is also hard coded using PP's example data. Otherwise item's arrays would be built off of a user's shopping cart items. The type is set to 'replace'.
So, yes. Subtotals and Totals need to be updated to match as well, else the PP call will fail.
function updatePayPalPayment ($type, $createdPayment, $total, $subtotal, $shipping, $currency) {
$subtotal = '54.80';
$total = '71.73';
$details = new Details();
$details->setShipping($shipping)
->setSubtotal($subtotal);
$amount = new Amount();
$amount->setCurrency($currency)
->setTotal($total)
->setDetails($details);
$item1 = new Item();
$item1->setName('Ground Coffee 40 oz')
->setCurrency('USD')
->setQuantity(1)
->setSku("123123") // Similar to `item_number` in Classic API
->setPrice(52.80);
$item2 = new Item();
$item2->setName('Granola bars')
->setCurrency('USD')
->setQuantity(1)
->setSku("321321") // Similar to `item_number` in Classic API
->setPrice(2.0);
$itemList = new ItemList();
$itemList->setItems(array($item1, $item2));
$patchItem = new Patch();
$patchItem->setOp($type)
->setPath('/transactions/0/item_list')
->setValue($itemList);
$patchAmount = new Patch();
$patchAmount->setOp($type)
->setPath('/transactions/0/amount')
->setValue($amount);
$patchRequest = new PatchRequest();
$patchRequest->setPatches(array($patchAmount, $patchItem));
$update = $createdPayment->update($patchRequest, getApiContext());
return $update;
}
I also have found it very helpful to set the apiContext for logging to DEBUG and output to a file in development for much better error messages.
'log.LogEnabled' => true,
'log.FileName' => '_PayPal.log',
'log.LogLevel' => 'DEBUG',
Hope that helps.

How to put contrasting information into a CGridView column based on a condition?

I'm looking into showing/hiding specific column data on a CGridView widget for the Wii Framework.
I have a CButtonColumn which contains 3 buttons. However, on certain conditions, I want to display something different for a particular row.
I have 3 different conditions which determin what gets displayed for particular row.
The following illustrates what I want to do:
| 1 | Title A | [hide][view][update] <-- if (condition == 'a')
| 2 | Title B | [hide][view][update] <-- if (condition == 'a')
| 3 | Title C | display text or link or button <-- if (condition == 'b')
| 4 | Title D | display alternative buttons <-- if (condition == 'c')
What is my best approach to take here?
I can't use 'visible'=> $model->processingStatus != "processed" on the column because this will remove the whole column. I need to target each row insatead.
Should I use the 'visible' parameter on each individual button? I have tried this using the commented out code below but it breaks the page.
FYI: I have successfully tried the 'visible' parameter on the CButtonColumn itself, but its not what I need. Plus not sure which row's status it is reading.
Or should I add a function to the controller? Have it do the if/else statements and return back what is to be displayed. How would this work?
Here is my code:
<?php $this->widget('zii.widgets.grid.CGridView', array(
'id'=>'my-grid',
'dataProvider'=>$model->search(),
'filter'=>$model,
'columns'=>array(
array(
'name'=>'myid',
'header'=>'ID',
),
'Title',
array(
'class'=>'CButtonColumn',
'visible'=> $model->status != "done",
'template'=>'{hide}{view}{update}',
'buttons'=>array(
'hide'=>array(
'label'=>'Hide', //Text label of the button.
'imageUrl'=>Yii::app()->request->baseUrl . '/img/icons/bulb-off.png' //Image URL of the button.
//'click'=>'function(){alert("Toggle Hide!");}', //A JS function to be invoked when the button is clicked.
//'options'=>array(), //HTML options for the button tag.
//'url'=>'javascript:void(0)', //A PHP expression for generating the URL of the button.
//'visible'=> $model->status == "done", //A PHP expression for determining whether the button is visible.
),
'view'=>array(
//Text label of the button.
'label'=>'View',
//Image URL of the button.
'imageUrl'=>Yii::app()->request->baseUrl . '/img/icons/view-record.png'
),
'update'=>array(
'label'=>'Update/Edit',
'imageUrl'=>Yii::app()->request->baseUrl . '/img/icons/edit-pencil.png',
'url'=>'Yii::app()->createUrl("metadataandchapters/create?bookid=" . $data->bookid)',
)
)
)
)
)); ?>
Hope I am making good enough sense here!
You should use visible button option, but it should be a PHP expression string, e.g. :
'visible'=> '$data->status == "done"',
http://www.yiiframework.com/doc/api/1.1/CButtonColumn#buttons-detail
Extend CButtonColumn with your own class, then you should be able to change this function to whatever you need to render or hide buttons or do any changes you want.
/**
* Renders a link button.
* #param string $id the ID of the button
* #param array $button the button configuration which may contain 'label', 'url', 'data-icon', 'imageUrl' and 'options' elements.
* #param integer $row the row number (zero-based)
* #param mixed $data the data object associated with the row
*/
protected function renderButton($id, $button, $row, $data)
More details about the function http://www.yiiframework.com/doc/api/1.1/CButtonColumn#renderButton-detail

How to use Yii CArrayDataProvider

I am new to php and Yii and need some help regarding showing array in the webpage.
In the controller I open my e-mail inbox and iterate through the e-mails in inbox and build array with each e-mail address as key having values
if (array_key_exists($fromemail,$senders))
{ $senders[$fromemail]['rcount']++; }
else {
$senders[$fromemail]['e-mail'] = $fromemail;
$senders[$fromemail]['Name'] = $fromname;
$senders[$fromemail]['rcount'] = 1;
}
$model->top_senders = $senders;
$this->render('Step2',array('model'=>$model,));
Then in the view file of Step2 I want to show the data in CGridview
if (isset($model->top_senders))
{
$gridDataProvider = new CArrayDataProvider($model->top_senders);
$gridDataProvider->setData($model->top_senders);
$gridColumns = array(
array('name'=>'e-mail', 'header'=>'E-mail','value' =>'$data->e-mail'),
array('name'=>'rcount', 'header'=>'# of mails','value'=>'$data->rcount'),);
$this->widget('bootstrap.widgets.TbGridView',array('dataProvider' => $gridDataProvider,'template' => "{items}",'columns'=>$gridColumns));
}
But I will get error during rendering of the table: PHP notice Undefined offset: 0
/**
125 * Renders a data cell.
126 * #param integer $row the row number (zero-based)
127 */
128 public function renderDataCell($row)
129 {
130 $data=$this->grid->dataProvider->data[$row];
What I am doing wrong? Can anyone help me?
You should't add data to provider as follows:
$gridDataProvider->setData($model->top_senders);
It added during initialization. You must be sure that the array has a key id, otherwise you need to specify it manually (it must be unique) as follows:
$gridDataProvider = new CArrayDataProvider($model->top_senders, array(
'id'=>'Name',
));
You will also need to make sure that the array $model->top_senders has the following structure:
array(
'0'=>array(...user data here),
'1'=>array(...user data here),
...
);
If you var_dump($gridDataProvider->data) you'd notice there's no value for the 0th index in the array. This happens when you run some filter function on the array. Assuming there are 5 values in the filtered array, the filtered array would look something like this when var_dump'd.
array(5) {
[1] => Object (Mailer) {…},
[2] => Object (Mailer) {…},
[4] => Object (Mailer) {…},
[8] => Object (Mailer) {…},
[9] => Object (Mailer) {…},
}
A filter operation on an array can leave the array looking like the above.
When the CGridView is trying to feed the view with data, it does it sequentially—this, I find, is a shortcoming in Yii and should be raised as an issue.
In order to fix this, use PHP's array_values() like so…
$properly_indexed_array = array_values($filtered_array);
This will copy the values of the filtered array into a new array. This is not the optimal solution in terms of memory. So far, I do not see any means in PHP other than this though.
You may then go ahead and set this as the data for your data provider like so…
$gridDataProvider->setData($properly_indexed_array);

using listdata only and get from another model in Yii

can i just have listdata by itself? The list doesn't list anything, all I keep getting is "Array" as the return.
I have:
$awards= $model->findAll('uid='.$uid);
return CHtml::listData($awards, 'award_id', '$data->award->name');
try this code:
$awards= $model->findAll(array('condition'=>'uid ='.$uid)); // get records from table
return CHtml::listData($awards, 'award_id', 'award_name'); // third parameter should the array value. Most of the case we use to display in combo box option text.
If you are getting from another table, then declare a variable in your award model.
public $awrd_name;
Then you have to get records using relation in criteria.
Output will be :
array("1" => "award1", "2" => "award2", "3" => "award3");
refer this link : http://www.yiiframework.com/forum/index.php/topic/29837-show-two-table-fields-in-dropdownlist/