Como usar mPDF de kartik para exportar a PDF

Hola a todos
Estoy tratando de exportar a pdf un reporte de mi BD con el widget de Kartik que usa mPDF

Lo primero que hice fue con un contenido de prueba, pero cuando hago clic en el boton me sale una pagina con caracteres axtraños, si actualizo la pagina entonces si me abre el pdf correctamente
Lo que necesito es que se me abra el pdf al dar clic en el boton.

Despues de solucionar esto, lo que necesito imprimir es un listado de facturas que tengo en la BD

Este es el codigo queestoy probando:

    public function actionImprimepdf() {
    // get your HTML raw content without any layouts or scripts
    $content = 'Esto es el PDF';

    $pdf = new Pdf([
        'filename' => 'pdf/reporte.pdf',
        'mode' => Pdf::MODE_BLANK,
        'destination' => Pdf::DEST_DOWNLOAD,
        'content' => $content,

        // format content from your own css file if needed or use the
        // enhanced bootstrap css built by Krajee for mPDF formatting
        '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}',
        // set mPDF properties on the fly
        'options' => ['title' => 'Factura'],
        // call mPDF methods on the fly
        'methods' => [
            'SetHeader'=>['Krajee Report Header'],
            'SetFooter'=>['{PAGENO}'],
        ]
    ]);

    // return the pdf output as per the destination setting
    Yii::$app->response->format = \yii\web\Response::FORMAT_RAW;
    Yii::$app->response->headers->add('Content-Type', 'application/pdf');

    return $pdf->render();
}

Esto es lo que me sale inicialmente

