Zend FrameworkのZend_Validateについては、以前書いた記事
http://blog3.logosware.com/archives/600
のようにiniファイルを利用し、メッセージを日本語化していました。
しかし、Zend Frameworkが1.10にバージョンアップしてから、
英語のメッセージが一部変わり、以前のiniファイルでは一部のメッセージが日本語化されません。
また、Zend Framework 1.10のfullパッケージには、リソースファイルが追加されました。
(resources/languages/ja/Zend_Validate.php)
ただ、記述が古いのか、うまく変換されなかったので、
1.10.8のZend_Validate.phpを元に、MessageKeyをベースにして翻訳用ファイルを作成しました。
以下のようにすることで、メッセージが日本語化されました。
$translator = new Zend_Translate(
'array',
'resources/languages/ja/Zend_Validate.php', // ファイルのパス
'ja',
array('scan' => Zend_Translate::LOCALE_FILENAME)
);
// デフォルトのトランスレータを設定
Zend_Validate_Abstract::setDefaultTranslator($translator);
Tags: ZendFramework, Zend_Validate
Twitterは6月にBasic認証が廃止されます。代替えとしてOAuth認証が採用されました。今や何処も彼処もOAuthについての記事を見かけますが、Zend_Oauthを用いての実装例があまり無いようで…..。Zend Framework をシステムに採用しているLogoswareとしては***と言う事でここに簡単な実装例を書いておきます。
【Writing A Simple Twitter Client - シンプルなTwitterクライアントの作成 -】
使用ライブラリ
Zend FrameworkのOAuthライブラリ
Zend Frameworkをダウンロードして下さい。古いVersionにはZend_Oauthが入っていないのでなるべく新しいVersionにして下さい。(ここではZendFramework-1.10.1-minimalを使用)
使用ファイル
callback.php, clear.php, common.php, index.php, tweet.php , twitter.css
大まかな手順
1.Twitterにアプリケーション登録の申請。consumerKey, consumerSecretを発行する。
2.OAuthパラメータ値をZend_Oauth_Consumerに設定
3.requestTokenを取得しOAuth認証
4.accessTokenを取得する
5.tweetをPOSTする
6.timelineGETで取得する
Twitterにアプリケーション登録の申請
割愛させて頂きます。こちらのサイトが参考になるかと思います。http://bit.ly/a00E2Q
OAuthパラメータ値をZend_Oauth_Consumerに設定
早速Zend_Oauthの設定ファイルを作成しましょう。
まずはcommon.phpを作成してください。
<?php
set_include_path(realpath(dirname(__FILE__))
.'/ZendFramework-1.10.1-minimal/library'
. PATH_SEPARATOR . get_include_path());
require_once 'Zend/Loader/Autoloader.php';
Zend_Loader_Autoloader::getInstance();
$host = $_SERVER['HTTP_HOST'];
define('URL_ROOT', "http://{$host}/twitter");
$configuration = array(
// 'version' => '1.0', // there is no other version...
'requestScheme' => Zend_Oauth::REQUEST_SCHEME_HEADER,
'signatureMethod' => 'HMAC-SHA1',
'callbackUrl' => "http://{$host}/twitter/callback.php",
'requestTokenUrl' => 'http://twitter.com/oauth/request_token',
'authorizeUrl' => 'http://twitter.com/oauth/authorize',
'accessTokenUrl' => 'http://twitter.com/oauth/access_token',
'consumerKey' => 'Twitterアプリ登録時に発行されるランダムな文字列',
'consumerSecret' => 'Twitterアプリ登録時に発行されるランダムな文字列'
);
session_start();
$consumer = new Zend_Oauth_Consumer($configuration);
今回はphp以外のデータストレージを使用しないのでsessionをフル活用します。
ここでsession_start()関数を叩いておきます。
それぞれ
| パラメータ | 説明 |
| version | OAuthのversionを指定。指定しないことも可能 |
| requestScheme | Authorizationヘッダ以外にもPOSTではRequest Body,GETではquery_stringを指定可 |
| signatureMethod | 署名方式:PLAINTEXTまたはHMAC-SHA1 を指定 |
| callbackUrl | 認証後に遷移する戻り先URLを指定。Twitterにアプリ登録時に設定したURL(80/443番ポート)を設定。戻り先URLがない場合は’oob’を指定可能 |
| requestTokenUrl | requestToken取得時に利用するURL |
| authorizeUrl | 認証画面URL |
| accessTokenUrl | accessToken取得時に利用するURL |
| consumerKey | Twitterアプリ登録時に発行されるランダムな文字列 |
| consumerSecret | Twitterアプリ登録時に発行されるランダムな文字列 |
requetTokenを取得しOAuth認証
index.php
<?php
require_once './common.php';
if (!isset($_SESSION['TWITTER_ACCESS_TOKEN'])) {
$token = $consumer->getRequestToken();
$_SESSION['TWITTER_REQUEST_TOKEN'] = serialize($token);
$consumer->redirect();
}
/*
以下 html部分
......
*/
認証していない場合はクライアントからTwitterにOAuthでAPIをたたきrequestTokenを取得。
Twitterに認証をお願いしています。
accessTokenを取得する
callback.php
<?php
include_once './common.php';
if (!empty($_GET) && isset($_SESSION['TWITTER_REQUEST_TOKEN'])) {
try{
$token = $consumer->getAccessToken($_GET,
unserialize($_SESSION['TWITTER_REQUEST_TOKEN']));
}catch (Exception $ex){
$ex->getMessage();
}
$_SESSION['TWITTER_ACCESS_TOKEN'] = serialize($token);
$_SESSION['TWITTER_REQUEST_TOKEN'] = null;
header('Location: ' . URL_ROOT . '/index.php');
}
else {
exit('無効なコールバック要求されました。おっと。申し訳ありません。');
}
認証を終えるとTwitterが上記common.phpで指定したcallbackUrlを呼び出してくれます。
ここではaccessTokenをsessionに入れておきます。
TweetをPOSTする
tweet.php
<?php
include_once './common.php';
if (!empty($_POST) && isset($_POST['status'])
&& isset($_SESSION['TWITTER_ACCESS_TOKEN'])) {
$token = unserialize($_SESSION['TWITTER_ACCESS_TOKEN']);
$client = $token->getHttpClient($configuration);
$client->setUri('http://twitter.com/statuses/update.json');
$client->setMethod(Zend_Http_Client::POST);
$client->setParameterPost('status', $_POST['status']);
$response = $client->request();
$data = json_decode($response->getBody());
$result = $response->getBody();
if (isset($data->text)) {
$result = 'true';
}
header('Location: ' . URL_ROOT . '?result=' . $result);
}
else {
exit('無効なTweetが要求されました。');
}
認証で取得したaccessTokenを用いtweetをTwetterにpostします。
responseの形式をjsonに指定していますが他にxmlを指定することができます。ここではresponseは使用しません。
詳しくはTwitter API Wikiを参照
Twitter REST API Method: statuses/update
以上でOAuthを用い認証そしてPOSTまでの手順になります。ホントにシンプルです。
以下はtwieetをPOST後timelineを表示させます。
timelineGETで取得する
Twitterからのレスポンスはjson or xmlの形で返されます。
以下はjson形式のresponseをphp用にdecodeした形です。
stdClass Object
(
[in_reply_to_user_id] =>
[contributors] =>
[source] => client
[created_at] => Sat May 22 21:33:34 +0000 2010
[in_reply_to_screen_name] =>
[place] =>
[favorited] =>
[truncated] =>
[in_reply_to_status_id] =>
[coordinates] =>
[user] => stdClass Object
(
[favourites_count] => number
[description] =>
[lang] => ja
[profile_background_color] => EDECE9
[profile_image_url] => http://a1.twimg.com/profile_images/912973500/TwitterID_normal.jpg
[time_zone] => Tokyo
[profile_sidebar_fill_color] => a7d6ac
[statuses_count] => number
[screen_name] => logosware
[following] =>
[created_at] => Sat May 30 03:36:56 +0000 2009
[followers_count] => number
[contributors_enabled] =>
[profile_background_image_url] => http://s.twimg.com/a/TwitterID/images/themes/theme1/bg.png
[profile_text_color] => 052115
[friends_count] => number
[profile_background_tile] =>
[protected] =>
[url] =>
[geo_enabled] =>
[name] => logosware
[profile_sidebar_border_color] => D3D2CF
[profile_link_color] => 088253
[location] => つくば
[id] => 43473241
[verified] =>
[notifications] =>
[utc_offset] => 32400
)
[geo] =>
[id] => 145175******
[text] => つくばってイノベーションだよね?
)
response中身は極々単純で分かりやすいです。
それではタイムライン表示させてみます。
index.phpの続き
<?php
...........
/*
以下 html部分
......
*/
if (isset($_SESSION['TWITTER_ACCESS_TOKEN'])) {
$token = unserialize($_SESSION['TWITTER_ACCESS_TOKEN']);
$client = $token->getHttpClient($configuration);
$client->setUri('http://twitter.com/statuses/home_timeline.json');
$client->setMethod(Zend_Http_Client::GET);
$response = $client->request();
$_data = json_decode($response->getBody());
if (count($_data)>0) {
$_SESSION['TWITTER_RESULT'] = $_data;
}
}
echo '<?xml version="1.0" encoding="UTF-8"?>';
?>
aceessTokenを用いhome timelineをGETで取得します。
responseの形式をjsonに指定していますが他にxml, atomを指定することができます。
詳しくはTwitter API Wikiを参照
Twitter REST API Method: statuses home_timeline
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" >
<head>
<title>Logosware twitter lite client</title>
<script type="text/javascript">
function imposemax(Object)
{
return (Object.value.length <= 140);
}
</script>
<link rel="stylesheet" type="text/css" href="css/twitter.css"></link>
</head>
<body>
<?php
if (isset($_GET['result']) && $_GET['result'] == 'true'){
?>
<p style="background-color: lightgreen;">正常にtweetしました!
<br />- You successfully sent your tweet!<br /></p>
<p> <br /></p>
<?php
}
else
if (isset($_GET['result']) && !empty($_GET['result'])){
?>
<p style="background-color: red;">
おっと! あなたのtweetはTwitterが受け付けてくれなかったようです。考えられる原因:
</p>
<div style="background-color: red;"><?php echo $_GET['result']; ?><br /></div>
<p> <br /></p>
<?php
}
?>
<p>簡易Twitterクライアント <br />
- All that work on Zend_Oauth, and all you do is send Tweets with it?
<img src="/admin/images/loading.gif" alt="load"
style="display: inline; vertical-align: bottom;" class="emoticon" /><br/><br/>
</p>
<form action="tweet.php" method="post" id="statusform">
<p>TweetをPOSTします。140文字でなにを言いたいですか? <br /></p>
<p>
<textarea name="status" id="status" rows="4" cols="70%"
onkeypress="return imposemax(this);"></textarea>
<br/><input type="submit" id="submit" value="Tweet"/>
</p>
</form>
ここまでが投稿フォームになります。ゴニョゴニョやっていますが好きに実装したらいいと思います。
<div class="wrapper">
<div class="section">
<div id="timeline_heading">
<h1 id="heading">result</h1>
<?php
if(isSet($_SESSION['TWITTER_RESULT'])){
?>
<ol class="statuses" id="timeline">
<?php
foreach($_SESSION['TWITTER_RESULT'] AS $key=>$data){
?>
<li style="background-color: <?php echo $color?>;" id="status_14505086646"
class="hentry u-<?php echo $data->user->screen_name?> status">
<span class="thumb vcard author">
<a class="tweet-url profile-pic url"
href="http://twitter.com/<?php echo $data->user->screen_name?>">
<img height="48" width="48" class="photo fn" alt="<?php echo $data->user->name ?>"
src="<?php echo $data->user->profile_image_url ?>"/>
</a>
</span>
<span class="status-body">
<span class="status-content">
<strong>
<a href="http://twitter.com/<?php echo $data->user->screen_name?>"
class="tweet-url screen-name" >
<?php echo $data->user->screen_name?>
</a>
</strong>
<span class="entry-content">
<?php echo $data->text?>
</span>
</span>
<span class="meta entry-meta">
<a rel="bookmark" class="entry-date"
href="http://twitter.com/<?php echo $data->user->screen_name?>/status/<?php echo $data->id?>">
<span class="published timestamp">
<?php echo $data->created_at?>
</span>
</a>
<span>
<?php echo $data->source?>から
</span>
</span>
</span>
</li>
<?php
}
?>
</ol>
<?php
}
?>
</div>
</div>
</div>
<p><br/><br/>セッションをクリアし再度OAuth認証します。<br/>
<a href="clear.php">Clear session&Access Token</a></p>
</body>
</html>
htmlも混ざって色合い的にちょっと見にくいかと思いますがaceessTokenを用いGETで取得したresponseの中身を表示させています。
以上でシンプルなTwitterクライアントの完成です。
今回はOAuthがメインのため実装した機能はtimeline表示とtweet更新だけですが他にもTwitter APIは様々な機能が実装できます。
Twitter API Wiki / FrontPage
作成したTwitterクライアントのファイルを置いておきます(css同梱)。MVC, オブジェクト指向なにそれな内容ですが何かの足しになれば私としても嬉しいです。
Tags: API, Twitter, ZendFramework
最近、PHPフレームワークについて調査していなかったので、再調査。
Googleの検索結果を見ると、symfony,CakePHP,Zend,CodeIgniterが4強の印象を受けました。
最近の動向(2010/4/12現在)
NetBeans 6.8で標準サポートされています。
2.0について、ページに
Based on an innovative architecture, Symfony 2 is fast, flexible, and easy to learn. It allows developers to build better and more easily maintainable websites with PHP.
とあるように、2.0では高速化されているようです。
日本では一番使われていると思われるフレームワーク。
ただ、4年間Cakeの発展に貢献してきたプロジェクトマネージャの人がCakePHPのプロジェクトを去って、Lithiumというプロジェクトを立ち上げたようです。
参考記事 http://blog.candycane.jp/archives/121
1.10でPHP5.3に対応。
バージョンアップ毎に便利なライブラリが追加されています。
軽量フレームワーク。
海外で割と使用されている印象。
使い捨てなら良いのだけれど、長期に渡って利用できるフレームワークじゃないとメンテナンスのコストが大きくなるので、どれを選ぶのかは重要です。
前回は「Hello world」をフッターに表示する簡単なプラグインを作成しました。
私もここまでは簡単にできました。いろいろなサイトに簡単なプラグインが紹介されているので、同じようにファイルを設置し、動作させることはできました。
問題はここからでした。自分が実現しようとしているプラグインを作成するためには、どのようなフックポイントに対してプラグインを作成すればいいのか、さっぱりわからないのです。
今回は、そのフックについて説明します。
WordPressのプラグイン機能はフックが鍵となります。前回の「Hello world」で言うと「add_action(’wp_footer’, ‘helloworld’);」の中の「wp_footer」の部分ですね。フックといわれてもピンと来ないのでWikiPediaで調べてみると
フック(Hook)は、プログラム中の特定の箇所に、利用者が独自の処理を追加できるようにする仕組みである。また、フックを利用して独自の処理を追加することを「フックする」という。
と書かれています。
また、WordPressのCodexで調べてみると
WordPress はプラグインを WordPress 本体に “引っ張り込む (hook into)” ためのフックを提供しています。これはつまり、特定のタイミングでプラグインの関数を呼び出したり、それによってプラグインを作動させたりするためのものです。
と書かれていました。
WordPressでは、起動から初期化、コンテンツの読み出し、ヘッダー出力、フッター出力と様々な処理を行って表示を行います。それらの処理のところどころにフックポイントが用意されていて、プラグイン作成時はそのフックポイントに対して処理を記述していく。ということになります。

