CakePHP 3 の Html ヘルパーを使って data:image 形式の画像を表示する


CakePHP 3.6 の Html ヘルパーを使って data:image 形式の画像を表示してみました。

課題

画像がファイルとして存在していなく、Base64エンコーディングされているデータだったり、1回のリクエストでHTMLと画像を送信しなければならないときなど、

<img src="data:image/png;base64,iVBORw0...S3wF==">

というタグをヘルパーを使って出力しようとして、テンプレート内で、

<?= $this->Html->image('data:image/png;base64,iVBORw0...S3wF=='); ?>

とそのまま data:image を突っ込んでも、

<img src="appdata:image/png;base64,iVBORw0...S3wF==" alt="">

の "app" のようなアプリケーションのパスがついてしまってうまく表示してくれません。

解決法

Htmlヘルパーの image() メソッドは、内部的にはパスを整形して formatTemplate() メソッドを呼び出しているようなので、

<?php
$imageData = 'data:image/png;base64,iVBORw0...S3wF==';
echo $this->Html->formatTemplate(
  'image', [ 'url' => $imageData ]
);
?>

で良さそうです。

<img src="data:image/png;base64,iVBORw0...S3wF==" alt="">

src 以外の属性を付けたい場合は、

<?php
$imageData = 'data:image/png;base64,iVBORw0...S3wF==';
$attributes = [
    'class' => 'header-image header-image-logo',
    'alt' => 'Header Image'
];
echo $this->Html->formatTemplate(
    'image', [
      'url' => $imageData, 
      'attrs' => $this->Html->templater()->formatAttributes($attributes)
    ]
);
?>

とすると、

<img src="data:image/png;base64,iVBORw0...S3wF==" class="header-image header-image-logo" alt="Header Image"/>

のような結果が得られました。

ICOOON MONOさんから、無料のタブレットアイコン素材2 の素材を使わせていただいて、実際に表示される画像をスニペット的に作りました。
ビューにコピペしていただければ動くと思います。
なお、ヒアドキュメントを使う場合、trim() と併用して前後のスペースを除くようにしておくのが無難ですね。

<?php

$imageData = trim(<<<END_OF_IMAGE
data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAB/ElEQVRoQ+1asU4bQRB947igSoeAhh5MQYeEIgGV5VuXOFVaZNpIEeEXIgpaS5RUFHS3u3IFSNBQgZRAnwJk0VC5snbQKQ6Kwvns3Vs3aK7emfdm39u9lWYIE3xKqXUAPwB8mmB5jCW/mbljjMkwXVFCGoNWUUp1AOzEYOWbg5lPjTGfi4ooLEAp9Q3AgS9wzPXMvGeMGcmhqABKkuSBiOZjEgrI1dNaLwDgvNiRBSillgDcBQBGD3HO1ay1uVxGFtBoNDYqlcp5dDYBCZ1zm9baCy8Fms3mJjOf/RtERFtpmk61KF/ckQr4JgrY2NwQX1wpINbO/80jCoTuRCwlRAFRoKSXxEJiIbGQ3xtMnhIlHfMmXG4huYVKekosJBYSC8mP7I8HfG+Dks55DffFladErJ0Pvf1EAVHgvx2QQxx6mGJZSRR41woA+EpEN7HskpeHmVcBHE7aWPH6D0yTeFHuos7Q+y0gRpOPmR8BHAPYJaKPoQoGNfnq9XqtWq3+DAUdxi1rre+VUl+GhQSlGwwGK91u91de8LhGd4+IZoNQARDRWpqm10mStIkoG1nw/pj5yRgz593ozpAijBo8M/MtgDUimvFmn7EuMWqQ4WXDHicAtkPAI8Qcaa13g4c9MgKtVutDv9//DqANYDECqUlSXDrn9q21V+MWvwBaiKVPvJ+e4gAAAABJRU5ErkJggg==
END_OF_IMAGE
);

$attributes = [
    'class' => 'icon-tablet',
    'alt' => 'Tablet'
];

echo $this->Html->formatTemplate(
    'image', [
        'url' => trim($imageData),
        'attrs' => $this->Html->templater()->formatAttributes($attributes)
    ]
);

?>