カテゴリーアーカイブ PHP

著者:杉浦

PHPの標準勧告提案PSR

PHPの標準勧告提案PSR
 PHP Standards Recommendations – PHP-FIG
PSRはPHPのコードはこのように作るべきだと推奨する提案の一つです。PSRはPHP-FIG — PHP Framework Interop Group – PHP-FIGによって策定されています。PHP-FIGはPHP Framework Interop Groupとある通り、複数あるPHPフレームワークの各関係者の集団です。その影響力は強く、いくつものフレームワークを始めとして多くのコードがPSRに準拠したコードになっています。
 現在、承認済みのPSRは次の表の通りです。

Accepted

Num Title Editor Coordinator Sponsor
1 Basic Coding Standard Paul M. Jones N/A N/A
2 Coding Style Guide Paul M. Jones N/A N/A
3 Logger Interface Jordi Boggiano N/A N/A
4 Autoloading Standard Paul M. Jones Phil Sturgeon Larry Garfield
6 Caching Interface Larry Garfield Paul Dragoonis Robert Hafner
7 HTTP Message Interface Matthew Weier O’Phinney Beau Simensen Paul M. Jones
11 Container Interface Matthieu Napoli, David Négrier Matthew Weier O’Phinney Korvin Szanto
13 Hypermedia Links Larry Garfield Matthew Weier O’Phinney Marc Alexander
15 HTTP Handlers Woody Gilk N/A Matthew Weier O’Phinney
16 Simple Cache Paul Dragoonis Jordi Boggiano Fabien Potencier
17 HTTP Factories Woody Gilk N/A Matthew Weier O’Phinney

 この中で特に多くの出番があるのはPSR-2、コーディング規約です。インデントはスペース4個、一行はできるだけ80文字以内に最大でも120文字以内、クラス、メソッドの開き括弧は次の行、などなどコードのスタイルについての規約が羅列されています。日本語訳も既にいくつかあります。PSR-2 コーディングガイド(日本語)|北海道札幌市のシステム開発会社インフィニットループ
【PSR】PHPの標準コーディング規約 – Qiita
【PHP】PSR-2 Coding Style Guide(コーディングスタイルガイド)
 チェックツールにはphp_codesniffer、修正ツールには php-cs-fixerなどがあります。

  • この記事いいね! (1)
村上 著者:村上

【PHP】FireBase Cloud Messagingを利用したプッシュ通知をPHPから送る方法

今日は、FireBase Cloud Messaging を利用したプッシュ通知を PHP から送付する方法についてです。
思ったより簡単に実装できたので、自分の備忘録(または困ったときのコピー元)としてまとめました。
なお、こちらは送信方法のみです。
FireBaseのアカウント作成等は飛ばしておりますので、その点はご了承ください。

今回参考にさせていただいた記事はこちらから。

WebAPIを叩く(curl) – Qiita
https://qiita.com/re-24/items/bfdd533e5dacecd21a7a

WebAPIの実行には、curl を使用しています。

 

早速ですが、コードはこちら。

$token = '[firebaseのトークン]';
$base_url = 'https://fcm.googleapis.com/fcm/send';

$data = array(
  "to" => "[送付先のデバイストークン]",
  "priority" => "high",
  "notification" => array(
    "title" => "[タイトル]",
    "body"  => "[メッセージ]",
    "sound" => "default",
    "click_action" => "FCM_PLUGIN_ACTIVITY"
  )
);

$header = array(
  'Authorization: key='.$token,
  'Content-Type: application/json'
);

$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $base_url);
curl_setopt($curl, CURLOPT_CUSTOMREQUEST, 'POST'); // post
curl_setopt($curl, CURLOPT_POSTFIELDS, json_encode($data)); // jsonデータを送信
curl_setopt($curl, CURLOPT_HTTPHEADER, $header); // リクエストにヘッダーを含める
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
curl_setopt($curl, CURLOPT_HEADER, true);

$response = curl_exec($curl);

$header_size = curl_getinfo($curl, CURLINFO_HEADER_SIZE); 
$header = substr($response, 0, $header_size);
$body = substr($response, $header_size);
$result = json_decode($body, true); 

curl_close($curl);

接続先だったり、送付するデータを変更しただけで、ほぼ参考にさせていただいた記事に書かれていたコードそのままです。
変数 $data 内に指定しているデータは、通知の内容によって変更してください。
FCMの詳細については、下記の公式サイトのガイドを参考にしてください。

Firebase Cloud Messaging|FireBase
https://firebase.google.com/docs/cloud-messaging/?hl=ja

 