WordPressのCodexでは、フックポイントの一覧が掲載されています。
様々なフックが載っていますが、
・どのタイミングで呼ばれるのか?
・どような変数が渡され、返すことができるのか?
さっぱりわかりませんでした。
また、アクションフックとフィルターフックの違いについても、私はしばらく理解することができませんでした。次回は、そのあたりを詳しく説明したいと思います。
ブログソフトウェアというと、「Movable Type」か「WordPress」が思いつきますが、弊社のDCG(デザインコンテンツグループ)ではWebサイト構築時にWordPressをよく利用しています。
その際にWebサイトの表示はWordPressで行い、データ管理を別システムで管理し、連携させることもあります。
そのような中で学ぶことができたプラグインの開発方法を紹介していきたいと思います。
PHPについては理解しているが、WordPressのプラグインを作成したことの無い方を対象としています。
WordPressのインストールについては多くのサイトで紹介されていますので省略いたします。
さっそくHello worldを表示してみます。
以下の内容でphpファイルを作成します。
/*
Plugin Name: Hello world
Plugin URI: http://logosware.com/
Description: Hello worldプラグイン
Version: 1
Author: Yasuhisa Ishikawa
Author URI: http://logosware.com/
*/
add_action('wp_footer', 'helloworld');
function helloworld(){
echo "--- Hello world ---";
}
WordPressのプラグインを設置する場合、主となるファイルの先頭には以下のヘッダを入れなければなりません。
/* Plugin Name: (プラグインの名前) Plugin URI: (プラグインの説明と更新を示すページの URI) Description: (プラグインの短い説明) Version: (プラグインのバージョン番号。例: 1.0) Author: (プラグイン作者の名前) Author URI: (プラグイン作者の URI) */
10行目の
add_action(’フック名’, ‘関数名’);
今回はフッターに表示させたいため、’wp_footer’にフックさせます。
フック時に実行される関数を指定します。
12行目の
function helloworld()
フック時に実行される関数です。
以下のディレクトリにファイルを設置します。

