- 投稿日:2019-07-16T23:36:42+09:00
p+q=r2乗のN以下の素数を求める
問題文
p+q=r2 を満たす N 以下の素数 (p,q,r) の組の個数を求めてください。
ソース
<?php //入力値 $nyu = 10; //素数を取得 for($i=2; $i<$nyu; ++$i){ $flag = 0; for($j=2; $j<$i; ++$j){ if( $i%$j == 0){ $flag =1; break; } } if($flag == 0){ $retsu[] = $i; } } //2乗の値を取得 for($i=0; $i<count($retsu); $i++){ $total[] = $retsu[$i] * $retsu[$i]; } //計算パターンを2次元配列に格納 foreach ($retsu as $val1) { foreach ($retsu as $val2) { $result[] = array_merge((array)$val1, (array)$val2); } } //配列に格納した組み合わせを足し算して、合計と一致するものにカウント+1 for($i=0; $i<count($retsu); $i++){ for($p=0; $p<count($result); $p++){ $tasu_kekka = ($result[$p][0] + $result[$p][1]); if($tasu_kekka == $total[$i]){ $kekka[] = 1; } } } echo count($kekka); ?>
- 投稿日:2019-07-16T23:18:08+09:00
MacでLaravel5.8導入 その2 Composer, Laravelのインストール プロジェクト作成
前提
下記のページ(公式ではない?)が非常によくできてるので読めばだいたいわかる
https://readouble.com/環境:Mac
VirtualBox, Vagrant導入済み
前回の記事で仮想環境構築までは完了済みComposerの導入
Homebrewを利用
すぐにバージョン古くなってるのでまずはアップデート確認# ステータスチェック $ brew doctor # 問題があれば極力解決しておく # アップデート $ brew update # アップグレード $ brew upgrade # エラーが出てなさそうなら、composerのインストール $ brew install composer # composerで、Laravelインストーラをダウンロード $ composer global require laravel/installerlaravelコマンドのパスを通す
.bash_profileに下記を追加
export PATH=$PATH:~/.composer/vendor/bin
プロジェクトを作成したい場所に移動してnewコマンド実行
$ cd ~/myProject $ laravel new laravelTestおしまい
- 投稿日:2019-07-16T22:58:25+09:00
MacでLaravel5.8導入 導入の下準備_仮想環境構築
前提
下記のページ(公式ではない?)が非常によくできてるので読めばだいたいわかる
https://readouble.com/環境:Mac
VirtualBox, Vagrant導入済み導入前の下準備
仮想環境の設定
Homestead というVagrant仮想環境を使うと非常に都合が良いらしい
# Vagrantに、HomesteadのBoxイメージをインストール $ vagrant box add laravel/homestead # homeディレクトリにhomesteadのリポジトリをクローン(自分のLaravelの全プロジェクトをホストしておくHomestead Boxを用意するためらしい) $ git clone https://github.com/laravel/homestead.git ~/Homestead # 最新のmasterではなく安定版のreleaseブランチに変更 $ cd ~/Homestead $ git checkout release # 設定ファイルを作成(Homestead.yaml) $ bash init.shHomestead.yamlの設定
下記以外は特殊な設定がなければ初期設定のままでOK
# 仮想環境に同期したいローカル環境のディレクトリを記載する # map: ローカル開発環境側 to: 仮想環境側 folders: - map: ~/myProject/laravelTest to: /home/vagrant/laravelTestホスト名の解決
hostsファイルに下記を追加する。192.168.10.10は、IPアドレスの初期値
192.168.10.10 homestead.test
Vagrantの起動
Homesteadの設定が一通り終わったので、Vagrantを起動する。
# Homesteadディレクトリで $ vagrant upブラウザで、
homestead.test
にアクセスして表示されればOK仮想環境へのSSH接続
# Homesteadディレクトリで $ vagrant sshアクセスが成功し、ホームディレクトリに同期させたかったディレクトリ, ファイルがあればOK
Homesteadディレクトリ以外からもssh接続できるようにするためには下記を.bash_profileに追加する。function homestead() { ( cd ~/Homestead && vagrant $* ) }これで他のディレクトリからも
$ homestead ssh
でssh接続できるようになる。(他のvagrantコマンドも)
- 投稿日:2019-07-16T22:58:25+09:00
MacでLaravel5.8導入 + 仮想環境構築
前提
下記のページ(公式ではない?)が非常によくできてるので読めばだいたいわかる
https://readouble.com/環境:Mac
Homebrew, VirtualBox, Vagrant導入済みまずはComposerの導入
Homebrewを利用
すぐにバージョン古くなってるのでまずはアップデート確認# ステータスチェック $ brew doctor # 問題があれば極力解決しておく # アップデート $ brew update # アップグレード $ brew upgrade # エラーが出てなさそうなら、composerのインストール $ brew install composer # composerで、Laravelインストーラをダウンロード $ composer global require laravel/installerパスを通してプロジェクト作成
laravelコマンドのパスを通す
.bash_profileに下記を追加
export PATH=$PATH:~/.composer/vendor/bin
プロジェクトを作成したい場所に移動してnewコマンド実行
$ cd ~/myProject $ laravel new laravelTestこれでいったんプロジェクトの作成は完了。
仮想環境の設定
Homestead というVagrant仮想環境を使うと非常に都合が良いらしい
# Vagrantに、HomesteadのBoxイメージをインストール $ vagrant box add laravel/homestead # homeディレクトリにhomesteadのリポジトリをクローン(自分のLaravelの全プロジェクトをホストしておくHomestead Boxを用意するためらしい) $ git clone https://github.com/laravel/homestead.git ~/Homestead # 最新のmasterではなく安定版のreleaseブランチに変更 $ cd ~/Homestead $ git checkout release # 設定ファイルを作成(Homestead.yaml) $ bash init.shHomestead.yamlの設定
下記以外は特殊な設定がなければ初期設定のままでOK
Homestead.yaml# 仮想環境に同期したいローカル環境のディレクトリを記載する # map: ローカル開発環境側 to: 仮想環境側 folders: - map: ~/myProject/laravelTest to: /home/vagrant/laravelTestホスト名の解決
hostsファイルに下記を追加する。192.168.10.10は、IPアドレスの初期値
192.168.10.10 homestead.test
Vagrantの起動
Homesteadの設定が一通り終わったので、Vagrantを起動する。
# Homesteadディレクトリで $ vagrant upブラウザで、
homestead.test
にアクセスして表示されればOK仮想環境へのSSH接続
# Homesteadディレクトリで $ vagrant sshアクセスが成功し、ホームディレクトリに同期させたかったディレクトリ, ファイルがあればOK
Homesteadディレクトリ以外からもssh接続できるようにするためには下記を.bash_profileに追加する。function homestead() { ( cd ~/Homestead && vagrant $* ) }これで他のディレクトリからも
$ homestead ssh
でssh接続できるようになる。(他のvagrantコマンドも)おしまい
- 投稿日:2019-07-16T21:20:39+09:00
PHPで4桁以上の金額などの数字をカンマ(,)区切りにする備忘録
sample.php$sujiA = 493948234153; $sujiB = number_format($sujiA); echo $sujiA; // 493948234153 echo $sujiB; // 493,948,234,153
- 投稿日:2019-07-16T18:57:44+09:00
Laravelコレクションのpluck()メソッドを活用しよう
環境
Laravel Framework 5.8
PHP 7.2やりたいこと
DBからこのようなデータを取得して、idがキー、カラムデータがバリューとなる、配列を作りたくなることがよくある。
$collection = collect([ ['id' => 1, 'name' => 'ジャック鈴木', 'company' => 'Five Needs'], ['id' => 2, 'name' => 'Umichiko' , 'company' => 'Five Needs'] ]);私はこれまで、このようなときarray_column()を利用して配列を生成していた。
$user_array = array_column($collection->all(),null,"id");スマートなやり方
Laravelコレクションの機能であるpluck()メソッドを利用することで同様のことがより簡潔に実現できる。
$collection = collect([ ['id' => 1, 'name' => 'ジャック鈴木', 'company' => 'Five Needs'], ['id' => 2, 'name' => 'Umichiko' , 'company' => 'Five Needs'] ]); /* * nameの値だけを取得できる。 */ var_dump($collection->pluck("name")); //class Illuminate\Support\Collection#331 (1) { // protected $items => // array(2) { // [0] => // string(18) "ジャック鈴木" // [1] => // string(8) "Umichiko" // } //} /* * キーがidでバリューがnameのコレクションを生成 */ var_dump($collection->pluck("name", "id")); //class Illuminate\Support\Collection#331 (1) { // protected $items => // array(2) { // [1] => // string(18) "ジャック鈴木" // [2] => // string(8) "Umichiko" // } //} /* * キーがidでバリューに全データが入ったコレクションを生成 */ var_dump($collection->pluck(null, "id")); //class Illuminate\Support\Collection#331 (1) { // protected $items => // array(2) { // [1] => // array(3) { // 'id' => // int(1) // 'name' => // string(18) "ジャック鈴木" // 'company' => // string(10) "Five Needs" // } // [2] => // array(3) { // 'id' => // int(2) // 'name' => // string(8) "Umichiko" // 'company' => // string(10) "Five Needs" // } // } //} /* * array_columnでも同様のことができる */ var_dump(array_column($collection->all(),null,"id")); //array(2) { // [1] => // array(3) { // 'id' => // int(1) // 'name' => // string(18) "ジャック鈴木" // 'company' => // string(10) "Five Needs" // } // [2] => // array(3) { // 'id' => // int(2) // 'name' => // string(8) "Umichiko" // 'company' => // string(10) "Five Needs" // } //}
- 投稿日:2019-07-16T16:57:46+09:00
CodeceptionのE2EテストでseeInSourceはなるべく使わない方が良い件
背景
Codeceptionで要素を見るために
seeInSource
を使っていたら、ローカルでは通ってもサーバー上では全て落ちていた。原因
ローカル上のE2Eテストとサーバー上でのE2Eテストで出力されるHTMLが異なる場合があった。
具体的にはサーバー上ではタグに勝手に閉じタグ< />
が付くなど。$I->seeInSource('<meta property="og:title" content="hogehoge">');とテストコードを書いても
<meta property="og:title" content="hogehoge" />サーバー上では的な具合でHTMLが出力されてしまう。
対処法
seeInSource
をなるべく使わないこと。
上記の例ではseeElementInDOM
を使う。例
$I->seeElementInDOM('meta[property="og:title"][content="hogehoge"]');参考
- 投稿日:2019-07-16T16:27:53+09:00
MacのPHP(Homebrew)でxdebug環境を用意する
Macローカルでデバッグがしたい
Dockerで立てる程ではないものの確認を行いたい場合にいいと思ったので。
PHPのバージョンが同じであれば、Dockerコンテナでも同じ設定で行けそうです。
Windowsはこちら前提条件
console% php -v PHP 7.3.6 (cli) (built: Jun 17 2019 08:40:34) ( NTS ) Copyright (c) 1997-2018 The PHP Group Zend Engine v3.3.6, Copyright (c) 1998-2018 Zend Technologies with Zend OPcache v7.3.6, Copyright (c) 1999-2018, by Zend Technologiesインストール
peclからインストールします。
console% pecl install xdebug # --- 中略 --- # エラーが出る場合 % pecl search xdebug [master] Retrieving data...0% Matched packages, channel pecl.php.net: ======================================= Package Stable/(Latest) Local xdebug 2.8.0alpha1 (beta) 2.8.0alpha1 Provides functions for function traces and profiling % pecl install -f xdebug-2.8.0alpha1 # 確認 % php -v PHP 7.3.6 (cli) (built: Jun 17 2019 08:40:34) ( NTS ) Copyright (c) 1997-2018 The PHP Group Zend Engine v3.3.6, Copyright (c) 1998-2018 Zend Technologies with Xdebug v2.8.0alpha1, Copyright (c) 2002-2019, by Derick Rethans with Zend OPcache v7.3.6, Copyright (c) 1999-2018, by Zend Technologiesおまけ: php.iniの場所
console% php -i | grep php.ini Configuration File (php.ini) Path => /usr/local/etc/php/7.3 Loaded Configuration File => /usr/local/etc/php/7.3/php.iniあとは、PhpStormなどで設定するだけ。
- 投稿日:2019-07-16T13:05:55+09:00
【web開発� PHP】同ページにHTTPを行いたい!
はじめに
webサービスを開発する際に便利だと思ったので書き起こしています。ButtonやAnchorを用いて同ページに変数を送信(HTTP)したいときに使います。例えば、ページ上のカテゴリボタンを押すとそのページ上でそのカテゴリのみのコンテンツが絞られたものが表示されたり。
以下のコード例では同ページ内に変数を渡す部分を記述しています。解決法
こちらではPOST送信で書いておりますが、GETでも可。
PHPファイル先頭に以下を記述。もしPOST送信があればdataを受け取りPOSTデータを削除するだけのシンプルなコードです。if (isset($_POST["btnid"])) { $data = $_POST["btnid"]; unset($_POST); }さて、以下のコードが鍵となります。こちらはform要素ですが、画面上には表示されないようになっております。valueには後に送信したい変数を格納するのでデフォルトでは空白。
<form name="form1"> <INPUT type="hidden" id="btnid" name="btnid" value=""/> </form>以下のコードではid="id"である要素をクリックするとvalueに送信したい変数を格納して送信するというものであり、これが実行されると、もう一度index.phpの先頭行から処理ををするため\$data変数に$_POST["btnid"]が送信されるというシンプルなものです。
$("#id").on("click", function(e){ $("#btnid").val(data); //送信したいデータをvalue値として登録 let form1 = document.forms["form1"]; form1.method = "POST"; //HTTP方式の決定 form1.action = "index.php"; //遷移先を同ファイルに設定 form1.submit(); //送信 return false; });未解決事項
色々調べてみたものの、一番よく見かけたのはAjaxでの送信でしたが今回はうまく実装できませんでした。AjaxはGoogle検索する時に、文字を少しタイプすると下に検索予想が出てくる機能に使われているようで、常にHTTP方式で送信している感じらしいです。おそらく、今回実装できなかったのは要素がクリックした時にのみ発火されるというものに相性が良くなかったのかなと思いますが、今後の実装でもう一度勉強しようと思います。
- 投稿日:2019-07-16T13:05:55+09:00
【web開発】PHPで同ページにHTTPを行いたい!
はじめに
webサービスを開発する際に便利だと思ったので書き起こしています。ButtonやAnkerを用いて同ページに変数を送信(HTTP)したいときに使います。例えば、ページ上のカテゴリボタンを押すとそのページ上でそのカテゴリのみのコンテンツが絞られたものが表示されたり。
以下のコード例では同ページ内に変数を渡す部分を記述しています。解決法
こちらではPOST送信で書いておりますが、GETでも可。
PHPファイル先頭に以下を記述。もしPOST送信があればdataを受け取りPOSTデータを削除するだけのシンプルなコードです。if (isset($_POST["btnid"])) { $data = $_POST["btnid"]; unset($_POST); }さて、以下のコードが鍵となります。こちらはform要素ですが、画面上には表示されないようになっております。valueには後に送信したい変数を格納するのでデフォルトでは空白。
<form name="form1"> <INPUT type="hidden" id="btnid" name="btnid" value=""/> </form>以下のコードではid="id"である要素をクリックするとvalueに送信したい変数を格納して送信するというものであり、これが実行されると、もう一度index.phpの先頭行から処理ををするため\$data変数に$_POST["btnid"]が送信されるというシンプルなものです。
$("#id").on("click", function(e){ $("#btnid").val(data); //送信したいデータをvalue値として登録 let form1 = document.forms["form1"]; form1.method = "POST"; //HTTP方式の決定 form1.action = "index.php"; //遷移先を同ファイルに設定 form1.submit(); //送信 return false; });未解決事項
色々調べてみたものの、一番よく見かけたのはAjaxでの送信でしたが今回はうまく実装できませんでした。AjaxはGoogle検索する時に、文字を少しタイプすると下に検索予想が出てくる機能に使われているようで、常にHTTP方式で送信している感じらしいです。おそらく、今回実装できなかったのは要素がクリックした時にのみ発火されるというものに相性が良くなかったのかなと思いますが、今後の実装でもう一度勉強しようと思います。
- 投稿日:2019-07-16T12:46:13+09:00
偶数だけを繰り返し表示する(PHP)
簡単だけど文法等をすっきり落とし込むためにアウトプット。
やること
1から100までの数字から偶数だけ表示させるどうやったか
<?php $i = 1; //変数を定義 while($i <= 100) { if($i % 2 == 0) { echo $i; echo '<br>'; } $i ++; } ?>1から100までを繰り返すWhile文の中で2で割り切れる数字(偶数)だけを表示させています。
これ自体は難しくはないけどこういった発想の組み合わせが大事だと思いました。(追加)
for($i = 1;$i <= 100; $i++) { if($i % 2 == 1){ continue; } echo $i; echo '<br>'; }もしくはfor文で奇数だけスキップなんてやり方もありますね。
- 投稿日:2019-07-16T11:35:57+09:00
PHP の mysqli, mysqlnd, pdo_mysql, PDO, libmysqlclient まとめ
PHP で MySQL を利用する時、通常は PHP 拡張モジュール(extension)を用いて接続します。
その時、
mysqli
,mysql
,mysqlnd
,pdo_mysql
,PDO
,libmysqlclient
といったわかりづらい名前の諸々があるので、ここでまとめておきます。拡張モジュール
php.iniextension=mbstring.soこんな感じで設定を書くことで、ネイティブ C で記述された機能を PHP 上で利用出来るようになります。
PHP の実装よりも高速に動作するため、 MySQL との通信処理など処理速度がボトルネックになるようなものは拡張モジュールとして実装することで、処理速度の向上をしています。
拡張モジュール用ライブラリ
まず、 MySQL 拡張モジュールを実装する際にベースとされるライブラリがあります。
現状は
mysqlnd
とlibmysqlclient
のどちらかです。これらは、 PHP のコンパイル時に
--with-pdo-mysql=mysqlnd
などと指定して選ぶことが可能です。mysqlnd
MySQL Native Driver が現在推奨されているネイティブライブラリで、デフォルトでこれが使われます。
libmysqlclient
よりも様々な点で優れているため、こちらを選ぶことがほとんどのケースで最適です。
mysqlnd
それ自体も PHP 拡張モジュールとして実装されているため、パフォーマンスも高いです。libmysqlclient
mysqlnd
の前に MySQL チーム(現 Oracle)が作成した、 PHP 依存のない純粋な C 言語のライブラリです。利用時に MySQL をインストールする必要があったり、 MySQL ライセンスのため PHP に同梱出来なかったりと欠点がいくつかあります。
サポート自体は継続されていますが、一般に利用することはほぼないでしょう。
まとめ1
mysqlnd
とlibmysqlclient
は MySQL に接続するためのベースライブラリで選択可能- 基本は
mysqlnd
を選択するmysql
単純に
mysql
と言った時は、大体 PHP 2.0 からある古い拡張モジュールのことを指します。mysql_connect 関数などを提供している extension ですが、 PHP 7 以降は利用出来ません。
なので、この拡張モジュールは新規開発では利用されないでしょう。そもそもトランザクションすらないので、実用性もありません。
超絶古い PHP 3 や 4 で開発されたプロダクトがまだ生きていて、保守しなければならない時に見かけることがあるかもしれない、くらいです。mysqli
MySQL Improved
拡張モジュールです。公式ではこの拡張モジュールが推奨されています。$mysqli = new mysqli("example.com", "user", "password", "database"); if ($mysqli->connect_errno) { echo "Failed to connect to MySQL: " . $mysqli->connect_error; } $res = $mysqli->query("SELECT 'choices to please everybody.' AS _msg FROM DUAL"); $row = $res->fetch_assoc(); echo $row['_msg'];こんな感じで手軽にクエリを投げることが出来る API を提供しています。
mysql
と似た API も提供しているので、移行も比較的楽に可能です。PDO
PHP の基本機能として、複数のデータベースアプリケーション(MySQL, sqlite, Oracle など...)間で出来るだけインターフェースを統一し、同じ PHP コードで別 DB にも投げれるようにした API 実装が PDO です。
これを使うことで、接続先のDB用のドライバを切り替えるだけで手軽に別の DB アプリケーションへ移行することが出来ます。
(実際に別の DB アプリケーションに移行することがあるのかはおいといて)Laravel や CakePHP は PDO をラップして実装されているので、
mysqli
拡張モジュールを利用することは出来ません。
逆に、 Doctrine や CodeIgniter はmysqli
を使うことも可能です。PDO を利用するのであれば、
extension=mysqli
としてmysqli
拡張モジュールを有効にする必要はありません。pdo_mysql
pdo_mysql
拡張モジュールは、 PDO API で MySQL に接続するためのドライバです。PDO を使って MySQL に接続したい場合はこの拡張モジュールを有効にする必要があります。
他にも、
pdo_sqlite
pdo_pgsql
などのドライバ拡張モジュールがあり、それらを有効にすることで PDO を通して接続可能になります。まとめ2
mysql
はもう使われない古い拡張モジュールmysqli
は推奨されている拡張モジュールpdo_mysql
は他の DB に繋ぐことも考えた抽象化層であるPDO
を一個挟んだ拡張モジュールフレームワークや OR マッパーによってこの辺りは隠蔽されることがほとんどですが、実際に使われている拡張モジュールが何かを知ることは
php.ini
の設定や Dockerfile を書く時などで必要になってきます。これでもう間違わないで拡張モジュールを選べるようになったのではないでしょうか。参考資料
- 投稿日:2019-07-16T08:57:18+09:00
php-master-changes 2019-07-15
今日は不要コードの削除、ドキュメントの更新、opcache_get_configuration() で ini_get_all('zend opcache') でとれる結果が全てとれない問題の修正、AArch64 用の文字列エスケープの最適化、循環参照GC で SEGV が起きる問題の修正、字句解析器で無効な文字向けに T_BAD_CHARACTER を吐くようにする修正、date.sunset_zenith と date.sunrise_zenith のデフォルト値を 90.583333 から 90.833333 にする修正、password_hash() が argon2 で弱いオプションを使う問題の修正、mysqlnd のバージョン番号に PHP バージョンを使うようにする修正、ftp のリーク修正の 7.2 系以降へのバックポート、shebang の対応を字句解析器内で行うようにする修正があった!
2019-07-15
petk: Remove unsed zts check for sqlite3
- https://github.com/php/php-src/commit/e39296d10bffaaf792440c82f61662268c748a93
- [7.4~]
- ext/sqlite3 で、不要な ZTS のチェックを削除
petk: Remove conditional calls of always available macros
- https://github.com/php/php-src/commit/94421e5724e1942499d024ae7537a329fe426133
- [7.4~]
- ビルドシステムで、常に存在するマクロの不要な存在チェックの削除
petk: Symbol HAVE_PCRE has been removed
- https://github.com/php/php-src/commit/9310ac2ab530da1ba5547bdac1b8786b8e3e41be
- UPGRADING.INTERNALS で、HAVE_PCRE の削除について言及を追加
petk: Remove usage of PHP_AIX_LDFLAGS
- https://github.com/php/php-src/commit/93b3d2f6eeb1db16af4a869688829a04c7f11e6d
- [7.4~]
- ビルドシステムで、PHP_AIX_LDFLAGS の利用を削除
amnuts: Fix bug #78291 Missing opcache directives
- https://github.com/php/php-src/commit/768ad70f70a1bebed38e2b06a7515e3c61482f75
- [7.2~]
- ext/opcache で、opcache_get_configuration() で ini_get_all('zend opcache') でとれる結果が全てとれない問題の修正
sebpop: vectorize string-escape with NEON
- https://github.com/php/php-src/commit/af7639683f072c15b8af3648dc6b0c2b14201d21
- [7.4~]
- AArch64 で、NEON を使って文字列エスケープをベクトル化
nikic: Fixed bug #78010
- https://github.com/php/php-src/commit/193f28c7d557df887c4456d072113cc2478e1c3e
- [7.3~]
- 循環参照GC で SEGV が起きる問題の修正
nikic: Remove unused is_constructor arguments
- https://github.com/php/php-src/commit/f821256d00180eb5452c7d01c5c31141bf10f884
- ext/intl で、使われていない引数 is_constructor の削除
nikic: Emit T_BAD_CHARACTER for unexpected characters
- https://github.com/php/php-src/commit/9ad094e371961f8d291f95945a2a086db2e0378f
- [7.4~]
- 字句解析器で無効な文字向けに T_BAD_CHARACTER を吐くよう修正
- ext/tokenizer で、token_get_all() で取得結果に穴ができないようになる
cmb69: Fix #65547: Default value for sunrise/sunset zenith still wrong
- https://github.com/php/php-src/commit/7556600dfc80e9a11db538ce58cb249d6cdda7b3
- ext/date で、date.sunset_zenith と date.sunrise_zenith が一般的な値でなかった問題の修正
- 90°50' を使って 90.833333 になると思いきや 90°35' で 90.583333 になっており、その根拠がよく分からない感じだった
- sunrise とか sunset でとる値が PHP 8 で(デフォルトでは)変わるので、使ってる人は急にテストこけてびびらされたりするかもしれない?
remicollet: Fix #78269 password_hash uses weak options for argon2
- https://github.com/php/php-src/commit/eab0079c902a9a52773c6bb63b57555dee45b3ab
- [7.2~]
- password_hash() が argon2 で弱いオプションを使う問題の修正
remicollet: typo [ci skip]
- https://github.com/php/php-src/commit/ad48464ec2ef6c9b4026129dd1adc413fa4fe3c7
- [7.3~]
- NEWS で、typo の修正
cmb69: Sync mysqlnd version with PHP version
- https://github.com/php/php-src/commit/37043e07dfa57dbc567b7217ca7aa25a1385ccb6
- [7.4~]
- ext/mysqlnd で、バージョン番号に PHP バージョンを使うよう修正
nikic: Fix bug #77124
- https://github.com/php/php-src/commit/88ffe0579726f7ba1985c9223e6005c581032757
- [7.2~]
- ext/ftp で、先日のリーク修正の 7.2 系以降へのバックポート
nikic: Move shebang handling into the lexer
- https://github.com/php/php-src/commit/c5f1b384b591009310370f0b06b10868d2d62741
- [7.4~]
- shebang の対応を字句解析器内で行うよう修正
- 元々 cli / cgi / phpdbg の各 sapi モジュール側で先頭を読んで読み込み開始位置をずらすような実装を持っており、#60677 や #78066 の原因になっていた
- 投稿日:2019-07-16T08:31:28+09:00
PHPでGuzzleを使ったHTTPリクエスト
はじめに
PHPからguzzleを使用して外部API(GithubやQiitaなど)をシンプルに実行するためのメモです。
エラー処理だけLaravel独自のメソッドがありますが、ほとんどフレームワークを選ばず使用できます。guzzleとは
シンプルなインターフェースで同期、非同期リクエストを行えるPHPのHTTPクライアントになります。
詳しくはこちら↓
https://github.com/guzzle/guzzle実装
まずはベース部分を実装します。
/** * @param string $base_url * @param string $path * @param array $headers * @param array $form_params * @param string $method * @return array */ private function requestClient( string $base_url, string $path, array $headers, array $form_params = [], string $method = 'GET' ): array { try { $client = new \GuzzleHttp\Client([ 'base_uri' => $base_url, ]); $response = $client->request($method, $path, [ 'headers' => $headers, 'form_params' => $form_params, ]); return json_decode($response->getBody()->getContents(), true); } catch (\GuzzleHttp\Exception\GuzzleException $e) { report($e); // ログ出力 return []; } }Qiitaからの取得
/** * @return array */ public function getQiitaList(): array { $base_url = 'https://qiita.com'; $path = '/api/v2/authenticated_user/items?page=1&per_page=20'; $headers = ['Authorization' => 'Bearer xxxxxxxxxxxxxxxxx']; return $this->requestClient($base_url, $path, $headers); }Githubからの取得
/** * @return array */ public function getGithubList(): array { $base_url = 'https://api.github.com'; $path = '/repos/terumichi1209/laravel-test/commits?sha=develop'; $headers = []; return $this->requestClient($base_url, $path, $headers); }終わりに
要件によってはこの辺りのオプション使うと良さそうです。
http://docs.guzzlephp.org/en/latest/request-options.html
- 投稿日:2019-07-16T00:28:44+09:00
Laravel[業務効率化]自動migrationファイル作成ツールをつくってみた話
作成するにあたっての動機
今まで、Laravelを使ったプロジェクトにかかわらせていただくことがあり、DB設計を終えた後に、sqlファイルやddlファイルを自動で作ってくれるものはあるのに、それを元にマイグレーションファイルを自動で作ってくれるものがないので、大変だぁと思い、取り組んでみました。
こうしたほうがいい(特にカプセル化・命名などなど)などの意見をぜひほしいです。新米のため、すごく助かります。もしよろしければ、お願いいたします。
最終目的
すでに作成されているテーブルからマイグレーションファイルを自動で作れるようにします。
準備
プロジェクト作成
コマンドcomposer create-project --prefer-dist laravel/laravel autoCreateMigrationFileSystemテーブル作成
今回は、laravelのmigrationファイルを作成・実行し、テーブルを作り、そこから同じファイルが作成されるかをテストします。
実際は複数テーブルがあるため、2つのテーブルを用意する。
・applesテーブル
・lemonsテーブル
コマンド/var/www# php artisan make:migration create_apples_table Created Migration: 2019_07_15_133234_create_apples_table /var/www# php artisan make:migration create_lemons_table Created Migration: 2019_07_15_133511_create_lemons_table僕が今回参加するプロジェクトで使うカラムタイプが補えればいいので、それだけ洗い出す(新たに必要なカラムタイプは後から加えていく)
今回使うカラムタイプ
- bigint(20)のauto_increment
- bigint(20)
- bigint(20) nullable
- bigint(20) default(0)
- varchar(255)
- timestamp (created_atとupdated_atで使用する)
- int(11)
- tinyint(4)
- text
- date
- datetime
これらを二つのマイグレーションファイルに記述します。
CreateApplesTable.php<?php use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateApplesTable extends Migration { public function up() { Schema::create('apples', function (Blueprint $table) { $table->bigIncrements('id'); $table->bigInteger('a'); $table->bigInteger('b')->nullable(); $table->bigInteger('c')->default(0); $table->string('d', 255); $table->timestamps(); }); } public function down() { Schema::dropIfExists('apples'); } }CreateLemonsTable.php<?php use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateLemonsTable extends Migration { public function up() { Schema::create('lemons', function (Blueprint $table) { $table->bigIncrements('id'); $table->integer('e'); $table->tinyInteger('f'); $table->text('g'); $table->date('h'); $table->dateTime('i'); $table->timestamps(); }); } public function down() { Schema::dropIfExists('lemons'); } }コマンド/var/www# php artisan migrate Migration table created successfully. Migrating: 2019_07_15_133234_create_apples_table Migrated: 2019_07_15_133234_create_apples_table Migrating: 2019_07_15_133511_create_lemons_table Migrated: 2019_07_15_133511_create_lemons_tableこれで準備が完了しました。
実装
今回作るファイル(4ファイル)
- app/Repositories/Repository.php
- views/create_table_stub.blade.php
- config/column_type.php
- app/Console/Commands/MakeMigrationFile.phpapp/Repositories/Repository.php(カラム情報を取得するよう)
Repository.php<?php namespace App\Repositories; use Illuminate\Support\Facades\DB; class Repository { //それぞれのテーブルごとのカラム情報を取得する public static function getTableColumnsList() { $tableColumnsList = []; $tableNameList = self::getTableNameList(); foreach ($tableNameList as $tableName){ $tableColumnsList[$tableName] = DB::select('show columns from '. $tableName); } return $tableColumnsList; } //テーブルの名前を一覧取得する(migrationsテーブルは必要ないので、取得したものからはずす) private static function getTableNameList() { return collect(DB::select('show tables')) ->keyBy('Tables_in_'. env('DB_DATABASE')) ->forget('migrations') ->keys(); } }getTableNameListの実行結果
getTableColumnsListの実行結果(applesテーブルの中身の写真だけ(長いので・・・・)
ファイルを作る用のフォーマットを作成する(views/create_table_stub.blade.php)
create_table_stub.blade.phpをview配下に作成する。
create_table_stub.blade.php@php $phpTag = '<?php' @endphp {!! $phpTag !!} use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class {{$className}} extends Migration { public function up() { Schema::create('{{$tableName}}', function (Blueprint $table) { @foreach($defineColumnList as $defineColumn) $table->{!! $defineColumn !!}; @endforeach }); } public function down() { Schema::dropIfExists('{{$tableName}}'); } }@foreachを一番左にしているのは、ファイルを作成したときにインデントを整えるためです。
{{}}ではなく、{!! !!}を使っているところは、エスケープされると都合がよくないため、こうしています。どのカラムタイプならどのマイグレーション用のメソッドを使うか決めておく(config/column_type.php)
今回使用する必要があるのだけ、定義しました。(後々必要なものは足して、完成度を上げていく)
column_type.php<?php return [ 'auto_increment' => [ 'bigint(20) unsigned' => 'bigIncrements' ], 'bigint(20)' => 'bigInteger', 'int(11)' => 'integer', 'tinyint(4)' => 'tinyInteger', 'date' => 'date', 'datetime' => 'dateTime', 'text' => 'text', //サイズ考慮する必要のあるタイプ 'length' => [ 'varchar' => 'string' ] ];auto_incrementは特殊パターンとして、またサイズを考量すべきものは、length配列の中に入れています。
今後、min maxや from toを使用するメソッドを使いたい場合はその時に強化します。
created_atとupdated_atのtimestampsメソッドは後々処理で追加します。
ちなみに、公式に使用できるカラムタイプが書いてあるので、そこを参考にしましたコマンド/var/www# php artisan config:clearコマンドを打ち、設定を反映させました。
コマンドで自動作成が動くようにする。(app/Console/Commands/MakeMigrationFile.php)
コマンドを打ち、ファイルを作成します。
コマンド/var/www# php artisan make:command MakeMigrationFile Console command created successfully.MakeMigrationFile.php<?php namespace App\Console\Commands; use App\Repositories\Repository; use Carbon\Carbon; use Illuminate\Console\Command; use Illuminate\Support\Facades\File; use Illuminate\Support\Str; class MakeMigrationFile extends Command { protected $signature = 'make:migration-file'; protected $description = 'マイグレーション用ファイルを自動作成'; public function __construct() { parent::__construct(); } public function handle() { $configColumnType = config('column_type'); $tableColumnsList = Repository::getTableColumnsList(); foreach ($tableColumnsList as $tableName => $columnList) { $tempDefineColumnList = []; foreach ($columnList as $index => $column) { if ($column->Extra === 'auto_increment') { $tempDefineColumnList[$index] = "{$configColumnType['auto_increment'][$column->Type]}('{$column->Field}')"; continue; } if (isset($configColumnType[$column->Type])) { $tempDefineColumnList[$index] = "{$configColumnType[$column->Type]}('{$column->Field}')"; if ($column->Null === 'YES') $tempDefineColumnList[$index] .= '->nullable()'; if (strlen($column->Default) > 0) $tempDefineColumnList[$index] .= "->default({$column->Default})"; continue; } $tempColumnType = preg_replace('/(\(|\)|[0-9])/', '', $column->Type); if (isset($configColumnType['length'][$tempColumnType])) { $tempLength = preg_replace('/[^0-9]/', '', $column->Type); $tempDefineColumnList[$index] = "{$configColumnType['length'][$tempColumnType]}('{$column->Field}', {$tempLength})"; continue; } //(特殊パターン)created_atとupdated_atのtimestampsメソッド if ($column->Field === 'created_at' && isset($columnList[$index + 1]) && $columnList[$index + 1]->Field === 'updated_at') { $tempDefineColumnList[$index] = 'timestamps()'; continue; } } $tempClassName = 'Create'. Str::studly($tableName). 'Table'; $tempContent = view('create_table_stub', [ 'className' => $tempClassName, 'tableName' => $tableName, 'defineColumnList' => $tempDefineColumnList ])->render(); $fileNamePrefix = Carbon::now()->format('Y_m_d_His'); $tempFilePath = database_path("migrations/{$fileNamePrefix}_create_{$tableName}_table.php"); File::put($tempFilePath, $tempContent); } } }こんな時間かぁー、自分の実力だとこのあとの改造(カプセル化やもっと短く書けるかなどを考える)と寝る時間が無くなってしまうので(あした会社のため)、とりあえず、要件は満たしたのでこれで、実行する。(handle内のカプセル化や足りない処理はまた今度修正)
コマンドphp artisan make:migration-file中身が同じマイグレーションファイルができました。いったん完了。
問題点
- MakeMigrationFile.phpのhandleメソッドの中身をカプセル化する
- lengthのほうのnullableとdefaultが考慮されていないため、その処理を加える。(その場合stringはデフォルト値をクォテーションで囲む)
- 命名ももっといいのがある
まとめ
意外と要件を満たすだけならさくっとできました。よかった明日会社で使ってみよ。
こうしたほうがいい(特にカプセル化・命名などなど)などの意見をぜひほしいです。新米のため、すごく助かります。もしよろしければ、お願いいたします。