以上、FireBase Cloud Messaging で プッシュ通知をPHPで送信する方法でした。
他の WebAPI を PHP で実行するときにも使えますので、参考にしていただければと思います。

  • この記事いいね! (0)
村上 著者:村上

【PHP】XMLファイルのエラー「Parse error: syntax error, unexpected T_STRING」の対処法

今日は、XMLを扱ったときに遭遇したエラーについて。
エラーの全文はこちら。

Parse error: syntax error, unexpected T_STRING in [ファイル名] on line 1.

「予期しないT_STRING がある」というシンタックスエラーです。
シンタックスエラー=構文エラーということでしたが、参考にしたサンプルと見比べても、間違いはないし…何故?と少しだけ焦りました。
そもそも、xml ファイルを開いているのに、何故 PHP のエラーが発生するのかも最初は分かりませんでした。

 

こちらのエラーは、原因としては下記の1行目が、PHP と誤認識されるために発生するエラーとのことでした。

<?xml version="1.0" encoding="utf-8"?>

確かに、PHPって <?php ~処理~ ?> だけでなく、省略形として <? ~処理~ ?> とも書けましたね…。

こちらの誤認識を防ぐために、下記のように、PHPの echo を使って1行目を記述すると、問題なく動作するとのことでした。

<?php echo '<?xml version="1.0" encoding="utf-8"?>'; ?>

試したところ、確かに問題なく動作しました!

他にも、.htaccess に「AddType text/html .html」もしくは「php_flag short_open_tag Off」を追加するという方法もあるようでしたが、対処が簡単だったこちらの方法を採用しました。

ちなみに、今回参考にさせていただいたサイトはこちらから。

「syntax error, unexpected ‘version’・・・」 エラーの対処方法 – Project Group
https://www.projectgroup.info/tips/php/comm_0004.html

 

以上、XMLファイルが正常に読み込めない・開けない時の対処法でした。
思ったよりもあっさり解決できたので良かったです。
もし同じところで躓いていらっしゃる方がいましたら、参考にしていただければと思います。

  • この記事いいね! (0)
takahashi 著者:takahashi

nginxやAmazon ALBなどのロードバランサー経由でLaravelにアクセスさせたときにHTTP/HTTPSを振り分ける方法

nginxやロードバランサーなどを使ってWebサーバーにアクセスさせた際に困るのが、一部の情報が本体のWebサーバーまで到達しない点。
特に、クライアントがHTTPでアクセスしているのか、HTTPSでアクセスしているのか、などの情報はそのままの状態で取得するのは困難です。

こういった環境と、HTTPかHTTPSどちらで接続されているのかを判定したうえでDOMのURLを書き換えるタイプの機能を持つフレームワークやプログラムとの相性は特に最悪で、Webサーバーに対してHTTPでアクセスされた時点で”クライアントからHTTPでアクセスされている”と判定して、すべてのアセットのアドレスをhttp://から始まるURLに置き換えて返してしまい、結果jsやcssが読み込めずに表示崩れや不具合になってしまうことがあります。

最近人気のLaravelもこの機構を持っており、そのままの状態でnginxやLBを間に置いてしまうと、httpsでアクセスしたときにページが正常に表示されない問題が発生してしまいます。

幸いにも、HTTPSかどうかの部分についてnginxやロードバランサーが代わりに取得し、その情報をヘッダーに含めて投げてくれる場合が多いので、今回はLaravel上でこのヘッダ情報を使って簡単にHTTP/HTTPSを判定できるようにしてみました。

Laravelプロジェクトフォルダ内の
routes/web.php
の最初あたりに、次のコードを追加します。

<?php

/*
|--------------------------------------------------------------------------
| Web Routes
|--------------------------------------------------------------------------
|
| Here is where you can register web routes for your application. These
| routes are loaded by the RouteServiceProvider within a group which
| contains the "web" middleware group. Now create something great!
|
*/

//ここから
//リバースプロキシ経由のHTTP/HTTPS判定
if(!empty($_SERVER["HTTP_X_FOWARDED_PROTO"])){ //"HTTP_X_FOWARDED_PROTO"ヘッダーが存在していたら
    if(strtoupper($_SERVER["HTTP_X_FOWARDED_PROTO"]) == "HTTP"){ //strtoupper("HTTP_X_FOWARDED_PROTO")の中身が"HTTP"だったら
        URL::forceScheme('http'); //すべてのURLをhttpに書き換える
    } else {
        URL::forceScheme('https'); //すべてのURLをhttpsに書き換える
    }
}
//ここまで

