Yii2: Override global pdf orientation settings for mpdf in controller action - yii2

I am using the mpdf extension to generate pdf files. I have set global settings for the mpdf in the config file, hence I am able to call the function every time I want to generate a pdf from my controller action. However, I am finding it hard to change the orientation for the pdf with data that requires landscape orientation since the default orientation set in the global settings is portrait. Here are the codes:
main.pdf code for the global setting
'pdf' => [
'class' => Pdf::classname(),
'mode' => Pdf::MODE_UTF8, // leaner size using standard fonts
'format' => Pdf::FORMAT_A4,
'orientation' => Pdf::ORIENT_PORTRAIT,
'destination' => Pdf::DEST_BROWSER,
'cssFile' => '#vendor/kartik-v/yii2-mpdf/assets/kv-mpdf-bootstrap.min.css',
// any css to be embedded if required
'cssInline' => '.kv-heading-1{font-size:18px}',
'options' => [
'shrink_tables_to_fit' => 0
],
// refer settings section for all configuration options
],
Controller Action calling the global settings:
public function actionReservationsList()
{
$searchModel = new ReservationsSearch();
$dataProvider = $searchModel->search(Yii::$app->session->get('repquery'));
$dataProvider->pagination = false;
$pdf = Yii::$app->pdf;
$pdf->content = $this->renderPartial('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
$pdf->methods = [
'SetHeader' => [Yii::$app->user->identity->company->name.'||Date: ' . date("r")],
'SetFooter' => ['User: '.Yii::$app->user->identity->username.'||Page {PAGENO}'],
];
return $pdf->render();
}
So I need help in overriding the 'orientation' => Pdf::ORIENT_PORTRAIT, setting that is in the global settings main.php file from the controller action.

This work for me:
<?php
namespace backend\controllers;
use Yii;
use yii\web\Controller;
use kartik\mpdf\Pdf;
class InformesController extends Controller
{
...
public function actionImprimirInforme($id,$key)
{
$html = $this->renderPartial('informe-pdf', [
'title' => 'Informe'
]);
$pdf = new Pdf([
'format' => Pdf::FORMAT_A4,
'orientation' => Pdf::ORIENT_LANDSCAPE,
'destination' => Pdf::DEST_BROWSER,
'options' => [
'showImageErrors' => true,
]
]);
$pdf->configure([
'title' => 'Informe ',
]);
$pdf->content = $html;
$pdf->orientation = Pdf::ORIENT_LANDSCAPE;
$pdf->execute('SetFooter', ['{PAGENO} de {nbpg}']);
$pdf->filename = "Informe.pdf";
return $pdf->render();
}
}
My first answer was wrong, i have been setting the property 'orientation' into pdf component, so the dynamically assign does not work properly.
Here you have the documentation example

You need to add the contents via addPage. So if you build a array of pages, with the contents etc - you should be able to specify the orientation per page.
<?php
$mpdf = new mPDF('', 'Legal');
$mpdf->WriteHTML('
Hello World
');
$mpdf->AddPage('L'); // Adds a new page in Landscape orientation
$mpdf->WriteHTML('
Hello World
');
$mpdf->Output();
?>

Try add this line this :
$pdf = Yii::$app->pdf;
$pdf->orientation = Pdf::ORIENT_LANDSCAPE;

Related

kartik-v/yii2 select2-widget not working with render partial

I am trying to add dynamic drop downs, which will added from javascript on clicking add new button.
view file
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
use kartik\select2\Select2;
use kartik\select2\Select2Asset;
use yii\helpers\ArrayHelper;
Select2Asset::register($this);
?>
<div class='row'>
<div class='form-group'>
<?=
Select2::widget([
'name' => 'coupons',
'value' => $model->coupon_id,
'data' => ArrayHelper::map($coupons, 'id', 'name'),
'options' => ['placeholder' => 'Select a state ...'],
'pluginOptions' => [
'allowClear' => true
],
]);
?>
</div>
</div>
controller
public function actionNewCoupon()
{
$coupon = new DealCoupon();
$deal = Yii::$app->request->get('deal');
$order = Yii::$app->request->get('order');
$coupon->deal_id = $deal;
$coupon->order = $order;
$coupon->save();
$coupons = Coupon::find('id','name')->all();
return $this->renderPartial('_form', [
'model' => $coupon,
'coupons' => $coupons
],true, true);
}
js file
.get(BASE_URL + '/coupon/new-coupon', { deal: dealId, order: order }, function(data) {
var dealWidget = newStep.find('.coupon-panel');
$(newStep).find('.coupon-panel').html(data);
});
What I am getting
Any help to resolve this issue is appreciable, as I am totaly lost.
Thanks in advance.
yii\web\Controller::renderPartial() doesn't include registered JS or CSS files. Try using yii\web\Controller::renderAjax() instead. It's similar but it injects registered JS/CSS files into rendered html code.

Yii2 save Log into Database

i have some problem with Log with Yii2.
I set Log Targets in this way:
'log' => [
'traceLevel' => YII_DEBUG ? 3 : 0,
'flushInterval' => 1,//test
'targets' => [
[
'class' => 'common\components\SaDbTarget',
'levels' => ['error', 'warning','trace','info'],
'exportInterval' => 1,//test
//'categories' => ['application'],
/*'except' => [
'yii\db\*',
],*/
],
],
],
I create my SaDbTarget extending DbTarget Class, and this is working fine because i found in my table some log.
After that, in a controller i tried to set a log like this way
public function actionIndex(){
$searchModel = new CategorySearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
Yii::trace('trace log', __METHOD__);
Yii::warning('warning log');
// here is the rest of the code
}
I can see this 2 logs into the debug toolbar, but not in my db table.
According to the Docs
To make each log message appear immediately in the log targets, you
should set both flushInterval and exportInterval to be 1
I tried to set this values but still doesn't work.
I don't know what am I doing wrong.
UPDATE
This is my SaDbTarget
namespace common\components;
use Yii;
use yii\log\DbTarget;
use yii\log\Logger;
class SaDbTarget extends DbTarget{
//set custom table db for saving log
public $logTable = 'authlog';
//overwrite export();
public function export(){
$tableName = $this->db->quoteTableName($this->logTable);
$sql = "INSERT INTO $tableName ([[authlog_login]], [[authlog_ip]], [[authlog_area]], [[authlog_act]], [[authlog_time]], [[authlog_data]])
VALUES (:login, :ip, :area, :act, :time, :data )";
$command = $this->db->createCommand($sql);
//Get username
$user=Yii::$app->user->getId();
//Get user ip address
$ip = Yii::$app->request->getUserIP();
//Get area/controller
$controller=Yii::$app->controller->uniqueId;
//Get action
$event= Yii::$app->controller->module->requestedAction->id;
//Set timezone
$time = Yii::$app->formatter->asDate('now', 'php:Y-m-d H:i:s');
//Set Data
$data = $this->messages[0];
$command->bindValues([
':login' => $user,
':ip' => $ip,
':area' => $controller,
':act' => $event,
':time' => $time,
':data' => $data,
])->execute();
}
Could you check wether the 'log' component is set on bootstrap?
I think this could be the issue that the dispatcher is not setup and does not pickup the target.
So the bootstrap should look like
[
'bootstrap' => ['log'],
'components' => [
'log' => [
...
],
....
]
Another way would be to check in the debugger if the dispatcher on the logger is configured correctly.

Undefined Variable model in kartik mpdf - yii2

I'm trying to use kartik mpdf to print data to a pdf file. I'm facing kind of same problem as - yii2 basic printing a page in pdf.
I've tried the solution given there but still getting the error.
View file(the code for the button) -
<?= Html::a('<i class="fa glyphicon glyphicon-print"></i> Print Salary Statement', ['/salary/salary/printsalarystatement'], [
'class'=>'btn btn-primary',
'target'=>'_blank',
'data-toggle'=>'tooltip',
'title'=>'Will open the generated PDF file in a new window'
]);?>
Controller
public function actionPrintsalarystatement() {
$pdf = new Pdf([
'content'=>$this->renderPartial('_printSalarystatement'), [
'model'=> $model,
'mode'=> Pdf::MODE_CORE,
'format'=> Pdf::FORMAT_A4,
'orientation'=>Pdf::ORIENT_POTRAIT,
'destination'=> Pdf::DEST_BROWSER,
'cssFile' => '#vendor/kartik-v/yii2-mpdf/assets/kv-mpdf-bootstrap.min.css',
'cssInline'=> '.kv-heading-1{font-size:18px}',
'options'=> ['title'=> 'Salary Statement'],
'methods'=> [
'setHeader'=>['Generated on: '.date("r")],
'setFooter'=>['|page {PAGENO}|'],
]
],
]);
return $pdf->render();
}
Present View.php -
<?= Html::a('<i class="fa glyphicon glyphicon-print"></i> Print Salary Statement', ['/salary/salary/printsalarystatement?id=s_id'], [
'class'=>'btn btn-primary',
'target'=>'_blank',
'data-toggle'=>'tooltip',
'title'=>'Will open the generated PDF file in a new window'
]);?>
Present Controller
public function actionPrintsalarystatement($id) {
//$model = Salary::find()->where(['s_id' => $id]);
$model = $this->findModel($id);
$searchModel = new SalarySearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
$data = Salary::findOne($id);
$content = $this->renderPartial('_printSalarystatement', ['model' => $model,'dataProvider' => $dataProvider,'searchModel' => $searchModel,'data'=> $data]);
$pdf = new Pdf([
'mode'=> Pdf::MODE_CORE,
'format'=> Pdf::FORMAT_A4,
'destination'=> Pdf::DEST_BROWSER,
'content' => $content,
]);
return $pdf->render();
}
Where are you generating the $model? You need to pass or call that into the function somehow.
public function actionPrintsalarystatement() {
// you don't have the model for passing to the pdf object
// eg:
$model = YourModel::find()->where(['your_column' => 'your_value']);
$pdf = new Pdf([
'content'=>$this->renderPartial('_printSalarystatement'), [
'model'=> $model, // this $model is missing if you don assign a proper result to the this var like suggested above
'mode'=> Pdf::MODE_CORE,
Based on your comment :
you don'have a proper $id so you can't retrieve nothings
you have $model = Salary::find()->where(['s_id' => '$id']); this is wrong you must remove the quotes around $id this way $model = Salary::find()->where(['s_id' => $id]);
If you have $id in the page where you call the actionPrintsalarystatement tye you could pass to the action
eg:
/salary/salary/printsalarystatement?id=your_id
and
public function actionPrintsalarystatement($id) {

yii2 createUrl is duplicating the route

i'm building multi lingual site with English and Arabic
url for English
url for Arabic
I want to switch language from any page exactly to the same page of the other language
so i made code like below.
$route = Yii::$app->controller->route;
$params = $_GET;
array_unshift($params, '/'.$route);
<?php if(Yii::$app->language == 'ar'){ ?>
<?= Html::a('English', [Yii::$app->urlManager->createUrl($params), 'language'=>'en']); ?>
<?php }else{?>
<?= Html::a('Arabic', [Yii::$app->urlManager->createUrl($params), 'language'=>'ar']); } ?>
and my url generating like below
/multi/backend/web/en/multi/backend/web/ar/site/index?val=hii&net=good
English
don't know what is wrong?
I'm using this for language management.
please check my main.php under backend/config
<?php
$params = array_merge(
require(__DIR__ . '/../../common/config/params.php'),
require(__DIR__ . '/../../common/config/params-local.php'),
require(__DIR__ . '/params.php'),
require(__DIR__ . '/params-local.php')
);
return [
'id' => 'app-backend',
'basePath' => dirname(__DIR__),
'controllerNamespace' => 'backend\controllers',
'language' => 'en',
'sourceLanguage' => 'en_UK',
'bootstrap' => ['log'],
'modules' => [],
'components' => [
'user' => [
'identityClass' => 'common\models\User',
'enableAutoLogin' => true,
],
'log' => [
'traceLevel' => YII_DEBUG ? 3 : 0,
'targets' => [
[
'class' => 'yii\log\FileTarget',
'levels' => ['error', 'warning'],
],
],
],
'errorHandler' => [
'errorAction' => 'site/error',
],
'i18n' => [
'translations' => [
'app' => [
'class' => 'yii\i18n\DbMessageSource',
'sourceLanguage' => 'en_UK',
],
],
],
'urlManager' => [
'class' => 'codemix\localeurls\UrlManager',
'languages' => ['en', 'ar'],
'enableDefaultLanguageUrlCode' => false,
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => [
],
],
],
'params' => $params,
];
If you are doing it as in your example, you have to think about it on every link you create. This can be automated easily.
URL-Rule
You can solve this with an url-rule in your config file like so:
'<language:[\w]{2,2}>/<controller:\w+>/<action:\w+>'=>'<controller>/<action>',
This will assert the proper routing to your controller and provide you the desired language in the language-variable.
Custom UrlManager
You can extend the UrlManager-class and make sure the current language is always appended to the params:
class MyUrlManager extends \yii\web\UrlManager
{
// ...
/**
* #inheritdoc
*/
public function createUrl($params)
{
if (!isset($params['language'])) {
$params['language'] = Yii::$app->language;
}
return parent::createUrl($params);
}
// ...
}
This will automate the process of adding the language to the links you create.
Custom Application
Now you should also override the Application-class and always set the language to the one provided or choose a default (in this case en):
class MyApplication extends \yii\web\Application
{
// ...
/**
* #inheritdoc
*/
public function init()
{
parent::init();
$lang = Yii::$app->request->get('language', 'en');
Yii::$app->language = $lang;
}
// ...
}
Now your language will always be set to the default value or the one provided viathe query param as specified above.
Final thoughts
This should give you the basic idea on how to solve your problem. Adjust as necessary...especially the last part with the Application-class and how you retrieve the value of the language-var. I hope it helped!
Possible problems with your code and the extension provided
If you read the docs of the extension the urls are generated differently. It tells you to create the urls as follows:
Url::to(['demo/action', 'language'=>'ar'])
You are createing a simple link-tag and overwrite the $params. Try this instead:
echo Html::a('Arabic', Url::to(['site/index', 'language'=>'ar']));
For redirection to the current page just replace the first part with the current route.
after lots of trying ..i found a solution.. now its worked for me.
$route = Yii::$app->controller->route;
if(Yii::$app->language == 'ar'){
$_GET['language'] = 'en';
}else{
$_GET['language'] = 'ar';
}
$params = $_GET;
array_unshift($params, '/'.$route);
<?php if(Yii::$app->language == 'ar'){ ?>
<?= Html::a('English', Yii::$app->urlManager->createUrl($params)); ?>
<?php }else{?>
<?= Html::a('Arabic', Yii::$app->urlManager->createUrl($params)); } ?>
its working for the url like
http://localhost/multi/backend/web/site/index?page=2&per-page=6
and
http://localhost/multi/backend/web/site/index

Dynamic Multilevel Drop-down menu in Yii2

I want to create a dynamic menu with my table (db). I have followed some instructions which are given below:
Table : "menupanal"
Step 01: I just create a super controller in app\components\Controller.php
Here is the code:
namespace app\components;
use app\models\MenuPanal;
class Controller extends \yii\web\Controller
{
public $menuItems = [];
public function init(){
$items = MenuPanal::find()
->where(['c_type' => 'MENU'])
->orderBy('id')
->all();
$menuItems = [];
foreach ($items as $key => $value) {
$this->menuItems[] =
['label' => $value['c_name'],
'items'=> [
['label' => $value['c_redirect'], 'url' => ['#']],
],
];
}
parent::init();
}
Step 02: Changed n main layout page:
echo Nav::widget([
'options' => ['class' => 'navbar-nav navbar-right'],
'items' => Yii::$app->controller->menuItems,
]);
It is working in only one level. My question::
Question : how can I add multilevel menu using Super controller ?
I am new in Yii2. Helps are highly appreciated.
Create New MenuHelper in Component folder. There is no default component folder. Please create by yourself.
<?php
namespace app\components;
use app\models\MenuPanel;
use app\models\Zuser;
use app\models\Vwrole;
use app\assets\AppAsset;
class MenuHelper
{
public static function getMenu()
{
$role_id = 1;
$result = static::getMenuRecrusive($role_id);
return $result;
}
private static function getMenuRecrusive($parent)
{
$items = MenuPanel::find()
->where(['c_parentid' => $parent])
->orderBy('c_sortord')
->asArray()
->all();
$result = [];
foreach ($items as $item) {
$result[] = [
'label' => $item['c_name'],
'url' => ['#'],
'items' => static::getMenuRecrusive($item['id']),
'<li class="divider"></li>',
];
}
return $result;
}
}
in Main Layout Page put the following code
echo Nav::widget([
'options' => ['class' => 'navbar-nav navbar-right'],
'items' => app\components\MenuHelper::getMenu(),
Enjoy Coding!!
You may use nested sets. Look at this extension for Yii: http://www.yiiframework.com/extension/nestedsetbehavior/ and its documentation. All you need to do is component with dynamic creation of menu items array for nested sets.
I found that there is a Yii2 extension version: http://www.yiiframework.com/extension/yii2-nestedsetbehavior/
Good luck
You may use this extension for multilevel dropdownMulti level Dropdown