Tag: php


PHPのメモ


色々

defineの文字列、ヒアドキュメント内での展開

 PHPでは、defineで定義した定数のようなものを文字列内で展開して使うことが出来ない。1つ変数を間に挟めばプログラム自体は書けると思うが、沢山あるとちょっと大変。その場合はラムダ関数を定義することで余計な変数を増やさずに目的を達成することが出来るそうです。(2021-03-05)

  • サンプル
    <?php
    define("aaa","123456789");
    $D_ = function($s){return $s;}; 
    print "{$D_(aaa)}";
    print "\n";
    print <<<EOT
    test : {$D_(aaa)}
    EOT;
  • サンプルの実行結果
    123456789
    test : 123456789


5.3.xと7.x.xの配列関係の表記について

7.x.xだと許可される書き方

$hairetu = [ ["山田",123], ["佐藤",222],["渡辺",789]];

[$x, $y] = 配列を返す関数();

5.3.xだと以下などのようにする

$hairetu = array( array("山田",123), array("佐藤",222), array("渡辺",789));

list($x, $y) = 配列を返す関数();


デバッグ

 エラー表示が、セキュリティホールを知る手がかりなどになることから、致命的なエラーでない場合にPHPの初期設定ではエラーが発生した場合に、画面が真っ白になります。プログラムミスを修正する際には、エラーや警告表示が参考になりますので、必要に応じて表示のする/しないを切り替えると良いです。
 プログラム開発中は、以下などとし、

ini_set( 'display_errors', 1);
error_reporting(E_ALL);

実働段階では、次などとする事が多いかな。

ini_set( 'display_errors', 0);
error_reporting(0);


エラー表示の指定

  • PHPスクリプトの中で表示設定にする。
ini_set( 'display_errors', 1 );

参照: https://www.php.net/manual/ja/errorfunc.configuration.php#ini.display-errors


エラー表示レベルの指定

  • エラー、警告・・・などどの段階の表示を行うか指定する
error_reporting(E_ALL);

以下も同様

ini_set('error_reporting', E_ALL);

E_ALLにすると、未定義の変数への代入なども対象となりますが、プログラム作成時は、細かくチェックし、運用時には致命的なエラーのみ表示とする事が多い。

参照: https://www.php.net/manual/ja/function.error-reporting.php




テキストファイルの扱い

SplFileObject で CSVの読み込みテスト

  • テストコード
    <?php
     
    // SplFileObject で CSVの読み込みテスト
    //
    // ※PHPは、5.1.x以上
     
    // 参考
    //     http://scene-live.com/page.php?page=9
    //     http://php.net/manual/ja/class.splfileobject.php
    //     http://qiita.com/suin/items/31a1c7c47f49cb53f2a7
    //     http://php.net/manual/ja/splfileobject.setcsvcontrol.php
     
        // ファイル取得
     
        $filepath = "testfile.csv";
        $file = new SplFileObject($filepath); 
        $file->setFlags(SplFileObject::READ_CSV);
        //$file->setCsvControl(",",'"');    // 初期値
        $file->setCsvControl("\t",'"');    // タブ区切りの場合
        
        // ファイル内のデータループ
        foreach ($file as $key => $line) {
            $oneLine = "";
            $r=0;
            foreach( $line as $str ){
                if ($oneLine != "") {
                    $oneLine .= "\t";
                }
                //$records[ $key ][] = $str ;
                $oneLine .= $str;
                $r++;
                if ($r>3) { break; }
            }
            print $oneLine."\n";
        }
     
    ?>


CSVから5行目のみを取得して変数に値を格納

コードは一部です。アップロードした数100行程のCSVファイルで先頭の10行をサンプルとしてtextareaタグで表示。その後、5行目のみ1行をデータの取り込み設定で表示する為に、変数に格納。