$_SERVERはPHPにおいて、サーバー情報および実行時の環境情報がすべて格納されるスーパーグローバル変数です。

$_SERVER – php.net

この中に、リクエストヘッダの中身もすべて格納されるので、その中からnginxやAmazon ALBやClassic Load BalancerがHTTP/HTTPSの情報を格納する”X_FOWARDED_PROTO”ヘッダーを参照して、どちらでアクセスされたかを判定しています。

ifを敢えてHTTPかどうかで判定している理由は万が一、”$_SERVER[“HTTP_X_FOWARDED_PROTO”]”にhttpでもhttpsでもない不正な値が入っていた場合も、とりあえずhttps://で吐き出すようにするためです。

こんな形で処理を加えてやれば、Laravelでもnginxやロードバランサーを使用していても正常にHTTPとHTTPSの切り替えが行えるようになると思います。

少しでも参考になりましたらしたら幸いです。

  • この記事いいね! (0)
takahashi 著者:takahashi

Laravelの設定ファイルがわかりづらい。

最近Laravelを触り始めた、Laravel初心者です。

fuelPHPなどのフレームワークはconfig周りをまとめたフォルダがあり、Laravelにもドキュメントルート下にconfigというフォルダがあり、

DOCROOT/config/database.php

を書き換えればデータベースに接続できるものだと思っていました。
ところが、database.phpの情報を書き換えた後、

php artisan migrate --seed

を実行したところ、Connection refusedエラーが。
確認したところ、実際にプログラムに渡されている値がdatabase.phpで定義されているものではなく、規定値のままになっていることがわかりました。

更にいろいろ調べたところ、Laravelでは下記の操作が必要であることがわかりました。

・ドキュメントルート直下の .env.example を .env にリネームする。
・.env内にもDB接続先の指定があるため、その項目を書き換える。
・php artisan config:cache コマンドを実行して、設定のキャッシュを作り直す

今回の場合、この手順でデータベースの接続先設定を書き換えることができました。

一方、configフォルダの方の設定はどのように使用するのか、まだ調べ中です。

正直、個人的に2箇所に設定ファイルが存在しているのはちょっとわかりづらい気がするのですが、どうなんでしょう…

  • この記事いいね! (0)
著者:杉浦

PHPのコメント形式のPHPDoc

phpDocumentor
PHPDoc reference — phpDocumentor
PHPDoc リファレンス — phpDocumentor
 PHPDocはphpには関数を表すためのコメントの形式として用意されているフォーマットです。PHPDocの形式に対応したコメントはIDEの様な多機能エディタでPHPファイルを編集する際に、読みやすい形になって出力されます。例えば次の様になります。

 関数の説明、引数の型と名前と説明、返り値の型と説明、どのファイルから呼ばれているかが整理されて記述されています。リンクを埋め込むこともできます。下図の様に、関数を呼び出すところでも同じ説明を出力できます。

 エディタによっては下図の様にPHPDocで指定された型と引数の型が異なる場合、警告を出力してくれます。
 
 PHPDocと認識されるフォーマットは次の様に/**と*/で括られ、各行頭に任意の数の空白文字と*がついたフォーマットです。

/**
 *
 */

 この中に説明と@から始まるタグを入れることで肉付けします。ここまでに上げた画像の様に関数に対してPHPDocを記述する場合、まず必要なのは@paramと@returnでしょう。それぞれ引数と返り値の説明です。関数内部の動作が正しいと仮定した場合、中身を読む必要はありません。適切な説明と引数、返り値がわかればそれだけで十分です。組み込み関数と同じですね。@paramと@returnの形式は

@param [型] 変数名 説明
@return [型] 説明

で、半角スペースは任意の空白です。ここまでの形式に従って、例えば次の様に記述します。

/**
 * 緯度経度を平面座標(測地座標)に変換
 * @link http://landhere.jp/docs/gis_phplib.html 引用元:地理情報関連 PHPライブラリ - LANDHER
 * @link https://vldb.gsi.go.jp/sokuchi/surveycalc/surveycalc/algorithm/bl2xy/bl2xy.htm 検証元:平面直角座標への換算 計算式
 *
 * @param int $K 19座標系の系番号
 * @param float $Lp 経度の度点
 * @param float $bp 緯度の度点
 * @return float[] array形式のXY座標
 */

 詳しい記述できるタグ、型は冒頭のリファレンスにあります。

  • この記事いいね! (0)
