Yii2 - Class 'mPDF' not found - yii2

As I tried to Export to PDF from my Application, but I got this error:
I don't really know what is causing the error. I have tries several means to no avail. This is the component:
<?php
namespace backend\components;
use Yii;
use yii\base\Component;
use yii\base\InvalidConfigException;
use common\models\Organization;
use yii\helpers\Html;
use yii\web\NotFoundHttpException;
use mPDF;
class ExportToPdf extends Component
{
public function exportData($title='',$filename='Jkkesrms Pdf',$html=NULL)
{
$mpdf = new mPDF('utf-8', 'A4',0,'',15,15,25,16,4,9,'P');
$mpdf->autoScriptToLang = true;
$mpdf->autoLangToFont = true;
$org = Organization::find()->asArray()->one();
$src = Yii::$app->urlManager->createAbsoluteUrl('site/loadimage');
$org_image=Html::img($src,['alt'=>'No Image','width'=>90, 'height'=>70]);
$org_name=$org['org_name'];
$org_add=$org['org_address_line1']."<br/>".$org['org_address_line2'];
$mpdf->SetHTMLHeader('<table style="border-bottom:1.6px solid #999998;border-top:hidden;border-left:hidden;border-right:hidden;width:100%;"><tr style="border:hidden"><td vertical-align="center" style="width:35px;border:hidden" align="left">'.$org_image.'</td><td style="border:hidden;text-align:left;color:#555555;"><b style="font-size:22px;">'.$org_name.'</b><br/><span style="font-size:10.2px">'.$org_add.'</td></tr></table>');
$stylesheet = file_get_contents('css/pdf.css'); // external css
$mpdf->WriteHTML($stylesheet,0);
$mpdf->WriteHTML('<watermarkimage src='.$src.' alpha="0.33" size="50,30"/>');
$mpdf->showWatermarkImage = true;
$arr = [
'odd' => [
'L' => [
'content' => $title,
'font-size' => 10,
'font-style' => 'B',
'font-family' => 'serif',
'color'=>'#27292b'
],
'C' => [
'content' => 'Page - {PAGENO}/{nbpg}',
'font-size' => 10,
'font-style' => 'B',
'font-family' => 'serif',
'color'=>'#27292b'
],
'R' => [
'content' => 'Printed # {DATE j-m-Y}',
'font-size' => 10,
'font-style' => 'B',
'font-family' => 'serif',
'color'=>'#27292b'
],
'line' => 1,
],
'even' => []
];
$mpdf->SetFooter($arr);
$mpdf->WriteHTML('<sethtmlpageheader name="main" page="ALL" value="on" show-this-page="1">');
$mpdf->WriteHTML($html);
$mpdf->Output($filename.'.pdf',"I");
}
}
?>
I have tried tried several means but the error persists. Please how do I resolve this error?

You need to include the full namespace with the use statement. Looking at the code it looks like that you are using this library. If that is correct then include it like
use Mpdf\Mpdf;
and then use it like below
$mpdf = new Mpdf('utf-8', 'A4',0,'',15,15,25,16,4,9,'P');

Related

Generate PDF from HTML using MPdf with Japanese characters and NotoSansJP font [duplicate]

