Web site construction UP-I

  • 遺跡データベース

  • 旅を楽しむエッセンス

  • ジモップ(地域活性サイト)

ZEND+SmartyをPHPバーションに対応させる。

ZENDは4、Smartyは3にまでバージョンアップしました。(2022年)

現在フレームワークと言えば

Laravel / CakePHP / Symfony / CodeIgniter / ZendFramework / Phalcon / Slim / Yii / FuelPHP / Flight / など


PHP5用MVCとして、また拡張性・自由度が高く中~大規模までを意識したZENDフレームワークがかつて主流でした。
さらに、プログラムとhtmlコーディングやデザインを分けた効率の良い制作の為にSmartyを連携させたZENDフレームワーク+Smartyも人気でした。 が、phpバージョンの変更による廃止関数などの影響でバグが発生するようになっています。
そこで、ZENDフレームワーク+Smartyを捨てて新しいフレームワークを習得するか、なんとか修正して使い続けるかの選択となります。
Laravelなど新しいフレームワークに変更する場合は、ネットでもいろいろな解説が出ていますし、書籍などもありますのでそちらで学習することをお勧めします。
大変なのはやっぱり古いバージョンのフレームワークを使い続けることですね。
今回、古いバージョンのZendFramework1+Smarty1をphp8に対応させるといった事を行ってみました。
例えば
php5.6ではpreg_replace関数のe修飾子などが廃止。
php7ではcreate_function() 関数の廃止
php8ではarray_key_exists() 関数などが廃止。
など、私が扱ってきた中では時代的にもZendFramework1+Smarty1が圧倒的に多く、その他様々な変更もありバグ修正に悪戦苦闘の連日です




■php5.4→php5.6の変更

■Smarty

library/smarty/smarty_Compiler.class.php

265行あたり

preg_replace関数のe修飾子の書き換え

$source_content = preg_replace($search.'e', "'" . $this->_quote_replace($this->left_delimiter) . 'php' . "' . str_repeat(\"\n\", substr_count('\\0', \"\n\")) .'" . $this->_quote_replace($this->right_delimiter) . "'" , $source_content);

preg_replace_callback(create_function ())に書き換える

$source_content = preg_replace_callback($search, create_function ('$matches', "return '" . $this->_quote_replace($this->left_delimiter) . 'php' . "' . str_repeat(\"\n\", substr_count('\$matches[1]', \"\n\")) .'" . $this->_quote_replace($this->right_delimiter) . "';") , $source_content);


■ZEND

特に変更は無し。


■php5.6→php7.3の変更

■Smarty

php5.6では動いていたcreate_function ()が廃止になるので、無名関数を使うという事です。

普通にfunction ($matches){ ...... }でOKです。

library/smarty/smarty_Compiler.class.php

265行あたり

$source_content = preg_replace_callback($search, function ($matches) {return $this->_quote_replace($this->left_delimiter) . 'php' . str_repeat("\n", substr_count($matches[0], "\n")) . $this->_quote_replace($this->right_delimiter);} , $source_content);

PHP5.6からpreg_replaceのe修飾子はDEPRECATED扱いとなっていたが、一応動いてはいた。
PHP7.3では、preg_replaceのe修飾子を使うと、Warningを吐きつつNULLを返して動かなくなる。

クラス名と同じ名前のメソッドは、コンストラクタと解釈されなくなりました。

__construct() メソッドを代わりに使用。

library/smarty/Smarty.class.php

559行目あたり

全体を囲っている