著者:杉浦

簡単な置換を簡単に書く

 置換と言えば正規表現ですが、正規表現の処理は複雑です。複雑さ同様、正規表現による置換は往々にして純粋な文字列のみの置換より重くなりがちです。PHP: str_replace – Manual にも

(正規表現のような) 技巧的な置換ルールを必要としない場合、 preg_replace() の代わりにこの関数を常用するべきです。

とあります。
 この技巧的な置換ルールを必要としない置換でよく行いたい置換は、AをB,CをDに置き換える、といった1対1の置換です。複数の置換の記述例は次の通りです。

$str = '置換対象';
$arr = [
	'置換' => 'ちかん',
	'対象' => 'taisyou'
];
$str_replaced = str_replace( array_keys($arr), array_values($arr), $str);

 上の書き方で$str中の’置換’を’ちかん’、対象を’taisyou’に置き換えた$str_replacedができあがります。
 str_replace,preg_replaceは引数の置き換え対象のパターン、置き換え後の語に配列を指定できます。またarray_keysは引数の配列のキーを格納した配列を、array_valuesは引数の配列の値を、配列にして返します。これらを組み合わせることで、置換対象と置換後の文字列を一つの配列内に格納できます。延々と同じ変数を対象にreplaceを繰り返すよりすっきりします。
 実行速度もこちらの書き方の方が高速です。私の環境では、aをaaに置換するという動作を’a’に対して100000回繰り返す動作にかかる実行時間はstr_replaceの重ね書きがおおよそ1*1e-3秒、上記の書き方が7*1e-6秒でした。雑な計り方ですが、ここまで極端な差があるので高速と言っていいでしょう。
 余談な上、勘ですがこの速度差はおそらく関数呼び出しによるオーバーヘッドです。計算コストの異なりそうな違いはstr_replaceの呼び出し回数、文字列変数をどこに保存するかの扱い、あたりにあります。

  • この記事いいね! (0)
著者:杉浦

assertで想定外の動作のみを検知する

 デバッグを行う際、プログラム中の変数、式を追うことになります。この変数や式を全て画面に出力すると読む対象が多すぎてとても分かりにくいです。また徐々に異常な結果を辿って、変数や式をその都度画面に出力する場合、実行回数がかさみ時間がかかってしまいます。assert文は異常を発見した時にのみ知りたい変数や式を出力させるための文です。またこのassert文はユーザに見せる本番環境の際には消えている必要があります。assert文の実行は実行速度の低下であり、assert文の出力は脆弱性の発見のきっかけにもなります。
 大体のassert文はassert(条件文,出力定義の色々)という呼び出され方をします。条件文の評価結果がtrueの場合、出力はされず、falseの場合、出力がされます。assert(想定の動作の際の条件文, Errorの際に知ると役に立つであろう値)と書くと想定外の動作を整った情報と共に検出し、早く修正できます。かくあるべし、と意味を書く際のコメントの代わりにもなります。
Console.assert() – Web API インターフェイス | MDN
 javascriptのassetは次の様に使えます。

console.assert(条件式,出力したいものA,出力したいものB,出力したいものC,...)

 出力は次の画像のconsole.log(出力したいもの)と同じ様に表示されます。  javascritptでは外部でどうにかすることでassertを見せないようにします。一つは力技の様な気がしますが

Object.keys(console).forEach(key => {console[key] = () => {}})

の実行です。これによってブラウザの持つconsoleオブジェクトの持つ要素を全て空の関数で埋めます。これならば結果は表示せず、実行速度の面でもconsoleなしより少々遅いぐらいで済みます。ただしユーザはconsoleを使うためにconsoleの再定義が必要になり、また再定義された場合、consoleの中身が表示されてしまいます。もう一つはbabel-plugin-transform-remove-console – npmをつけたbabelのようなconsoleを除去するコンパイラを通すことによってコード内からassert文を消すことです。javascriptの実行コードはユーザがダウンロードするファイルです。そのため高速化を目的にソースコードを結合、圧縮します。その時にまとめてassertの除去を実行することで手間を意識せずassertを消せます。

PHP: assert – Manual
 PHPのassertは7前後で異なっています。PHP7では次のように簡単に書けます。

<?php
$a = 2;
$b = 1;
// assertionを作成
assert($a < $b);
assert($b < $a, '$b is less than $a.$a:'.$a.' $b:'.$b);
assert($a < $b, '$a is less than $b.$a:'.$a.' $b:'.$b);

実行結果