I'm using version 7.x of mPDF and tried to follow this documentation:
https://mpdf.github.io/fonts-languages/fonts-in-mpdf-7-x.html
I just can't get it to work. No errors, but the font is still the default mPDF font.
I also tried to do it another way with the answers from these:
How to generate PDF using mPDF and add custom Google font to it?
php mPDF, impossible to set font-family and font-size
adding font to mPDF
But I guess they donĀ“t work, as they might only be for older version than 7.X ...So here's is my latest attempt trying to use the information for the 7.x documentation.
Heres my php file:
require_once __DIR__ . '/vendor/autoload.php';
$defaultConfig = (new Mpdf\Config\ConfigVariables())->getDefaults();
$fontDirs = $defaultConfig['fontDir'];
$defaultFontConfig = (new Mpdf\Config\FontVariables())->getDefaults();
$fontData = $defaultFontConfig['fontdata'];
$mpdf = new \Mpdf\Mpdf(['tempDir' => __DIR__ . '/upload'],
['fontdata' => $fontData + [
'BentonSans' => [
'R' => 'BentonSans.ttf',
'I' => 'BentonSans-Bold.ttf',
]
],
'default_font' => 'BentonSans'
]);
$url = rawurldecode($_REQUEST['url']);
$html = file_get_contents($url);
$stylesheet = file_get_contents('style.css');
$mpdf->setBasePath($url);
$mpdf->AddFontDirectory('fonts');
$mpdf->WriteHTML($stylesheet,1);
$mpdf->WriteHTML($html);
$mpdf->Output('filename.pdf','I');
And my css:
body {
font-family: 'BentonSans';
font-size: 14px;
font-style: normal;
font-variant: normal;
font-weight: normal;
line-height: 20px;
}
My custom fonts are stored in "fonts" which is in the same folder as the php file.
Here's the real working solution as instructed in the docs:
"Define the font details in fontdata configuration variable - font name must be lowercase".
So BentonSans must be changed to bentonsans.
Code would be:
$defaultConfig = (new \Mpdf\Config\ConfigVariables())->getDefaults();
$fontDirs = $defaultConfig['fontDir'];
$defaultFontConfig = (new \Mpdf\Config\FontVariables())->getDefaults();
$fontData = $defaultFontConfig['fontdata'];
$mpdf = new \Mpdf\Mpdf(
[
'tempDir' => __DIR__ . '/upload',
'fontDir' => array_merge($fontDirs, [
__DIR__ . '/fonts'
]),
'fontdata' => $fontData + [
'bentonsans' => [
'R' => 'BentonSans.ttf',
'I' => 'BentonSans-Bold.ttf',
],
],
'default_font' => 'bentonsans'
]
);
The issue is in Mpdf version 7 the configuration is passed as a single parameter (an array), while you were passing in multiple parameters to the constructor.
This is a valid configuration:
$mpdf = new \Mpdf\Mpdf(
[
'tempDir' => __DIR__ . '/upload',
'fontdata' => $fontData + [
'bentonsans' => [
'R' => 'BentonSans.ttf',
'I' => 'BentonSans-Bold.ttf',
],
],
'default_font' => 'BentonSans',
]
);
Got it to work. Not sure what did the trick, but here's the working code:
<?php
require_once __DIR__ . '/vendor/autoload.php';
if (!defined('_MPDF_TTFONTPATH')) {
// an absolute path is preferred, trailing slash required:
define('_MPDF_TTFONTPATH', realpath('fonts/'));
// example using Laravel's resource_path function:
// define('_MPDF_TTFONTPATH', resource_path('fonts/'));
}
function add_custom_fonts_to_mpdf($mpdf, $fonts_list) {
$fontdata = [
'bentonsans' => [
'R' => 'BentonSans.ttf',
'B' => 'BentonSans-Bold.ttf',
],
];
foreach ($fontdata as $f => $fs) {
// add to fontdata array
$mpdf->fontdata[$f] = $fs;
// add to available fonts array
foreach (['R', 'B', 'I', 'BI'] as $style) {
if (isset($fs[$style]) && $fs[$style]) {
// warning: no suffix for regular style! hours wasted: 2
$mpdf->available_unifonts[] = $f . trim($style, 'R');
}
}
}
$mpdf->default_available_fonts = $mpdf->available_unifonts;
}
$mpdf = new \Mpdf\Mpdf(['tempDir' => __DIR__ . '/upload']);
add_custom_fonts_to_mpdf($mpdf);
$url = rawurldecode($_REQUEST['url']);
$html = file_get_contents($url);
$stylesheet = file_get_contents('style.css');
$mpdf->setBasePath($url);
$mpdf->AddFontDirectory('fonts');
$mpdf->WriteHTML($stylesheet,1);
$mpdf->WriteHTML($html);
$mpdf->Output('filename.pdf','I');
?>

Cannot generate HalResource for object of type ArrayObject

