tohokuaikiのチラシの裏

技術的ネタとか。

今更だけど、EthnaをPHP7にしてmysqliに対応した時のメモ

昔のコードのメンテナンスです(とか言ってみる

いい加減PHPも7になってEthnaはねーんじゃないの?って感じなのですが、これがまた意外と動くので使い続けたりしています。

ただ、preg_replaceのe修正子とmysql*系の関数が無くなったのでmysqli*に対応しないといけなくて、そのメモです。ちなみに、Ethna.phpをみると

/** バージョン定義 */
define('ETHNA_VERSION', '2.5.0-preview3');

とか書かれてたりします。

やらないといけないこと

  • preg_replaceのe修正子の削除
  • mysqliの適応
  • =&を=にする。(これは一括置換とか使って)

以下コードの羅列です。

etc/*****-ini.php

<?php
     'dsn' => 'mysql://user:pass@localhost/db_name',

 ↓

<?php
     'dsn' => 'mysqli://user:pass@localhost/db_name',

DB/Ethna_DB_PEAR.php

<?php

    function getInsertId()
    {
        if ($this->isValid() == false) {
            return null;
        } else if ($this->type == 'mysql') {
            return mysql_insert_id($this->db->connection);
        } else if ($this->type == 'sqlite') {


     function isValid()
     {
          if (is_null($this->db)
             || is_resource($this->db->connection) == false) {


    function quoteIdentifier($identifier)
    {
        if (is_array($identifier)) {
            foreach (array_keys($identifier) as $key) {
                $identifier[$key] = $this->quoteIdentifier($identifier[$key]);
            }
            return $identifier;
        }
            
        switch ($this->type) {
        case 'mysql':
            $ret = '`' . $identifier . '`';
            break;


    function &getMetaData($table)
    {
        $def =& $this->db->tableInfo($table);
            /** 中略 **/
            // flags
            $def[$k]['flags'] = explode(' ', $def[$k]['flags']);
            switch ($this->type) {
            case 'mysql':

 ↓

<?php

    function getInsertId()
    {
        if ($this->isValid() == false) {
            return null;
        } else if ($this->type == 'mysql') {
            return mysql_insert_id($this->db->connection);
        } else if ($this->type == 'mysqli') {
            return mysqli_insert_id($this->db->connection);
        } else if ($this->type == 'sqlite') {

     /* mysqli_connectはresourceではなく、Objectなので */
     function isValid()
     {
          if (is_null($this->db)
             || (is_object($this->db->connection) == false && is_resource($this->db->connection) == false)) {


    function quoteIdentifier($identifier)
    {
        if (is_array($identifier)) {
            foreach (array_keys($identifier) as $key) {
                $identifier[$key] = $this->quoteIdentifier($identifier[$key]);
            }
            return $identifier;
        }
            
        switch ($this->type) {
        case 'mysql':
        case 'mysqli':
            $ret = '`' . $identifier . '`';
            break;

    function &getMetaData($table)
    {
        $def =& $this->db->tableInfo($table);
            /** 中略 **/
            // flags
            $def[$k]['flags'] = explode(' ', $def[$k]['flags']);
            switch ($this->type) {
            case 'mysql':
            case 'mysqli':

preg_replaceのe修正子対応

Ethna_Controller.php

まとめて書く。

<?php
         $postfix = preg_replace('/_(.)/e', "strtoupper('\$1')", ucfirst($action_name));
         $action_name = substr(preg_replace('/([A-Z])/e', "'_' . strtolower('\$1')", $target), 1);
         $r = preg_replace('/_(.)/e', "'/' . strtoupper('\$1')", ucfirst($action_name)) . '.' . $this->getExt('php');
         $postfix = preg_replace('/_(.)/e', "strtoupper('\$1')", ucfirst($forward_name));
         $r = preg_replace('/_(.)/e', "'/' . strtoupper('\$1')", ucfirst($forward_name)) . '.' . $this->getExt('php');

 ↓

<?php
         $postfix = preg_replace_callback('/_(.)/', function($m){ return strtoupper($m[1]);}, ucfirst($action_name));
         $action_name = substr(preg_replace_callback('/([A-Z])/', function($m){ return '_' . strtolower($m[1]);}, $target), 1);
         $r = preg_replace_callback('/_(.)/', function($m){ return '/' . strtoupper($m[1]); }, ucfirst($action_name)) . '.' . $this->getExt('php');
         $postfix = preg_replace_callback('/_(.)/', function($m){ return strtoupper($m[1]); }, ucfirst($forward_name));
         $r = preg_replace_callback('/_(.)/', function($m){ return '/' . strtoupper($m[1]); }, ucfirst($forward_name)). '.' . $this->getExt('php');
<?php
        $name = preg_replace('/_(.)/e', "strtoupper('\$1')", ucfirst($name));

 ↓

<?php
        if (preg_match_all('/_(.)/', ucfirst($name), $m)){
            foreach ($m[1] as &$v) $v = strtoupper($v);
            $name = str_replace($m[0], $m[1], ucfirst($name));
        }

Plugin/Cachemanager/Ethna_Plugin_Cachemanager_Localfile.php

<?php
    function _escape($string)
    {
        return preg_replace('/([^0-9A-Za-z_])/e', "sprintf('%%%02X', ord('\$1'))", $string);
    }

 ↓

<?php
    function _escape($string)
    {
        return preg_replace_callback('/([^0-9A-Za-z_])/', function($m){
            return sprintf('%%%02X', ord($m[1]));
        }, $string);
    }

Ethna_MailSender.php

<?php
                 $part['name'] = preg_replace('/([^\x00-\x7f]+)/e',
                     "Ethna_Util::encode_MIME('$1')", $part['name']); // XXX: rfc2231
                 $part['filename'] = preg_replace('/([^\x00-\x7f]+)/e',
                     "Ethna_Util::encode_MIME('$1')", $part['filename']);
              /* ... */
              $header[$i][] = preg_replace('/([^\x00-\x7f]+)/e', "Ethna_Util::encode_MIME('$1')", $value);

 ↓

<?php
                 if (preg_match_all('/([^\x00-\x7f]+)/', $part['name'], $m)){
                     foreach ($m[1] as &$v) $v = Ethna_Util::encode_MIME($v);
                     $part['name'] = str_replace($m[0], $m[1], $part['name']);
                 }
                 if (preg_match_all('/([^\x00-\x7f]+)/', $part['filename'], $m)){
                     foreach ($m[1] as &$v) $v = Ethna_Util::encode_MIME($v);
                     $part['filename'] = str_replace($m[0], $m[1], $part['filename']);
                 }
              /* ... */
              $header[$i][] = preg_replace_callback('/([^\x00-\x7f]+)/',function($m){ return Ethna_Util::encode_MIME($m[1]); }, $value);

Ethna_AppObject.php

<?php
         $table = preg_replace('/^([A-Z])/e', "strtolower('\$1')", $table);
         $table = preg_replace('/([A-Z])/e', "'_' . strtolower('\$1')", $table);

 ↓

<?php
         if (preg_match_all('/^([A-Z])/', $table, $m)){
             foreach ($m[1] as &$v) $v = strtolower($v);
             $table = str_replace($m[0], $m[1], $table);
         }
         if (preg_match_all('/([A-Z])/', $table, $m)){
             foreach ($m[1] as &$v) $v = "_" . strtolower($v);
             $table = str_replace($m[0], $m[1], $table);
         }

=& newをつぶす

find lib app -name "*php"|xargs -I{} sed -i -e "s/ = &new/ = new/" {}
find lib app -name "*php"|xargs -I{} sed -i -e "s/ =& new/ = new/" {}