WordPressの管理画面から、プラグインを開きます。
その中にあるHello worldプラグインの「使用する」をクリックし、有効にします。

ブログを表示すると、フッター部分にHello worldが表示されます。
Tags: PHP WordPress プラグイン
開発で、よくTinyMCEのversion2を使用していおります。
(ブログ等に設置されている、便利なテキストエディタです)
しかし、このツールイメージブラウザが、
標準では設置されていないようです。
そこで非常に単純なイメージブラウザの設置の仕方を紹介します。
1.tinymce/themes/advanced/image.html
のファイルで、開くイメージブラウザのパスを変更します。
2.次にイメージブラウザ(imageBrowser.php)を作成します。
イメージブラウザ自体の作成は、ここで全部公開するのはよろしくないと思いますので、
簡単に説明します。
【作り方】
・特定の公開ディレクトリを画像保管庫とし、そこに画像をFTP等でアップしておきます。
・そのディレクトリのファイル一覧を取得し、同時に該当画像の立て幅、横幅を取得します。
・画像をクリックすることで、以下のJavascriptを実行します。
function imageInsert(PATH,WIDTH,HEIGHT){
window.opener.document.getElementById('src').value=PATH;
window.opener.document.getElementById('width').value=WIDTH;
window.opener.document.getElementById('height').value=HEIGHT;
close();
}
ご参考頂ければ幸いです。
PHPで意外に使いそうなのに用意されていない関数があります。
その1つに、ディレクトリの削除があります。
ディレクトリを削除するには、rmdir関数を使いますが、
知っている限り(PHP5.3.0時点)、ディレクトリの中にファイル等がある場合には削除できません。
Linuxの場合には、
system(”rm -rf $path”);
でも削除できますが、Windowsでは当然動かなく、delコマンドに変える必要があります。
そこで、PHPの関数で実装してみると、以下のようになりました。
<?php
/**
* 再帰的にディレクトリを削除する。
* @param string $dir ディレクトリ名(フルパス)
*/
function removeDir( $dir ) {
$cnt = 0;
$handle = opendir($dir);
if (!$handle) {
return ;
}
while (false !== ($item = readdir($handle))) {
if ($item === "." || $item === "..") {
continue;
}
$path = $dir . DIRECTORY_SEPARATOR . $item;
if (is_dir($path)) {
// 再帰的に削除
$cnt = $cnt + removeDir($path);
}
else {
// ファイルを削除
unlink($path);
}
}
closedir($handle);
// ディレクトリを削除
if (!rmdir($dir)) {
return ;
}
}
?>
Tags: PHP
以前からZend_Validateを使っていたのですが、本格的な翻訳は行わず、手元で強引に日本語メッセージを作成していました。
しかし、開発規模が大きくなってくると対応が難しくなってきます。
ZendFrameworkにはZend_Translateという多言語に対応したアプリケーションを作るためのパッケージが用意されています。
このZend_Translateを使うとZend_Validateのメッセージを多言語に対応させることが可能です。
※ZendFrameworkのバージョンは1.9.6を使っています。
■Zend_Translateの使い方
Zend_Translateでは設定ファイルを、配列、CSV、ini、Gettextなど各種入力ファイルをサポートしていますが、ZendFrameworkのドキュメントに記載されている例を使って、簡単な配列で説明いたします。
$english = array(
'message1' => 'message1',
'message2' => 'message2',
'message3' => 'message3');
$japanese = array(
'message1' => 'メッセージ1',
'message2' => 'メッセージ2',
'message3' => 'メッセージ3');
$translate = new Zend_Translate('array', $english, 'en');
$translate->addTranslation($japanese, 'jp');
print $translate->_("message1");
// 結果:メッセージ1
このようにとても簡単に翻訳ができます。
■Zend_Validateの翻訳
Zend_Validateの翻訳は量が多いため、配列ではなく、ini形式で翻訳ファイルを用意しました。以下は、翻訳ファイルの記載例です。
; Alnum Invalid type given, value should be float, string, or integer = "不正な値です。小数、文字列、又はは数字を入力して下さい。" '%value%' has not only alphabetic and digit characters = "'%value%'にアルファベットと数字以外の文字が含まれています。" '%value%' is an empty string = "'%value%'が入力されていません。"
どのメッセージを日本語化すべきかは、Zend_Validateのドキュメントに記載されています。
http://framework.zend.com/manual/ja/zend.validate.messages.html
次に作成した翻訳ファイルをZend_Validateにあてます。
$translate = new Zend_Translate('ini', '/filepath/validate.jp.ini', 'jp');
Zend_Validate_Abstract::setDefaultTranslator($translate);
これでValidateを行うとメッセージは用意した翻訳ファイルにしたがって日本語化されます。
Tags: PHP, ZendFramework, Zend_Validate
通常、ブラウザでパスワードを入力して送信すると、
ブラウザが「パスワードを保存しますか?」と聞いてきて、
「OK」すると、パスワードが保存されます。
ドメイン単位で管理されているらしく、ブラウザのオートコンプリート機能によって
パスワードの入力欄があると勝手に補完されてしまいます。
<form>
<input name="loginid" type="text" value="" />
<input name="password" type="password" value="" />
<input type="submit" value="送信" />
</form>
どうやら、passwordと直前のtextとの組み合わせで、
両方の値が空(value=”")の場合に、勝手に補完されるようです。
<input name=”password” type=”password” value=”" autocomplete=”off” />
とすれば補完されないようですが、今回はそれとは別の方法で防ぎます。
password直前のinputに適当に値を入れてみます。
<form>
<input name="loginid" type="text" value="" />
<span style="display:none">
<input name="datetime" type="text" value="<?= date("Y-m-d H:i:s") ?>" />
</span>
<input name="password" type="password" value="" />
<input type="submit" value="送信" />
</form>
こうすることで、ほとんどのブラウザで補完されなくなります。
Tags: PHP
PHPプログラムで、動的にPDFファイルを生成することがよくあります。
このとき、mbfpdfというPDF生成ライブラリを利用するのが主なのですが、
簡単な帳票などは、html2fpdfというライブラリを私は利用しています。
google先生で検索すると、
色々と改行方法のインフォメーションがあるのですが、
どれも実際はうまく動きませんでした。(あくまで私の使っているバージョンでは)
そこで、半ば無理やりに、但し確実に改ページする方法を紹介します。
html2pdf.phpに
function WriteHTML($html)
{
$this->ReadMetaTags($html);
$html = AdjustHTML($html,$this->usepre); //Try to make HTML look more like XHTML
if ($this->usecss) $html = $this->ReadCSS($html);
//Add new supported tags in the DisableTags function
$html=str_replace('','< ',$html); //Fix 'enabledtags); //remove all unsupported tags, but the ones inside the 'enabledtags' string
//Explode the string in order to parse the HTML code
$a=preg_split('/<(.*?)>/ms',$html,-1,PREG_SPLIT_DELIM_CAPTURE);
foreach($a as $i => $e)
{
$this->SetFont('SJIS','',9);
$this->SetTextColor(0,0,139);
$e = mb_convert_encoding($e,'SHIFT-JIS','UTF-8');
このような記述部分があります。
ここでは、変換対象のHTMLを解析し、HTMLタグを抽出し、
それに対応したPDF出力を行う部分になります。
foreach($a as $i => $e)
この$eの中に、タグが格納されています。(tableとかtrとか)
そこで、
例えば「divタグがある場合は、必ず改行」と自分の中でルールを設定し、
foreach($a as $i => $e)
{
if($e=="div"){
$this->AddPage();
}
このような感じで、mbfpdfの改ページメソッドを叩けば、
その部分で確実に改ページされます。
かなり無理やり感がありますが、
応用すれば、色々なHTMLタグに対して、
いかようにも出力を操作できますので、非常に便利だと思います。
参考にしていただければ幸いです。