I've some problems to return a paginator object as HAL json collection. I'm using the latest versions of zend-expressive and zend-expressive-hal.
This is the setting from my ConfigProvider:
public function __invoke() : array
{
return [
'dependencies' => $this->getDependencies(),
MetadataMap::class => $this->getHalConfig(),
];
}
public function getHalConfig() : array
{
return [
[
'__class__' => RouteBasedCollectionMetadata::class,
'collection_class' => RoleCollection::class,
'collection_relation' => 'user_roles',
'route' => 'api.user.roles',
],
];
}
And these are my handler methods:
public function get(ServerRequestInterface $request) : ResponseInterface
{
// read some records from the database
$select = new Select();
$select->from(['r' => 'user_roles']);
$select->columns(['id', 'name']);
$paginator = new RoleCollection(new DbSelect($select, $this->dbAdapter));
$paginator->setItemCountPerPage(25);
$paginator->setCurrentPageNumber(1);
return $this->createResponse($request, $paginator);
}
private function createResponse(ServerRequestInterface $request, $instance) : ResponseInterface
{
return $this->responseFactory->createResponse(
$request,
$this->resourceGenerator->fromObject($instance, $request)
);
}
The RoleCollection class is only an inheritance of the Paginator:
class RoleCollection extends Paginator
{
}
The error message which I get is:
Cannot generate Zend\Expressive\Hal\HalResource for object of type ArrayObject; not in metadata map
I think you are missing the metadata for the Role object itself.
For example this is something similar for my posts object:
MetadataMap::class => [
[
'__class__' => RouteBasedCollectionMetadata::class,
'collection_class' => Posts::class,
'collection_relation' => 'posts',
'route' => 'api.posts',
],
[
'__class__' => RouteBasedResourceMetadata::class,
'resource_class' => Post::class,
'route' => 'api.posts.view',
'extractor' => ArraySerializable::class,
],
],
You have only described the collection and the resource class is missing for a single role.
I also see the resource generator tries to parse an ArrayObject. This should be wrapped in a Role object, which you can add to the MetadataMap.
Where it goes wrong in your code is this line:
$paginator = new RoleCollection(new DbSelect($select, $this->dbAdapter));
This adds the result of a query into the paginator, but the paginator does not know how to handle it. If I remember correctly, the DbSelect return a ResultSet. I'm guessing this is where the ArrayObject is coming from. What you probably need is to override that ResultSet and make sure it returns an array of Role objects. You might want to look into the dbselect adapter and the hydrating resultset.
Once you have the Role object in the paginator, you can describe it in the metadata.
[
'__class__' => RouteBasedResourceMetadata::class,
'resource_class' => UserRole::class,
'route' => 'api.roles',
'extractor' => ...,
],
I use doctrine myself with hal so zend-db is out of my scope. If you need more help, I suggest the zf forums.

How to update customer in braintree payment method