%PDF-1.4 %���� 3 0 obj <> /Contents 4 0 R>> endobj 4 0 obj <> stream x�u�MO!��̯x�z��.��jڮы�$LM�n��֤�a�Īax�y�gp�1�ih-�R�o�zѮ+����b�Q�yo��y�x]B���.�9�5�c]�����T��SN��K��iE5}�;�tOkޗ�[�-�b>�y�^x���(v�2��8 V��a��y���X�/8���K�_}�[�%a>�t;.��( W��B���x�jɀ��iZ���a …

Y vi que debajo me sale este error

    An Error occurred while handling another error:

yii\web\HeadersAlreadySentException: Headers already sent in D:\Programacion\Web\sisleg\vendor\mpdf\mpdf\src\Mpdf.php on line 9446. in D:\Programacion\Web\sisleg\vendor\yiisoft\yii2\web\Response.php:366
Stack trace:
#0 D:\Programacion\Web\sisleg\vendor\yiisoft\yii2\web\Response.php(339): yii\web\Response->sendHeaders()
#1 D:\Programacion\Web\sisleg\vendor\yiisoft\yii2\web\ErrorHandler.php(135): yii\web\Response->send()
#2 D:\Programacion\Web\sisleg\vendor\yiisoft\yii2\base\ErrorHandler.php(111): yii\web\ErrorHandler->renderException(Object(yii\web\HeadersAlreadySentException))
#3 [internal function]: yii\base\ErrorHandler->handleException(Object(yii\web\HeadersAlreadySentException))
#4 {main}
Previous exception:
yii\web\HeadersAlreadySentException: Headers already sent in D:\Programacion\Web\sisleg\vendor\mpdf\mpdf\src\Mpdf.php on line 9446. in D:\Programacion\Web\sisleg\vendor\yiisoft\yii2\web\Response.php:366
Stack trace:
#0 D:\Programacion\Web\sisleg\vendor\yiisoft\yii2\web\Response.php(339): yii\web\Response->sendHeaders()
#1 D:\Programacion\Web\sisleg\vendor\yiisoft\yii2\base\Application.php(392): yii\web\Response->send()
#2 D:\Programacion\Web\sisleg\frontend\web\index.php(17): yii\base\Application->run()
#3 {main}

Ahora veo que este problema me lo da con un documento de hasta 77 paginas, si supera esta cantidad de paginas me muestra directamente el pdf pero con 0 paginas.
El documento tiene 256 paginas pero puede llagar hasta 300 o 350.

Existe algun limite para la generacion de paginas con mPdf ?

Hola,

por casualidad estás tratando de hacer la llamada via Pjax ? si el boton está dentro de un bloque Pjax debes especificar el ‘data-pjax’ = false o cero

pudes utilizar desde una tabla html o cualquier boton, un llamado al controlador para la ejecucion del PDF, en mi caso uso :


con mpdf genera mas de 300 paginas

<?= Html::a('Imprime', ['/bienesmovimaestro/notaentrega', 'id' => $notaentrega], ['class' => 'nav-icon fas fa-print','class' => 'btn btn-primary','target' => "_blank"]) ?>

image

tambien esta la libreria TCPDF es mucho mas rapido para generar PDF

te dejo el link https://tcpdf.org/

Creo que lo que ocurre es que estás mandando unas header http (las normales para una acciòn) en tu primera request, y luego mandas las pdf y el animalico se queja de que tiene demasiadas headers.

Te dejo un ejemplo. Este código presenta en pdf un modelo (un artículo, en este caso) y luego busca una serie de campos extra para listarlo (usando un dataprovider) así que con un poco de apaño creo que te servirá o te dará una idea:

 public function actionPdf($id) {
         // buscamos el modelo a "imprimir"
        $model = $this->findModel($id);
        // bucamos la lista de campos extra para un artículo y usamos un ArrayDataProvider, por ejemplo
        $providerArticleExtraField = new \yii\data\ArrayDataProvider([
            'allModels' => $model->articleExtraFields,
        ]);

        // usamos una view llamada _pdf para presentar el contenido
        $content = $this->renderAjax('_pdf', [
            'model' => $model,
            'providerArticleExtraField' => $providerArticleExtraField,
        ]);


        // ahora configuramos el pdf en sí. Ten en cuenta que $content ya lleva la plantilla
        $pdf = new \kartik\mpdf\Pdf([
            'mode' => \kartik\mpdf\Pdf::MODE_CORE,
            'format' => \kartik\mpdf\Pdf::FORMAT_A4,
            'orientation' => \kartik\mpdf\Pdf::ORIENT_PORTRAIT,
            'destination' => \kartik\mpdf\Pdf::DEST_BROWSER,
            'content' => $content,
            'cssFile' => '@vendor/kartik-v/yii2-mpdf/assets/kv-mpdf-bootstrap.min.css',
            'cssInline' => '.kv-heading-1{font-size:18px}',
            'options' => ['title' => \Yii::$app->name],
            'methods' => [
                'SetHeader' => [\Yii::$app->name],
                'SetFooter' => ['{PAGENO}'],
            ]
        ]);

        // y devolvemos el render
        return $pdf->render();
    }

Para la plantilla _pdf, sería algo así:

<?php
use yii\helpers\Html;
use yii\widgets\DetailView;
use kartik\grid\GridView;

/* @var $this yii\web\View */
/* @var $model backend\models\Layout */

$this->title = $model->name;
$this->params['breadcrumbs'][] = ['label' => 'Layout', 'url' => ['index']];
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="layout-view">

    <div class="row">
        <div class="col-sm-9">
            <h2><?= 'Layout'.' '. Html::encode($this->title) ?></h2>
        </div>
    </div>

    <div class="row">
<?php 
    $gridColumn = [
        ['attribute' => 'id', 'visible' => false],
        'name',
        'internal_ref',
        'notes:ntext',
        'description:ntext',
        'email_answer:ntext',
        'youtube_video_id',
        'featured',
        [
                'attribute' => 'category.name',
                'label' => 'Category'
            ],
        [
                'attribute' => 'supplier.name',
                'label' => 'Supplier'
            ],
    ];
    echo DetailView::widget([
        'model' => $model,
        'attributes' => $gridColumn
    ]); 
?>
    </div>
    
    <div class="row">
<?php
if($providerArticleLayout->totalCount){
    $gridColumnArticleLayout = [
        ['class' => 'yii\grid\SerialColumn'],
                [
                'attribute' => 'article.name',
                'label' => 'Article'
            ],
        'quantity',
    ];
    echo Gridview::widget([
        'dataProvider' => $providerArticleLayout,
        'panel' => [
            'type' => GridView::TYPE_PRIMARY,
            'heading' => Html::encode('Article Layout'),
        ],
        'panelHeadingTemplate' => '<h4>{heading}</h4>{summary}',
        'toggleData' => false,
        'columns' => $gridColumnArticleLayout
    ]);
}
?>
    </div>
</div>

Cualquier cosa me dices. A ver si te sirve. Ten en cuenta que tendrás que cambiar cosas para que quede como quieras, y que es un ejemplo e igual hay algún error de comas, comillas o algo.

EDITO: Para aclarar, lo que hago es usar _pdf no como plantilla, sino como layout. Así no carga el layout general y evitas el problema de la doble header. Hay otras formas de hacerlo, claro.