function Smarty(){.... → function __construct() {....

に変更

templates_cのコンパイルされている.tpl.phpを削除すると442行目のpreg_match(内の465行目にエラーがあると表示されます)
が、これは下記function Smarty_Compiler()を書き換える事でエラーがなくなります。

library/smarty/smarty_Compiler.class.php

81行目

function Smarty_Compiler(){.... → function __construct() {....

に変更


■ZEND

php7.3以上ではcount()内は配列でないといけないのでis_countable()でチェック。
is_countable()は引数が、数えられる値かどうかなのでおかしければis_array()を利用。
以前はcountがnullであれば0を返していたば→warningを返す仕様

library/Zend/Db/Table/Abstract.php

1240行

$keyValuesCount = count($keyValues); ↓↓↓ $count=1;//0だとパラメータが無いと判断されるので1を代入 if (!is_array($keyValues)) { $keyValues_arry = array($keyValues); $count=count($keyValues_arry); } //$keyValuesCount = count($keyValues); $keyValuesCount = $count;


■php7.3→php8の変更

■Smarty

each()関数の廃止

古いコード(php4世代)ではlist()= each();がよく使われていたという事ですが、1000行以下では普通にforeach(){.....}が使われているのでforeach(){.....}でいいのでは?

library/smarty/smarty_Compiler.class.php

list(, $block) = each($this->_folded_blocks); ↓↓↓ foreach($this->_folded_blocks as $key=>$val){ $block=$val; $this->_current_line_no += substr_count($block[0], "\n"); }

formでWarningエラー

コンパイルファイルエラーと表示される
Warning: Undefined array key "name" in /home/.../.../application/modules/default/views/templates_c/%%DD^DD5^DD5C262E%%index.tpl.php on line 54" class="input"
Undefined array key 未定義の配列キーを参照してるというエラー
input のvalue値に{$name}など未定義の変数をセットすることで起こる。
php7.4ではスルーされるがphp8ではWarningとなる。
Undefined array keyとなるのはコンパイルファイル内の変数 _tpl_vars{'.....'}; ?>
などが配列となっているからで、より厳格になったと言える。

解決
Controller.php の index Action に$this->smarty->assign(各変数,'')を初期セットしてassignする。
formを受け取ったあとは、if ($this->_request->isPost()){//ポストされた値を取得}で変数がセットされていくので問題は無し。


■ZEND

array_key_exists()は廃止なので、property_exists()かisset()を利用。

array_key_exists()はオブジェクトと配列を区別しない。
property_exists()はオブジェクトを処理するので単純に書き換えてもエラーとなる。
new ArrayObjectで$thisをオブジェクトに変換

library/Zend/Registry.php

197行目

return array_key_exists($index, $this); ↓↓↓ $obje = new ArrayObject($this); return property_exists($obje,$index);


■その他注釈

library/Custom/内にCheckForm.phpやFileOperation.phpやUtil.phpなどを作成して独自のfunctionで処理をしたり、application/modelsにNews.phpなど作成してSQL文での処理をすることで、Controlle.php内で自由度が高い高度なプログラム処理をおこなってきています。

アップロード画像を正方形に切り抜く

function squarecut($image_dir,$image_name){ $_FILES['imageupload']['name'] = $image_name; $image_path=$image_dir.$image_name;//画像パス if(file_exists ($image_path)){ $imginfo = getimagesize($image_path);//画像情報 //画像データ取得 $image=$image_path; list($width, $height, $type, $attr) = getimagesize($image); if ($type == 2) { $img = ImageCreateFromJPEG($image); } elseif ($type == 1) { $img = ImageCreateFromGIF($image); } elseif ($type == 3) { $img = ImageCreateFromPNG($image); } //変更設定 //縦・正方形タイプ---flagで縦と横を入れ替える $new_width = $width; $new_height = $width; $set_width=$width; $set_heigh=$height; $shape_flag=""; $shape_data=$width-$height; //横-縦 if($shape_data==0){ $shape_flag='square'; //正方形 $x=0; $y=0; }elseif($shape_data<0){ $shape_flag='verticallylong'; //縦長 $x=0; $y=0; //(int)縦の長さ-横の長さ÷2がy座標ポイン x座標は0 $y=(int)($height-$width)/2; }else{ $shape_flag='oblong';//横長 $x=0; $y=0; //(int)横の長さ-縦の長さ÷2がx座標ポイント y座標は0 $x=(int)($width-$height)/2; //横長のみ変更 $set_width=$height; $set_heigh=$width; $new_width = $height; $new_height = $height; } //左上0~横幅分縦に切り抜き $newimg = imagecreatetruecolor($new_width,$new_height); $white = imagecolorallocate($newimg,255,255,255); imagefill($newimg, 0, 0, $white); //abs----float以外の返り値の型は integer となります $make_image=imagecopy ( $newimg //コピー先の画像リンクリソース ,$img //コピー元の画像リンクリソース ,0 //コピー先の x 座標(int) ,0 //コピー先の y 座標(int) ,$x //コピー元の x 座標(int) ,$y //コピー元の y 座標(int) ,$set_width //コピー元の幅(int) ,$set_heigh //コピー元の高さ(int)* ); //画像の保存 if ($type == 2) { imagejpeg($newimg,$image_path, 100); } elseif ($type == 1) { ImageGIF($newimg,$image_path); } elseif ($type == 3) { ImagePNG($newimg,$image_path); } imagedestroy($newimg); imagedestroy($img); return $newimg; } }

SQLコード例

$db = $this->getAdapter(); $db = Zend_Registry::get('dbAdapter'); try{ $sql .=" SELECT "; $sql .= "....."; $sql .= ".....";  $sql .= ".....";  $stmt= $db->query($sql); $result= $stmt->fetchAll(); }catch (Exception $e) { return false; } return $result;

phpでの動作テスト済


ヴァリデートやPOST処理なども、ZENDヘルパーを使わないことでデータの処理に高度な自由度を与えていますのでまだまだバグが発生する可能性はあります。
とりあえず、php8が推奨から非推奨に変わるまでは動作し続ける事でしょう。