I have integrated braintree method in yii2 rest api Using this reference.. I want to update the customer but I am getting following error:
Missing argument 2 for Braintree\Customer::update()
Below is my code :
$braintree = Yii::$app->braintree;
$response = $braintree->call('Customer', 'update','15552090',[
'firstName' => 'test-1545',
'lastName' => 'asdf',
'company' => 'New Company',
'email' => 'new.email#example.com',
'phone' => 'new phone',
'fax' => 'new fax',
'website' => 'http://new.example.com'
]);
print_r($response); die;
I am stack here how to pass the arguments?
It's a problem of this particular extension. See this issue on Github.
Issue OP recommends this fix:
public function call($command, $method, $values, $values2 = null)
{
$class = strtr("{class}_{command}", [
'{class}' => $this->_prefix,
'{command}' => $command,
));
if ($values2) {
return call_user_func(array($class, $method), $values, $values2);
else {
return call_user_func(array($class, $method), $values);
}
}
while extension author recommends this:
if (is_array($values)) {
call_user_func_array(...);
} else {
call_user_func(...);
}
Either way you need to override this component with your own and apply a patch.
Note that the amount of code in application is small (64 lines in one file) so you can create your own wrapper or find better one because this issue is still not fixed.
And maybe is better to directly use braintree_php methods which will be more clear than magical call.
Update: To override component, create own class extending from bryglen's, place it for example in common/components folder in case of using advanced app.
namespace common\components;
class Braintree extends \bryglen\braintree\Braintree
{
public function call($command, $method, $values)
{
// Override logic here
}
}
Then replace extension class name with your custom one in config:
'components' => [
'braintree' => [
'class' => 'common\components\Braintree',
'environment' => 'sandbox',
'merchantId' => 'your_merchant_id',
'publicKey' => 'your_public_key',
'privateKey' => 'your_private_key',
],
],

Yii2 karthik editable column first row not working

I used karthik grid view and editable column to edit my grid view data. it not work for the first row of the grid view and work for the other rows when i enter value to the first row it give error like this
SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data
my gridview code is.
<?= GridView::widget([
'dataProvider' => $dataProvider,
'pjax' => true,
'pjaxSettings' => [
'options' => [
'id' => 'grid',
]
],
'export'=>false,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
[
'header'=>'Sub Category',
'value'=>'item.subCategory.name',
],
'item.code',
[
'header'=>'Brand',
'value'=>'item.brand.name',
],
'item.description',
'item.pack_size',
[
'header'=>'Unit',
'value'=>'item.unit',
],
[
'header'=>'Last Price',
'value'=>function($model){
$customerId = $model->customerOrderRequest->customer_id;
$lastPurchasedPrice = Item::getLastPurchasedPrice($customerId,$model->item_id);
return '$ ' . number_format($lastPurchasedPrice, 2);
}
],
[
'class' => 'kartik\grid\EditableColumn',
'attribute'=>'qty',
'editableOptions' =>
[
'formOptions' => ['action' => 'customer-order-request']
],
'header' => 'Qty',
],
[
'header'=>'Estimate',
'value'=>function($model)
{
return '123123.00';
}
],
[
'header'=>'Price (UNIT)',
'format'=>'raw',
'value'=>function($modal){
$salse_rep_id = Yii::$app->user->identity->ref_id;
$exsist_respond = Respond::find()->where(['sales_rep_id'=>$salse_rep_id,'customer_order_request_id'=>$modal->customer_order_request_id])->one();
if(!empty($exsist_respond)){
$exsist_respond_item = RespondItem::find()->where(['item_id'=>$modal->item_id,'respond_id'=>$exsist_respond->id])->one();
if(!empty($exsist_respond_item)){
$price = $exsist_respond_item->price;
} else {
$price = NULL;
}
} else {
$price = NULL;
}
if(!empty($exsist_respond) && $exsist_respond->status !="Pending"){
return $price;
}else{
return "<input type='text' class='respond-item' cor='$modal->customer_order_request_id' value='$price' item_id='$modal->item_id' />";
}
},
'visible'=>(Yii::$app->user->identity->ref_table =="sales_rep")? true:false
],
],
]); ?>
and my controller is
public function actionEditable()
{
if (Yii::$app->request->post('hasEditable'))
{
$customerItemsId = Yii::$app->request->post('editableKey');
print_r($customerItemsId);die();
$model = RequestItem::findOne($customerItemsId);
$out = Json::encode(['output'=>'', 'message'=>'']);
$post = [];
$posted = current($_POST['RequestItem']);
$post['RequestItem'] = $posted;
if ($model->load($post))
{
$model->save();
$output = '';
$out = Json::encode(['output'=>$output, 'message'=>'']);
}
echo $out;
return;
}
}
any one can help me with this problem.
Form tag nested.
a trick: Add a fake form to let browser remove it.
I meet this problem today, cause I put a form in another, they are nested.
So the browser remove the first nested form.
In the official W3C XHTML specification, Section B. "Element Prohibitions", states that:
"form must not contain other form elements."
official website
Following is sample code:
<form id="thisisMainForm">
<form id="dummy"> ->This will get Removed
<gridview id="thisisEditableGridView">
Gridviewcode.....
</gridview>
</form>
</form>

yii2 : make SerialColumn a link

How to make the numbering result of the SerialColumn a link. Normally it generates number starting from 1. I want to make it a link. What property to use?
'columns' => [
// ...
[
'class' => 'yii\grid\SerialColumn',
// you may configure additional properties here
],
]
You can't using the actual SerialColumn class.
That being said it should be fairly easy to do with a regular column. You can define a content callback that will receive all the necessary information to do this on its own:
'columns' => [
// ...
[
'content' => function($model, $key, $index, $column) {
$globalIndex = $index + 1;
$pagination = $column->grid->dataProvider->getPagination();
if ($pagination !== false) {
$globalIndex = $pagination->getOffset() + $index + 1;
return \yii\helpers\Html::a($globalIndex, ['/route/action', 'id' => $globalIndex]);
}
],
]
Note: I haven't tested this so might not fully work out of the box.