<?php     $h = "";    // HTMLを予め作成しておいてあとでprintする為の変数
    // アップロードしたファイルの先頭の10行をサンプルとして表示する
    $filepath = $uploadTempName;
    $file = new SplFileObject($filepath);
    $l=1;
    $textSample = "";
    while (!$file->eof() && $l<11) {
        $textSample .= $file->fgets();
        $l++;
    }
 
    $h .= "参考:ファイルの先頭10行<br>\n";
    $h .= "<textarea style='width:90%;height:11em;'>{$textSample}</textarea><br>\n";
 
    // フィールドの設定
    // アップロードデータの1行目をフィールド取り込みの選択表示に使うので取得
    $file->rewind();
    $file->setFlags(SplFileObject::READ_CSV);
    $csvS = $fieldSeparator == "canma" ? "," : ",";        // デバッグ中
    $csvQ = $fieldQuotor == "double" ? '"' : '"';    // デバッグ中
    $file->setCsvControl($csvS,$csvQ);
    $file->seek(5);
    $csv1 = $file->current();
 ?>


$file->rewind();

ファイルの先頭からデータを読み込むためにファイルポインタを先頭にセットし直す。

$file->seek(4);

ファイルの5行目にファイルポインタを移動します。0から始まる。SplFileObject::READ_CSVでCSVを読み込む事を指定しておく。

$csv1 = $file->current();

現在ファイルポインタのある1行を読み込み。$csv1へ格納する。CSV読み込み設定しているので、フィールドに分割して$csv1[0]から$csv1[1]…と格納される。


利用終了後のオブジェクト開放

$file = null;

利用終了後に速やかにオブジェクトを開放するには、上記の様にしたほうが良いと以下のWEBに解説あり。これをしないとその後にファイルの削除でファイルが使用中と判断され出来ない事がある。

http://php.net/manual/ja/class.splfileobject.php




文字列

全角の英数字が半角に変換されない

$str = mb_convert_kana($str, "a");

の結果、全角の英数字が半角に変換されない場合は、$strの文字コードの自動判別が正常に出来てない事が考えれます。次の様に明示すると目的の結果が得られる事があります。

$str = mb_convert_kana($str, "a","UTF-8");




メモリ利用について

WEBのプログラムのメモリエラー

Fatal error: Allowed memory size of 134217728 bytes exhausted
(tried to allocate 97 bytes) in /home/hogehoge/public_html/sample.php
on line 1234

WEBのプログラムを実行しブラウザで上記のようなエラーが表示される場合、問題になるプログラム(PHPスクリプト)の冒頭で以下の様にすると、変数等で利用出来るメモリの要領を変更することが出来る事がある。ただし、プログラムを見直して無駄がない事を確認の上で変更することが望ましい。

ini_set('memory_limit', '128');




jQuery関係

テーブルTABLEタグ関係のJQueryプラグインを使う時のetc

 PostgreSQLのpsqlコマンドで結果をHTML出力した際に、表示にJQueryのプラグインを使うためのちょっとした加工。何をするかというと、1行目の見出し部分を「<thead>」と「</thead>」で囲みます。また使ってみようと思っているプラグインは、fixed Table Header です。

<table border="1">
  <tr>
    <th align="center">列1</th>
    <th align="center">列2</th>
    <th align="center">列3</th>
    <th align="center">列4</th>
    <th align="center">列5</th>
    <th align="center">列6</th>
    <th align="center">列7</th>
    <th align="center">列8</th>
    <th align="center">列9</th>
  </tr>
  <tr valign="top">
    <td align="left">データ1</td>
    <td align="left">データ2</td>
    <td align="left">データ3</td>
    <td align="left">データ4</td>
    <td align="left">データ5</td>
    <td align="right">データ6</td>
    <td align="left">データ7</td>
    <td align="left">データ8</td>
    <td align="left">データ9</td>
  </tr>
  <tr valign="top">
    <td align="left">データ1</td>
    <td align="left">データ2</td>
    <td align="left">データ3</td>
    <td align="left">データ4</td>
    <td align="left">データ5</td>
    <td align="right">データ6</td>
    <td align="left">データ7</td>
    <td align="left">データ8</td>
    <td align="left">データ9</td>
  </tr>
 
<!-- 中略 -->
 
</table>
<p>(25 rows)<br />
</p>

を次の様にします。

