20190710のPHPに関する記事は8件です。

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

petk: Update NEWS [ci skip]

petk: Add zend.exception_ignore_args [ci skip]

petk: Catch up with current procedures

derickr: Update NEWS for PHP 7.4.0alpha3

derickr: Update NEWS for 7.4.0beta1

dstogov: Remove duplicated code for (PRE|POST)DEC(OBJ|STATIC_PROP) opcodes

cmb69: Upgrade to SQLite 3.28.0

nikic: Revert "Fixed bug #76980"

dstogov: Avoid unintended inlining

devnexen: CGI: Fix memory leak on error paths

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

PHPでシステム時刻と違う結果が出るとき

PHPをタイマー系の自分用バッチで使っていて、システムロケールと違う結果が出ると困りますよね。

もちろん、日本だけで使うバッチなら、設定ファイルを日本専用に書き換えてしまえば良いのですが、旅行先などで違う時間を見ていたとか、飛行機に乗り遅れる原因になります。(なりました。)

MacOS10.14 + PHP7.3で確認したところ、以下の設定にしておくと、自動的にシステムのロケール見てくれました。マニュアルによればWindowsでもOKとのこと。

<?php
setlocale(LC_ALL, ''); // システム環境設定を読む
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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.vue
export default {
  head() {
   return {
     script: [
       {
         src: 'https://www.google.com/recaptcha/api.js?render=サイトキー'
       }
     ],
   }
  }
}

トークンの取得

 フォームを送信する前に、 バックエンド( 今回はphp)のメール送信プログラムにパラメータとして送るトークンを取得します。

pages/contact.vue
methods: {
   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.vue
methods: {
    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.vue
data: function() {
   return {
     ...
    // localStorage.getItem('formName') に保存されていればそこから取得
    formName: localStorage.getItem('formName') || '', 
    formEmail: localStorage.getItem('formEmail') || '',
    formContent: localStorage.getItem('formContent') || ''
   }
 },

デスクトップの場合違うwifiで、というのはあまりできないだろうが、せっかく書いた問い合わせ内容が消えてしまうよりはいいだろう。同じブラウザでもう一度試したり、コピペしてブラウザを変えたりメールやメモに移したりもできる。

以上、参考になれば幸いです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

PHP 5.6.x から PHP 7.x.x への移行のまとめ

概要

ここに訪れた方がphp7について理解できるまでを目標のため、日々更新予定

新機能

  1. スカラー型宣言
  2. 戻り値の型宣言
  3. Null 合体演算子
  4. 宇宙船演算子
  5. define() を用いた配列定数の定義
  6. 無名クラス
  7. Unicode コードポイントエスケープ構文
  8. unserialize() のフィルタリング
  9. IntlChar 
  10. Expectation
  11. use 宣言のグループ化
  12. ジェネレータでの return
  13. ジェネレータの委譲
  14. intdiv() による整数の除算
  15. セッションのオプション
  16. preg_replace_callback_array()
  17. CSPRNG 関数
  18. list() が常に、 ArrayAccess を実装したオブジェクトをアンパックできるように
  19. 名前空間のグループ指定における最後のカンマの許可
  20. object 型
  21. 名前指定による拡張モジュールのロード
  22. 抽象メソッドのオーバーライド
  23. Sodium がコアモジュールに
  24. Argon2 によるパスワードハッシュ
  25. PDO の拡張文字列型
  26. PDO のデバッグ情報にプリペアのエミュレートの内容を追加
  27. LDAP における拡張オペレーションのサポート
  28. ソケット 拡張モジュールでのアドレス情報の対応
  29. パラメータの型の拡大変換
  30. Windows での proc_nice() のサポート
  31. pack() と unpack() でのエンディアンのサポート
  32. EXIF 拡張モジュールの機能追加
  33. PCRE の新機能
  34. SQLite3 での BLOB の書き込み
  35. Oracle OCI8 Transparent Application Failover コールバック
  36. ZIP 拡張モジュールの機能追加

説明などについては以下公式ページへ
https://www.php.net/manual/ja/migration70.new-features.php
https://www.php.net/manual/ja/migration72.new-features.php

PHP 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.php

PHP 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.php

php.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

https://www.php.net/manual/ja/migration72.php

https://www.php.net/manual/ja/debugger.php

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

PHP 5.6.x から PHP 7.0.x への移行

概要

ここに訪れた方がphp7について理解できるまでを目標のため、日々更新予定

新機能

  1. スカラー型宣言
  2. 戻り値の型宣言
  3. Null 合体演算子
  4. 宇宙船演算子
  5. define() を用いた配列定数の定義
  6. 無名クラス
  7. Unicode コードポイントエスケープ構文
  8. unserialize() のフィルタリング
  9. IntlChar 
  10. Expectation
  11. use 宣言のグループ化
  12. ジェネレータでの return
  13. ジェネレータの委譲
  14. intdiv() による整数の除算
  15. セッションのオプション
  16. preg_replace_callback_array()
  17. CSPRNG 関数
  18. list() が常に、 ArrayAccess を実装したオブジェクトをアンパックできるように

説明などについては以下公式ページへ
https://www.php.net/manual/ja/migration70.new-features.php

php.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

https://www.php.net/manual/ja/migration72.php

https://www.php.net/manual/ja/debugger.php

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

PHP 5.6.x から PHP 7.0.x への移行のまとめ

概要

ここに訪れた方がphp7について理解できるまでを目標のため、日々更新予定

新機能

  1. スカラー型宣言
  2. 戻り値の型宣言
  3. Null 合体演算子
  4. 宇宙船演算子
  5. define() を用いた配列定数の定義
  6. 無名クラス
  7. Unicode コードポイントエスケープ構文
  8. unserialize() のフィルタリング
  9. IntlChar 
  10. Expectation
  11. use 宣言のグループ化
  12. ジェネレータでの return
  13. ジェネレータの委譲
  14. intdiv() による整数の除算
  15. セッションのオプション
  16. preg_replace_callback_array()
  17. CSPRNG 関数
  18. list() が常に、 ArrayAccess を実装したオブジェクトをアンパックできるように

説明などについては以下公式ページへ
https://www.php.net/manual/ja/migration70.new-features.php

php.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

https://www.php.net/manual/ja/migration72.php

https://www.php.net/manual/ja/debugger.php

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

PHPでオブジェクトをシリアライズする

serializeを使ってSerialization of 'Closure' is not allowedになった場合はOpis Closureを使ってみると良さそう。
super_closureというのもある。

Opis Closure

composer require --dev opis/closure
use 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を叩いた際に取得できたオブジェクトをシリアライズしてテスト時にデシリアライズして使うようにしてみたり。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

SQLSTATE[42000]: Syntax error or access violation: 1075 Incorrect table definitionの解消

タイトルのエラーについて

docker上でテーブルを作成しようとphp artisan migrateをかけたら初めてこのエラーに遭遇
解消法はいたって簡単
最初に書いていたmigrationファイル

migration.php
Schema::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.php
Schema::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();
        });

結果

無事マイグレーションが成功

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む