<br />
<b>Warning</b>:  assert(): assert($a &lt; $b) failed in <b>[...][...]</b> on line <b>5</b><br />
<br />
<b>Warning</b>:  assert(): $a is less than $b.$a:2 $b:1 failed in <b>[...][...]</b> on line <b>7</b><br />

 assert(条件式,出力文字列)とするだけです。出力文字列とassert文を記述した行数を出力してくれます。出力文字列を指定しない場合はfalseを出力した条件文を出力します。
 PHP7より前のバージョンではコールバックの指定が必要であり少々面倒です。

<?php
// assertを有効にし、出力を抑制する
assert_options(ASSERT_ACTIVE, 1);//assert()による評価を有効にする。0でassert()を読み飛ばす。
assert_options(ASSERT_WARNING, 0);
assert_options(ASSERT_QUIET_EVAL, 1);

// ハンドラ関数を作成する
function my_assert_handler($file, $line, $code, $desc = null)
{
    echo "Assertion failed at $file:$line: $code";
    if ($desc) {
        echo ": $desc";
    }
    echo "\n";
}

// コールバックを設定する
assert_options(ASSERT_CALLBACK, 'my_assert_handler');

// 失敗するassertionを作成
assert('2 < 1');
assert('2 < 1', 'Two is less than one');

実行結果

Assertion failed at [...][...]:21: 2 < 1
Assertion failed at [...][...]:22: 2 < 1: Two is less than one

 PHP7より前では必ず評価を行った状態を引数にしたコールバックを呼び出します。これが手間で昔のassert文はあまり使われなかったらしいです。PHP7はコールバック呼び出しも可能なまま、容易に使えるasset文になりました。
 PHPはオプションで宣言することによってassert文を読み飛ばします。PHP7ではphp.ini中にzend.assertions=-1とすることでassert文を読み飛ばせます。PHP7より前ではassert_options(ASSERT_ACTIVE, 0);とすることでassertによる評価を無効にします。

  • この記事いいね! (0)
著者:杉浦

php用パッケージマネージャcomposer

   ______
  / ____/___  ____ ___  ____  ____  ________  _____
 / /   / __ \/ __ `__ \/ __ \/ __ \/ ___/ _ \/ ___/
/ /___/ /_/ / / / / / / /_/ / /_/ (__  )  __/ /
\____/\____/_/ /_/ /_/ .___/\____/____/\___/_/
                    /_/

 ComposerはPHPのパッケージ管理ツールです。必要なライブラリやフレームワークをまとめます。またphp向けのアプリケーションを管理する事もしてくれます。使っていてphp版npmみたいに思っていましたが、製作者はnpmに強い影響を受けたとあります。納得。
 パッケージのリポジトリはPackagistです。ここと雑多な記事のおすすめで目的に合ったもの、欲しいものを探します。
 フレームワークならLaravel、テスト用環境ならphpunitあたりが高評価なようです。

  • この記事いいね! (0)
著者:杉浦

webページ評価ツールLighthouse

 Lighthouse – Chrome ウェブストア
 Lighthouse によるウェブアプリの監査 | Tools for Web Developers
| Google Developers

 Lighthouseはwebページの評価を行ってくれるツールです。お手軽な使い方は上記リンクのウェブストアからChrome拡張機能としてのLighthouseを導入し使用することです。オプションもコマンドも必要なく、ただ起動するだけで監査を行い、結果を出力します。 Lighthouseの評価は下図の様にPerformance,ProgressiveWebApp,Accessibility,Best Practices,SEOに分かれています。

 それぞれ、Performanceはおおよそ速度、データ量関連に問題が無いか、ProgressiveWebAppはネイティブアプリのようにふるまえるか、Accessibilityはわかりやすさ、Best Practicesは良いとされるやり方をしているか、SEOは検索エンジン最適化がされているか、です。画像の更に下の方には細分化された指摘がいくつもあります。
 Lighthauseの特徴は、googleが奨励しているPWAとしての評価がgoogle自身の規定でできる、という点です。またSEOは大概眉唾物ですが検索エンジン大手のgoogleが提供するツールが評価するSEOですから多少は当てになるでしょう。
 これが高得点ならばよいwebページというわけはないです。PWAは特に顕著でアプリである必要のないページは多々あります。基本的にぱっと見の第一印象がどうか、という点から評価がなされます。ただ高得点のページならば低得点のページよりも快適に使用しやすいのではないでしょうか。
 また、Lighthouseの指摘により今まで知らなかったより良いやり方を知ることもできます。

  • この記事いいね! (0)