You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

FPDF实现旋转透明文本报No page has been added yet解决方法

报错根因
  • 核心错误1:对象实例反复重建。你在调用AddPage()给初始$pdf对象添加页面后,多次执行$pdf = new AlphaPDF()、$pdf = new PDF(),相当于把原有带页面的对象替换成了全新的空对象,空对象没有执行过AddPage(),直接调用需要页面上下文的方法就会触发「No page has been added yet」致命错误。
  • 核心错误2:类继承结构设计错误。你写的AlphaPDF、PDF_Rotate两个功能类是平行关系,都直接继承原生FPDF,最终使用的PDF类只继承了PDF_Rotate分支,根本不包含AlphaPDF实现的透明度能力,就算不报错也没法同时使用两个功能。
正确实现方式

在FPDF 1.84 + PHP 8.1环境下同时实现旋转、透明效果,只需要做两处调整:

  1. 调整类继承链,把两个功能合并到同一条继承线上,不要做平行拆分
  2. 整个PDF生成流程只实例化一次PDF对象,全程复用该实例,不要中途新建对象覆盖变量
修正后代码

类定义部分

use setasign\FpdiProtection\FpdiProtection;

require_once('../../pdf/fpdf/fpdf.php');
require_once('../../pdf/fpdi/src/autoload.php');
require_once('../../pdf/fpdi-protection/src/autoload.php');
require('../../pdf/fpdf/fpdf_merge.php');

// 第一层:实现透明度能力,继承原生FPDF
class AlphaPDF extends FPDF
{
    protected $extgstates = array();

    function SetAlpha($alpha, $bm='Normal')
    {
        $gs = $this->AddExtGState(array('ca'=>$alpha, 'CA'=>$alpha, 'BM'=>'/'.$bm));
        $this->SetExtGState($gs);
    }

    function AddExtGState($parms)
    {
        $n = count($this->extgstates)+1;
        $this->extgstates[$n]['parms'] = $parms;
        return $n;
    }

    function SetExtGState($gs)
    {
        $this->_out(sprintf('/GS%d gs', $gs));
    }

    function _enddoc()
    {
        if(!empty($this->extgstates) && $this->PDFVersion<'1.4')
            $this->PDFVersion='1.4';
        parent::_enddoc();
    }

    function _putextgstates()
    {
        for ($i = 1; $i <= count($this->extgstates); $i++)
        {
            $this->_newobj();
            $this->extgstates[$i]['n'] = $this->n;
            $this->_put('<</Type /ExtGState');
            $parms = $this->extgstates[$i]['parms'];
            $this->_put(sprintf('/ca %.3F', $parms['ca']));
            $this->_put(sprintf('/CA %.3F', $parms['CA']));
            $this->_put('/BM '.$parms['BM']);
            $this->_put('>>');
            $this->_put('endobj');
        }
    }

    function _putresourcedict()
    {
        parent::_putresourcedict();
        $this->_put('/ExtGState <<');
        foreach($this->extgstates as $k=>$extgstate)
            $this->_put('/GS'.$k.' '.$extgstate['n'].' 0 R');
        $this->_put('>>');
    }

    function _putresources()
    {
        $this->_putextgstates();
        parent::_putresources();
    }
}

// 第二层:实现旋转能力,继承已经带透明功能的AlphaPDF,不要直接继承FPDF
class PDF_Rotate extends AlphaPDF
{
    var $angle=0;

    function Rotate($angle,$x=-1,$y=-1)
    {
        if($x==-1)
            $x=$this->x;
        if($y==-1)
            $y=$this->y;
        if($this->angle!=0)
            $this->_out('Q');
        $this->angle=$angle;
        if($angle!=0)
        {
            $angle*=M_PI/180;
            $c=cos($angle);
            $s=sin($angle);
            $cx=$x*$this->k;
            $cy=($this->h-$y)*$this->k;
            $this->_out(sprintf('q %.5F %.5F %.5F %.5F %.2F %.2F cm 1 0 0 1 %.2F %.2F cm',$c,$s,-$s,$c,$cx,$cy,-$cx,-$cy));
        }
    }
    
    function _endpage()
    {
        if($this->angle!=0)
        {
            $this->angle=0;
            $this->_out('Q');
        }
        parent::_endpage();
    }
}

// 第三层:实现旋转文本快捷方法,继承带旋转+透明能力的PDF_Rotate
class PDF extends PDF_Rotate
{
    function RotatedText($x,$y,$txt,$angle)
    {
         $this->Rotate($angle,$x,$y);
         $this->Text($x,$y,$txt);
         $this->Rotate(0);
    }
}

// 整个流程只实例化一次,不要后续重复new
$pdf = new PDF();

页面生成逻辑部分

删掉所有重复实例化的代码,直接复用全局$pdf对象:

if ($height>=$width)
{
    $pdf->AddPage('P','A4');
    $pdf->Image($imagefilePath,2,4,208,293);
    // 直接在原有实例上调用透明度方法,不要新建对象
    $pdf->SetAlpha(0.5);
    $pdf->SetFont('Arial', '',15);
    $pdf->SetTextColor(255,0,0);
          
    $pdf->RotatedText(105-90, 148.5-120,'CONTROLLED COPY',45);
    $pdf->RotatedText(105-90, 148.5+7-120,$nmrdvl,45);
          
    $pdf->RotatedText(105-25, 148.5,'CONTROLLED COPY',45);
    $pdf->RotatedText(105-25, 148.5+7,$nmrdvl,45);
          
    $pdf->RotatedText(105+35, 148.5+120,'CONTROLLED COPY',45);
    $pdf->RotatedText(105+35, 148.5+7+120,$nmrdvl,45);
          
    // 恢复完全不透明状态
    $pdf->SetAlpha(1);
    $pdf->SetTextColor(0,0,0);
} 
else
{
    $pdf->AddPage('L','A4');
    $pdf->Image($imagefilePath,2,4,293,208);
    // 直接在原有实例上调用透明度方法
    $pdf->SetAlpha(0.5);
    $pdf->SetFont('Arial', '',15);
    $pdf->SetTextColor(255,0,0);
          
    $pdf->RotatedText(148.5-120, 105-85, 'CONTROLLED COPY',45);
    $pdf->RotatedText(148.5-120, 105+7-85, $nmrdvl,45);
          
    $pdf->RotatedText(148.5-25, 105, 'CONTROLLED COPY',45);
    $pdf->RotatedText(148.5-25, 105+7, $nmrdvl,45);
          
    $pdf->RotatedText(148.5+70, 105+85, 'CONTROLLED COPY',45);
    $pdf->RotatedText(148.5+70, 105+7+85, $nmrdvl,45);
          
    // 恢复完全不透明状态
    $pdf->SetAlpha(1);
    $pdf->SetTextColor(0,0,0);
}
注意事项
  • 调整继承链后,最终的PDF实例同时拥有SetAlpha、Rotate、RotatedText以及原生FPDF的所有方法,不需要切换对象调用
  • 旋转方法基于PDF图形状态栈实现,旋转结束后调用Rotate(0)即可恢复原有坐标状态,和透明效果互不冲突
  • FPDF 1.84版本已兼容PHP 8.1,只要保证所有方法都在同一个实例、且已调用AddPage()的前提下执行,就不会触发页面不存在的报错

内容的提问来源于stack exchange,提问作者Pup In The Tree

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.01 04:55:19