- 投稿日:2019-07-10T13:57:15+09:00
php-master-changes 2019-07-09
今日は VM のコード修正、ドキュメントの更新、SQLite の 3.28.0 への更新、Symfony で影響が出ていた修正のリバート、メモリリークの修正があった!
PHP 7.4.0alpha3 がそろそろ出そう、次は beta1。2019-07-09
dstogov: Fixed dispatch from inlined hybrid opcode to another opcode
- https://github.com/php/php-src/commit/1804fd634e9b7d25cc885f22dd822c51f26e8d0d
- [7.4~]
- ZEND_VM_KIND_HYBRID のディスパッチコードを修正
petk: Update NEWS [ci skip]
petk: Add zend.exception_ignore_args [ci skip]
- https://github.com/php/php-src/commit/5017676438439f1f26a9ef8401bacec903a38ec5
- [7.4~]
- UPGRADING へ先日追加された zend.exception_ignore_args について追記
petk: Catch up with current procedures
- https://github.com/php/php-src/commit/d094ca83df2d57dd782884c23cabdc9a5d282ce8
- [7.4~]
- docs/release-process.md の内容を現状にあわせ更新
derickr: Update NEWS for PHP 7.4.0alpha3
- https://github.com/php/php-src/commit/3fd7c478a5c83f6c596c70d001cd0c68d7fbe779
- PHP 7.4.0alpha3 のリリース用に NEWS の更新
derickr: Update NEWS for 7.4.0beta1
- https://github.com/php/php-src/commit/086b476c27790889e25d872eec21090185ce4e6f
- 7.4 系の開発バージョンを PHP 7.4.0beta1 へ引き上げ
dstogov: Remove duplicated code for (PRE|POST)DEC(OBJ|STATIC_PROP) opcodes
- https://github.com/php/php-src/commit/e1f418dd18479748739b93aa9f84b9a2e907cfbd
- [7.4~]
- VM の (PRE|POST)DEC(OBJ|STATIC_PROP) の重複コードを削除
cmb69: Upgrade to SQLite 3.28.0
- https://github.com/php/php-src/commit/e944ae6b2a0533cb6098af8c2beb8d0f2c84ec6d
- [7.1~]
- ext/sqlite3 で、SQLite のバージョンを 3.28.0 に引き上げ
nikic: Revert "Fixed bug #76980"
- https://github.com/php/php-src/commit/22ed362810c1b3a5ecb54ebd1d50d804c7fc3159
- [7.2~]
- 先日のなんじゃこりゃあの修正をリバート
- Symfony で問題が出たため、7.2 系、7.3 系のみでリバートした形
dstogov: Avoid unintended inlining
- https://github.com/php/php-src/commit/8f0c87e1b63807a1afb755a038ad57f2951a4505
- [7.4~]
- VM のコードで意図せぬインライン化を避けるよう修正
devnexen: CGI: Fix memory leak on error paths
- https://github.com/php/php-src/commit/aa0e29a66838bd89547a5a8ec4ae25945556ad54
- [7.4~]
- sapi/cgi で、エラー時のメモリリークの修正
- 投稿日:2019-07-10T09:36:10+09:00
PHPでシステム時刻と違う結果が出るとき
PHPをタイマー系の自分用バッチで使っていて、システムロケールと違う結果が出ると困りますよね。
もちろん、日本だけで使うバッチなら、設定ファイルを日本専用に書き換えてしまえば良いのですが、旅行先などで違う時間を見ていたとか、飛行機に乗り遅れる原因になります。(なりました。)
MacOS10.14 + PHP7.3で確認したところ、以下の設定にしておくと、自動的にシステムのロケール見てくれました。マニュアルによればWindowsでもOKとのこと。
<?php setlocale(LC_ALL, ''); // システム環境設定を読む
- 投稿日:2019-07-10T08:19:27+09:00
Nuxt.jsにGoogle reCAPTCHA v3 を入れる。
reCAPTCHA
Nuxt.jsで作った問い合わせフォームにbot対策でgoogle reCAPTCHA Version 3を導入しました。v3 は機械学習により読みにく文字を入力したりあいまいな画像選択させたりすることなしで、人間かbotかの判定を0(bot)から1(botではない)のスコアにして返してくれるそうな。
Google reCAPTCHA
https://developers.google.com/recaptcha/?hl=jaはじめに
利用にはGoogle アカウントにてログイン、サイトを登録、ドメインの登録(本番環境と開発環境、localhostなど)して、サイトキーとシークレットキーを取得します。
APIの読み込み
reCAPTCHを利用するページでapiソースをパラメータに取得したサイトキーを指定して読み込み。nuxt.config.jsで読み込んでも構いません。その場合は全ページにreCAPCHAのラベルが表示されます。
pages/contact.vueexport default { head() { return { script: [ { src: 'https://www.google.com/recaptcha/api.js?render=サイトキー' } ], } } }トークンの取得
フォームを送信する前に、 バックエンド( 今回はphp)のメール送信プログラムにパラメータとして送るトークンを取得します。
pages/contact.vuemethods: { getToken: function(e) { grecaptcha.ready(function() { grecaptcha .execute('サイトキー', { action: 'homepage' }) .then(function(token) { _this.sendForm(token) }) }) } }バックエンド(php)にパラメーターを渡す
パラメーターは URLSearchParmasインターフェースで渡す必要があるようでけっこうハマりました。先ほど取得したトークンはg-recaptcha-response というパラメータ名でURLSearchParamsに追加、postでバックエンドへ。
pages/contact.vuemethods: { sendForm(token) { const params = new URLSearchParams() params.append('form-name', this.formName) params.append('form-email', this.formEmail) params.append('form-content', this.formContent) params.append('g-recaptcha-response', token) const res = await this.$axios.$post( 'https://メール送信プログラムURL', params ) ... } }バッグエンドでの処理
今回はphpにてメール送信をしました。
header('Access-Control-Allow-Origin: 許可するドメイン'); header('Access-Control-Allow-Methods: POST'); header('Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept'); header('Content-Type: application/json; charset=utf-8' ) ;サーバーサイドによってアクセス制御を整えます。
シークレットキーとトークン
シークレットキーとトークンをパラメータにgoogle reCAPTCHにお伺いを立てます。その結果がjsonで返ってきます。閾値を設定し、それ以上なら送信、以下ならエラーをnuxtに返します。
// シークレット}キー $secret_key = 'シークレットキー'; // エンドポイント $endpoint = 'https://www.google.com/recaptcha/api/siteverify'; $params = '?secret=' . $secret_key; $params .= '&response=' . $_POST['g-recaptcha-response']; // botの閾値 $safescore = 0.1; // 判定結果の取得 $curl = curl_init(); curl_setopt($curl, CURLOPT_URL, $endpoint . $params); curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); // 証明書の検証を行わない curl_setopt($curl, CURLOPT_RETURNTRANSFER, true); // curl_execの結果を文字列で返す curl_setopt($curl, CURLOPT_TIMEOUT, 5); // タイムアウトの秒数 $json = curl_exec($curl); curl_close($curl); $obj = json_decode($json); // 判定の成功と、スコアが閾値以上ならメール送信 if ($obj->success && $obj->score >= $safescore) { // メール送信 } else { //閾値以下ならnuxtにjsonを返す $obj->isbot = true; echo json_encode($obj); exit(); }このスコアは機械学習によるものだそうで、実際に運用してreCAPTCHAのコンソールで確認しならがら閾値を調整していくイメージでしょうか。
実際インド旅行中にホテルのwifiでのテストでは0.5-0.7くらいでしたがスタバのフリーwifiからだと0.1だったり、日本の自宅wifiからだと0.9だったりしました。
これで一通りの実装の流れは終了です。
bot判定だった場合
実際にbotだった場合はさておいて、人間だったけどbot 判定されて送信でき叶った場合にどういうメッセージを表示するのがいいか考えた。
表示する文言はさておいて、別のな方法で問い合わせしてもらう(メールや電話)のもひとつだが、入力した問い合わせ内容(名前、メールアドレス、問い合わせ内容など)を再度入力させるのは申し訳ないので、送れなかった場合はlocalStorageに各項目保存するようにした。これで後ほど違うwifi環境などで試してみたら遅れればlocalStrorageを削除する。
pages/contact.vue// 判定は成功で、bot判定なら if (res.success && res.isbot) { // add localStorage localStorage.setItem('formName', this.formName) localStorage.setItem('formEmail', this.formEmail) localStorage.setItem('formContent', this.formContent) } else { // 送信できた場合、localStorageがあれば削除 if(localStorage.getItem('formName')) localStorage.removeItem('formName') if(localStorage.getItem('formEmail')) localStorage.removeItem('formEmail') if(localStorage.getItem('formContent')) localStorage.removeItem('formContent') }ページリロード時、 localStorageにデータがある場合はそれをinputに渡す
pages/contact.vuedata: function() { return { ... // localStorage.getItem('formName') に保存されていればそこから取得 formName: localStorage.getItem('formName') || '', formEmail: localStorage.getItem('formEmail') || '', formContent: localStorage.getItem('formContent') || '' } },デスクトップの場合違うwifiで、というのはあまりできないだろうが、せっかく書いた問い合わせ内容が消えてしまうよりはいいだろう。同じブラウザでもう一度試したり、コピペしてブラウザを変えたりメールやメモに移したりもできる。
以上、参考になれば幸いです。
- 投稿日:2019-07-10T07:19:31+09:00
PHP 5.6.x から PHP 7.x.x への移行のまとめ
概要
ここに訪れた方がphp7について理解できるまでを目標のため、日々更新予定
新機能
- スカラー型宣言
- 戻り値の型宣言
- Null 合体演算子
- 宇宙船演算子
- define() を用いた配列定数の定義
- 無名クラス
- Unicode コードポイントエスケープ構文
- unserialize() のフィルタリング
- IntlChar
- Expectation
- use 宣言のグループ化
- ジェネレータでの return
- ジェネレータの委譲
- intdiv() による整数の除算
- セッションのオプション
- preg_replace_callback_array()
- CSPRNG 関数
- list() が常に、 ArrayAccess を実装したオブジェクトをアンパックできるように
- 名前空間のグループ指定における最後のカンマの許可
- object 型
- 名前指定による拡張モジュールのロード
- 抽象メソッドのオーバーライド
- Sodium がコアモジュールに
- Argon2 によるパスワードハッシュ
- PDO の拡張文字列型
- PDO のデバッグ情報にプリペアのエミュレートの内容を追加
- LDAP における拡張オペレーションのサポート
- ソケット 拡張モジュールでのアドレス情報の対応
- パラメータの型の拡大変換
- Windows での proc_nice() のサポート
- pack() と unpack() でのエンディアンのサポート
- EXIF 拡張モジュールの機能追加
- PCRE の新機能
- SQLite3 での BLOB の書き込み
- Oracle OCI8 Transparent Application Failover コールバック
- ZIP 拡張モジュールの機能追加
説明などについては以下公式ページへ
https://www.php.net/manual/ja/migration70.new-features.php
https://www.php.net/manual/ja/migration72.new-features.phpPHP 7.0.x で推奨されなくなる機能
PHP 4 形式のコンストラクタ
PHP 4 形式のコンストラクタ (クラス名と同じ名前のメソッドを定義するもの) が非推奨となりました。将来的に削除される見込みです。 PHP 7 では、クラス内でこの形式のコンストラクタしか定義されていない場合に E_DEPRECATED が発生します。 __construct() メソッドを実装していれば、この警告は発生しません。
<?php class foo { function foo() { echo 'I am the constructor'; } } ?>上の例の出力は以下となります。
Deprecated: Methods with the same name as their class will not be constructors in a future version of PHP; foo has a deprecated constructor in example.php on line 3もっと知りたい方↓
https://www.php.net/manual/ja/migration70.deprecated.phpPHP 7.2.x で推奨されなくなる機能
クオートしない文字列
クオートしない文字列は、その名前のグローバル定数が定義されていない場合は単なる文字列という扱いになります。 このとき、いままでは E_NOTICE が発生していました。 PHP 7.2.x 以降は、E_WARNING が発生するようになります。 次のメジャーバージョンアップ後は Error 例外が発生するようになります。
<?php var_dump(NONEXISTENT); /* 出力: Warning: Use of undefined constant NONEXISTENT - assumed 'NONEXISTENT' (this will throw an Error in a future version of PHP) in %s on line %d string(11) "NONEXISTENT" */もっと知りたい方↓
https://www.php.net/manual/ja/migration72.deprecated.phpphp.ini ディレクティブのリスト
https://www.php.net/manual/ja/ini.list.php
PHP のデバッグについて
PHP 5.6 には、phpdbg 対話型デバッガー が同梱されます。 5.6 より前のバージョンには、内部のデバッガ機能はありませんが、 外部のデバッガモジュールを使用することができます。 » Zend IDE にはデバッガが付属していますし、 DBG(» http://www.php-debugger.com/dbg/
Advanced PHP Debugger(APD) および » Xdebug といったフリーの外部デバッガモジュールもあります。function console_log( $data ){ echo '<script>'; echo 'console.log('. json_encode( $data ) .')'; echo '</script>'; } Usage: $myvar = array(1,2,3); console_log( $myvar ); // [1,2,3]PHP公式の全関数およびメソッドの一覧
https://www.php.net/manual/ja/indexes.functions.php
PHP公式サンプル集
https://www.php.net/manual/ja/indexes.examples.php
参考
https://www.php.net/manual/ja/migration70.php
- 投稿日:2019-07-10T07:19:31+09:00
PHP 5.6.x から PHP 7.0.x への移行
概要
ここに訪れた方がphp7について理解できるまでを目標のため、日々更新予定
新機能
- スカラー型宣言
- 戻り値の型宣言
- Null 合体演算子
- 宇宙船演算子
- define() を用いた配列定数の定義
- 無名クラス
- Unicode コードポイントエスケープ構文
- unserialize() のフィルタリング
- IntlChar
- Expectation
- use 宣言のグループ化
- ジェネレータでの return
- ジェネレータの委譲
- intdiv() による整数の除算
- セッションのオプション
- preg_replace_callback_array()
- CSPRNG 関数
- list() が常に、 ArrayAccess を実装したオブジェクトをアンパックできるように
説明などについては以下公式ページへ
https://www.php.net/manual/ja/migration70.new-features.phpphp.ini ディレクティブのリスト
https://www.php.net/manual/ja/ini.list.php
PHP のデバッグについて
PHP 5.6 には、phpdbg 対話型デバッガー が同梱されます。 5.6 より前のバージョンには、内部のデバッガ機能はありませんが、 外部のデバッガモジュールを使用することができます。 » Zend IDE にはデバッガが付属していますし、 DBG(» http://www.php-debugger.com/dbg/)、 » Advanced PHP Debugger(APD) および » Xdebug といったフリーの外部デバッガモジュールもあります。
function console_log( $data ){ echo '<script>'; echo 'console.log('. json_encode( $data ) .')'; echo '</script>'; } Usage: $myvar = array(1,2,3); console_log( $myvar ); // [1,2,3]参考
https://www.php.net/manual/ja/migration70.php
- 投稿日:2019-07-10T07:19:31+09:00
PHP 5.6.x から PHP 7.0.x への移行のまとめ
概要
ここに訪れた方がphp7について理解できるまでを目標のため、日々更新予定
新機能
- スカラー型宣言
- 戻り値の型宣言
- Null 合体演算子
- 宇宙船演算子
- define() を用いた配列定数の定義
- 無名クラス
- Unicode コードポイントエスケープ構文
- unserialize() のフィルタリング
- IntlChar
- Expectation
- use 宣言のグループ化
- ジェネレータでの return
- ジェネレータの委譲
- intdiv() による整数の除算
- セッションのオプション
- preg_replace_callback_array()
- CSPRNG 関数
- list() が常に、 ArrayAccess を実装したオブジェクトをアンパックできるように
説明などについては以下公式ページへ
https://www.php.net/manual/ja/migration70.new-features.phpphp.ini ディレクティブのリスト
https://www.php.net/manual/ja/ini.list.php
PHP のデバッグについて
PHP 5.6 には、phpdbg 対話型デバッガー が同梱されます。 5.6 より前のバージョンには、内部のデバッガ機能はありませんが、 外部のデバッガモジュールを使用することができます。 » Zend IDE にはデバッガが付属していますし、 DBG(» http://www.php-debugger.com/dbg/
Advanced PHP Debugger(APD) および » Xdebug といったフリーの外部デバッガモジュールもあります。function console_log( $data ){ echo '<script>'; echo 'console.log('. json_encode( $data ) .')'; echo '</script>'; } Usage: $myvar = array(1,2,3); console_log( $myvar ); // [1,2,3]参考
https://www.php.net/manual/ja/migration70.php
- 投稿日:2019-07-10T00:31:29+09:00
PHPでオブジェクトをシリアライズする
serializeを使って
Serialization of 'Closure' is not allowed
になった場合はOpis Closureを使ってみると良さそう。
super_closureというのもある。Opis Closure
composer require --dev opis/closureuse function Opis\Closure\{serialize as opisSerialize, unserialize as opisUnserialize};$path = 'tests/fixtures/serialize/objectName'; // 保存 $file = new \SplFileObject(base_path($path), 'w'); $file->fwrite(encrypt(opisSerialize($objectName))));// encrypt、base_pathはlaravelのもの// 復元 $object = opisUnserialize(decrypt(file_get_contents(base_path($path))));// decrypt、base_pathはlaravelのものシリアライズされた文字列はセキュリティ的な意味で気を付けたいので、ものによっては暗号化
使いどころの例
- 複雑なオブジェクトを返すメソッドを持つ外部APIの公式ライブラリがある。
- このオブジェクトを引数とするアプリ内のメソッドを作ってみたのでテストをしたい。
- テストではテストのAPIでも叩きたくないが、ライブラリ使用しないで自力でオブジェクトを作るのが難しい。
上記のとき、開発用のAPIを叩いた際に取得できたオブジェクトをシリアライズしてテスト時にデシリアライズして使うようにしてみたり。
- 投稿日:2019-07-10T00:28:53+09:00
SQLSTATE[42000]: Syntax error or access violation: 1075 Incorrect table definitionの解消
タイトルのエラーについて
docker上でテーブルを作成しようとphp artisan migrateをかけたら初めてこのエラーに遭遇
解消法はいたって簡単
最初に書いていたmigrationファイルmigration.phpSchema::create('questions', function (Blueprint $table) { $table->increments('id'); $table->integer('user_id'); $table->increments('tag_category_id'); $table->string('title'); $table->text('content'); $table->timestamps(); $table->softDeletes(); });これだとタイトルのエラーが出た。
立てた仮説は主キーがふたつできてしまっているからエラーになっているのではないかと予想。
なので、こう変更して再びマイグレーション。migration.phpSchema::create('questions', function (Blueprint $table) { $table->increments('id'); $table->integer('user_id'); $table->integer('tag_category_id'); //変更 $table->string('title'); $table->text('content'); $table->timestamps(); $table->softDeletes(); });結果
無事マイグレーションが成功