<table border="1">
  <thead>
  <tr>
    <th align="center">列1</th>
    <th align="center">列2</th>
    <th align="center">列3</th>
    <th align="center">列4</th>
    <th align="center">列5</th>
    <th align="center">列6</th>
    <th align="center">列7</th>
    <th align="center">列8</th>
    <th align="center">列9</th>
  </tr>
  </thead>
 
  <tr valign="top">
    <td align="left">データ1</td>
    <td align="left">データ2</td>
    <td align="left">データ3</td>
    <td align="left">データ4</td>
    <td align="left">データ5</td>
    <td align="right">データ6</td>
    <td align="left">データ7</td>
    <td align="left">データ8</td>
    <td align="left">データ9</td>
  </tr>
  <tr valign="top">
    <td align="left">データ1</td>
    <td align="left">データ2</td>
    <td align="left">データ3</td>
    <td align="left">データ4</td>
    <td align="left">データ5</td>
    <td align="right">データ6</td>
    <td align="left">データ7</td>
    <td align="left">データ8</td>
    <td align="left">データ9</td>
  </tr>
 
<!-- 中略 -->
 
</table>
<p>(25 rows)<br />
</p>


テストスクリプト

<?php
$b =<<<EOHTML
<table border="1">
  <tr>
    <th align="center">列1</th>
    <th align="center">列2</th>
    <th align="center">列3</th>
    <th align="center">列4</th>
    <th align="center">列5</th>
    <th align="center">列6</th>
    <th align="center">列7</th>
    <th align="center">列8</th>
    <th align="center">列9</th>
  </tr>
  <tr valign="top">
    <td align="left">データ1</td>
    <td align="left">データ2</td>
    <td align="left">データ3</td>
    <td align="left">データ4</td>
    <td align="left">データ5</td>
    <td align="right">データ6</td>
    <td align="left">データ7</td>
    <td align="left">データ8</td>
    <td align="left">データ9</td>
  </tr>
  <tr valign="top">
    <td align="left">データ1</td>
    <td align="left">データ2</td>
    <td align="left">データ3</td>
    <td align="left">データ4</td>
    <td align="left">データ5</td>
    <td align="right">データ6</td>
    <td align="left">データ7</td>
    <td align="left">データ8</td>
    <td align="left">データ9</td>
  </tr>
 
<!-- 中略 -->
 
</table>
<p>(25 rows)<br />
</p>
EOHTML;
 
$b2 = preg_replace("/(<tr>.+?<th )/sm","<thead>\n  $1", $b);
$b3 = preg_replace("/(<\/th>.+?<\/tr>)/sm","$1\n  </thead>\n", $b2);
 
print $b3;

正規表現の以下の部分がポイントです。

$b2 = preg_replace("/(<tr>.+?<th )/sm","<thead>\n  $1", $b);
$b3 = preg_replace("/(<\/th>.+?<\/tr>)/sm","$1\n  </thead>\n", $b2);

2017-02-27




気になるライブラリ等

phpQuery

  • WEBスクレイピング


PHPExcel




日付関係

24時を翌日の0時に・・・

  • 2018-11-12

 strtotimeは24時もエラーにはならないで処理してくれる。date関数で表示フォーマットを指定すれば、翌日の0時になる。

print date("Y-m-d H:i", strtotime("2018-11-11 24:00"));

結果は、以下の様になります。

2018-11-12 00:00

しめしめと思って、25時も変換可能かと思って以下を実行すると

print date("Y-m-d H:i", strtotime("2018-11-11 25:00"));

結果は、予想に反して以下の様になりました。

1970-01-01 09:00


うるう年2月29日の1年前

strtotimeでは、2020年2月29日の1年前は2019年3月1日。そして、2020年3月1日は2019年3月1日でした。(2020-08-25)

<?php
 
$date1 = "2020/02/29";
 
#$date2 = date("Y-m-d", strtotime($date1) - 60*60*24*365);
$date2 = date("Y/m/d", strtotime($date1." -1 year"));
 
print $date2 ." - ". $date1;
 
 
// 2020/02/29 - 2019/03/01




PHP7からPHP8への変更について

  • 7から8へは多くの互換性のない変更があります。プログラムの記述方法によってはエラーが出てちょっとやそっとでは実行出来ないPHPのプログラム出てきます。

参考URL