- 投稿日:2020-09-18T23:54:45+09:00
【PHP】初心者が実務でnumber_format()にハマった話
はじめに
PHPを扱い始めて1ヶ月程度の駆け出しエンジニアです。
本日の業務中に私個人の勝手な思い込みで必要以上にハマってしまいました。
反省もかねて自宅で色々と検証をしてみました。コード検証はいつもお世話になっているpaiza.ioを使用。
number_format()とは
ざっくり説明すると
4ケタ以上の数字を3ケタ区切りの表記にフォーマットする関数です。簡単な例
<?php $int = 10000; echo number_format($int); ?>このように3ケタずつ区切りをつけることで
画面表示した際の見やすさを助ける役割があります。ここ最近、経理部門が使うプログラムの改修作業をしていたので
ブラウザに出力する数値にはこのnumber_format()を使う、と頭に入れていました。勘違いでハマる
データベースから必要な数値を取り出す際にデータ型が全部int型なのは確認しておりました。
なので、データベースから取り出した数値同士で足し引き計算などを行い、それをブラウザに出力する時には<?php $int1 = 10000; $int2 = 50000; $int_disp = $int1 + $int2; echo number_format($int_disp); ?>
何を血迷ったのか<?php $int1 = 10000; $int2 = 50000; $int_disp = number_format($int1) + number_format($int2); echo $int_disp; ?>てな感じで勝手に自爆しておりました。
理由
データベースから取り出してきた値はint型なのですが
number_format()でフォーマットすることでstring型になります。
※当たり前のことです。。。<?php $int1 = 10000; echo gettype($int1)."\n"; $int2 = 50000; $int2_disp = number_format($int2); echo gettype($int2_disp); ?>厳密に言うと
ブラウザ上で表示はされていたのですが、計算結果の値がめちゃくちゃでした。
それを私は(計算式やデータベースに格納されるまでの流れを確認しなければ...!!)
と、見当違いの調査に時間を使い過ぎてしまいました。恥ずかしい限りです。
変数の型に、もっと意識を向けないといけない、と痛感した1日でした。
4連休に入りますが、連休明けにロスを少しでもカバーできるようにしっかり学習しようと思います。視野を広く持ち、落ち着いて業務できるように日々精進あるのみ。
おまけ
number_format()にかけると、string型になるので
文字列の連結として、以下の文法は適用されます。
使いどころは全くないと思うので、オマケ。
(3ケタ区切りとは)<?php $int1 = 10000; $int2 = 50000; $int_disp = number_format($int1).number_format($int2); echo $int_disp; ?>
- 投稿日:2020-09-18T23:52:32+09:00
コードでわかる$this->入門
なんとなく
$this
や->
を使ったり、$this
や->
ってなんだって思った駆け出しの方への記事です
かなり大雑把に説明していますが、これくらいの方が最初はイメージがつかみやすいと思います
他の素晴らしい記事の橋渡しになれば幸いです。
$this
はオブジェクト自身を表す特別な変数で
->
はオブジェクトのメソッドやプロパティにアクセスするために使うアロー演算子というものです。
実際にコードで見ていきましょう。example.php<?php //クラス class Example { //プロパティ初期化 public $int1 = 100; public $int2 = 200; //メソッド function show() { //ローカル変数 $int1 = 'int2'; echo $this->int1; echo $this->int2; echo $this->$int1; } } //インスタンス化 $test = new Example(); //オブジェクトのメソッドを呼び出す $test->show(); echo '------------'; //プロパティを変更する $test->int1 -= 1; //取得 echo $test->int1; $test->show();この実行結果は以下のようになります
100 200 int2 ---------- 99 99 200 int1
$this->$int1
は$this->int2
に変換されるのがミソ
プロパティもメソッドも->
で呼び出すことができる
またメソッドチェーンという連結する書き方もできる
$this->test()->example()
みたいな感じ
- 投稿日:2020-09-18T19:32:42+09:00
検索条件(get)を複数ページ持ち越す方法
開発中に以下のような遷移時にgetパラメターを持ち越せず苦戦。
①ページ内で検索(get)
②検索結果表示
③検索結果を並び替え(get)
調べてみるとページネーションの際などでも結構はまっている人がいるっぽい。
自分なりに解決した方法が以下。③の処理の際にurlのパラメターをhideで投げる。
<input type="hidden" name="condition" :value="setGetParams()"> setGetParams() { return window.location.search },urldecodeでパラメータと並び替えの条件を合体させurl作成⇒リダイレクト
public function action_result() { $get = \Input::get(); //urlのパラメターが投げられていたら以下処理 if(!empty($get['condition'])): $url = urldecode(\Uri::current().$get['condition']); $url = $url.'&order='.$get['order']; \Response::redirect($url); endif; //パラメータが投げられていなければ通常の検索処理 $data = Model_Data::search($get); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~多少強引ですが以下で検索条件をページを跨いでも引き継げます。
- 投稿日:2020-09-18T18:35:09+09:00
Laravel-AdminLTEのビューをカスタマイズする
環境
- jeroennoten/laravel-adminlte
- v3.4.4
やりたいこと
app/config/adminlte.php
(以降「設定ファイル」と記載)で制御できる範囲を超えてカスタマイズすることです。たとえば、ログイン画面における「ログイン状態を保持する」チェックボックスを消したい場合です。このケースでは設定ファイルで制御することができません。
方法
以下コマンドを実行しましょう。
$ php artisan adminlte:install --only=main_viewsこのコマンドを実行すると
resources/views/vendor/adminlte
内にビューファイルが作成されます。あとはこれらを編集して各ビューで読み込ませればOKです。補足
本パッケージの
README.md
にもこのやり方は書いてあります。ただ、Google検索経由だとphp artisan vendor:publish 〜
コマンドを用いる旨のWebページがけっこうヒットして紛らわしかったのでここに書き留めておきます。まあ最初から一次ソースを見ればよかったのですが。笑以上です。
- 投稿日:2020-09-18T17:05:55+09:00
php.iniを変更したのにsessionの保存先が変わらない
セッションの保存先を変更したい
と思い、php.iniのsession.save_pathの値を変更してみたのだが、変化がなかった。
php.inisession.save_path = "/home/test/session"Master ValueとLocal Value
phpinfoを見てみると、「Master Value」のほうは変更されていたが、「Local Value」のほうが変更されていなかった。
調べてみると、どうやらphp.iniより優先されるファイルがあるらしい。
php.ini < httpd.conf < .htaccess < ini_set()
参考:https://qiita.com/yamadayamada_jp/items/22b358e2c8389d1e31ddなんだ他のところで上書きしてるだけかー
と思い、httpd.confと.htaccess見てみたが、見当たらない・・・
ini_set()もやってなさそう・・・conf.d/*.conf
どういうこったーと色々見ていると、httpd.conf内に
httpd.conIncludeOptional conf.d/*.confと記述が・・・!
/etc/httpd/conf.d/php〇〇-php.conf(※〇〇はphpのバージョンによります)
にいました。/etc/httpd/conf.d/php〇〇-php.confphp_value session.save_path "/var/opt/remi/php70/lib/php/session"そんなところにいたんかい!
ということで、ここを書き換えて見事反映。
因みに、.htaccessやiniset()で上書きされないように「PHP_Admin_Value」というものもあるようです。
参考:https://www.php.net/manual/ja/configuration.changes.php
- 投稿日:2020-09-18T16:59:54+09:00
Laravel id管理 パラメーターの{id}なんとなく振り当ててない?
パラメータ系の記事でよく見るこんなルーティング
Route::get('/post/{id}', 'TopController@detail');初心者のワイ:はぁ(0_0)/
脳死状態で記述していたので意味調べました!!!!
指定されたコントローラの関数(TopController@detail)で'Request $request'でリクエスト受け取ります。
このリクエストの中に$request->idというものが生成されています。それが{id}の正体だ!!!!
仮に{id}を{sushi}に変更します
Route::get('/post/{sushi}', 'TopController@detail');それでコントローラーでdd($request->id)で受け取れてるか確認
結果:nulldd($request->sushi)
結果:id表示これで{id}が$request->idであるということの裏付けができましたね!!!!
これが初投稿です!
何かお役に立てれば幸いです!
- 投稿日:2020-09-18T15:08:40+09:00
【Laravel】クエリ実行前にMySQLのDBコネクションのPDOにsetAttributeする。
メモとして残します。
■やり方
下記の例では現在のDBコネクションに
PDO::ATTR_EMULATE_PREPARES
をtrueでセットしています。(\DB::connection()->getPdo())->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);■余談
laravelでは
PDO::ATTR_EMULATE_PREPARES
はデフォルトFalseですが、
LOAD DATA LOCAL INFILE
ステートメントを実行するときにエラーになってしまうため、PDO::ATTR_EMULATE_PREPARESをTrueにしてやる必要があります。
しかし、configのdatabase.phpで常にtrueにするのはさすがにちょっと、、、
と、なったなっため、瞬間的にTrueにすることで解決しました。
- 投稿日:2020-09-18T13:51:08+09:00
【PHP】Valitronの使い方と独自ルールの追加方法
概要
PHPのバリデーションライブラリValitronを使ったときのメモです。
準備
Composerでインストールします。
インストールしたいディレクトリで以下を実行します。php composer.phar require vlucas/valitron
・vendor/vlucas(ディレクトリ)
・composer.json
・composer.lockが生成されていればインストール完了です。
実装
// $dataには検証したいデータの配列が入る想定(POSTの値等) $data = [ 'name' => '山田太郎', 'kana' => 'ヤマダタロウ', 'email' => 'hoge@example.com', ]; // ライブラリ読み込み require_once('path/to/vendor/autoload.php'); // メッセージの日本語化 Valitron\Validator::lang('ja'); // 検証する値を引数にインスタンスを生成 $validation = new Valitron\Validator($data); // 項目名を設定 $validation->labels([ 'name' => '名前', 'kana' => 'フリガナ', 'email' => 'メールアドレス' ]); // バリデーションルール $validation->rule('required', ['name', 'kana', 'email']) ->message('{field}は必須項目です。'); $validation->rule('lengthMax', ['name', 'kana'], 50) ->message('入力可能な文字数は50字までです。'); $validation->rule('email', 'email') ->message('正しいメールアドレス形式で入力してください。'); $validation->rule('regex', 'kana', '/^[ ァ-ヴー]+$/u') ->message('カタカナで入力してください。'); // バリデーションの実行 if(!$validation->validate()) { echo 'バリデーションエラーです。'; } // エラー内容の入った配列 var_dump($validation->errors());
複数のバリデーションに引っかかることもあるので、1つだけ返すようにしたりもします。public function validation($data) { // 諸々のバリデーションの処理 : $err_msg = []; if(!$validation->validate()) { foreach ($validation->errors() as $key => $value) { // 1つめのエラーだけを代入 $err_msg[$key] = $value[0]; } } return $err_msg; }
【項目名の設定】
$validation->labels
では、項目名の設定ができます。
message部分で{field}を使用する際、項目名設定が無い場合は配列のキー名がそのまま使用されるので、「nameは必須項目です」のようになります。そのため、項目の別名(ラベル)を設定します。
【エラーの結果】
$data
にルールに反する入力項目を入れた場合の$validation->errors()
の中身です。
項目ごとに引っかかったバリデーションのエラーメッセージが格納されます。array(3) { ["name"]=> array(1) { [0]=> string(45) "名前は必須項目です。" } ["kana"]=> array(2) { [0]=> string(47) "入力可能な文字数は50字までです。" [1]=> string(42) "カタカナで入力してください。" } ["email"]=> array(1) { [0]=> string(66) "正しいメールアドレス形式で入力してください。" } }ルールについて
基本はValitron:公式Githubに、すでに用意されているルールについて記載があります。
入力必須、文字数、パスワードなどの確認入力、正規表現などが用意されています。また、
required
に関しては、半角スペースのみの場合はエラーになりますが、全角スペースは入力としてみなされるようです。
【参考】
以下でも分かりやすくルールや設定について書かれています。
・シンプルで使いやすい!バリデーションライブラリ「Valitron」の使い方独自ルールの追加方法
独自のルールはインスタンスを生成する前に定義を行います。
今回は半角・全角スペースのみの入力をNGとするルールを作ります。validation.php// 独自ルールの追加 Valitron\Validator::addRule('spaceOnly', function($field, $value) { // 値の半角・全角スペースを削除 $replace = preg_replace('/[\s ]*/', '', $value); // 空でなければtrue if (!empty($replace)) { return true; // trueは必ず返す } else { return false; } }, '空白文字のみの入力は出来ません。'); // 検証する値を引数にインスタンスを生成 $validation = new Valitron\Validator($data); : : if (!empty($data[$name])) { $validation->rule('spaceOnly', $name, $data['name']) ->message('空白文字のみの入力は出来ません。'); }
【独自ルールの判定】
ルールに関数を渡して処理した結果でバリデーションをかけることができます。公式の例のようにやってみましたが、falseのみを返す場合うまく挙動せず、基本的に独自ルールではtrueを返すか、どちらも明示的に返すのが良いかと思います。【エラーメッセージ】
addRule
の第三引数にはエラー時のメッセージを指定できます。
ただし、文頭にラベルが勝手に付きます。例えば「お名前 空白文字のみの入力は出来ません。」のような出力になります。
{field}を使えばラベルの位置は変更可能です。指定しない場合は「お名前 Invalid」となります。
なので、基本的には$validation->ruleのmessage()
の方で指定が良いかと思います。参考
・シンプルで使いやすい!バリデーションライブラリ「Valitron」の使い方
・validatorjsとValitronのカスタムルールを作成する
・PHP Valitron Validator::addRule Examples
- 投稿日:2020-09-18T11:45:03+09:00
Laravel8 (laravel/ui)でのLogin機能の実装方法〜MyMemo
Laravle6.x/7.x/8.xのログイン実装コマンドの違いを見る
みなさんこんにちは
ジーズアカデミー 主席講師 山崎ですm(_ _)m
今回はLaravel8にアップデートされLogin画面作成(laravel/ui)を前バージョン同様で使用したい場合
の方法をMemoしておきます(初めてLaravel触る人はこっちが良いかも、、敷居が低い)。「jetstreamの人はこちらのリンク」
https://qiita.com/daisu_yamazaki/items/607ea579a374c4187562前提条件/検証環境
- LaravelでCRUDを作成した経験がある人
- Laravelの基本を理解している人
- 記事内容的には、Laravel6のAuthを使う場合の自分メモです。
- Laravel6/7=PHP 7.2.x(確認した環境)
- Laravel8 =PHP 7.3.x(確認した環境)
- EC2の場合:t2.small (メモリ2G以上必要 "laravel/ui"に必要なため,t2.microだとコケます)
- Node.js インストール済みであること
【 Laravel6/7/8でのログイン(laravel/ui)画面作成】
Laravel5.xでは「php artisan make:auth」コマンドで簡単にLOGIN機能を作成できていました。
※Laravel6.x以降 php artisann make:auth コマンドは無くなりました。
Laravel6 / Laravel7 / Laravel8 ログイン画面作成
1. laravel/uiをインストール
【要注意】Laravel7 が出たタイミング・・・だと思いますが、
laravel/ui コマンドにバージョンを付けないとエラーがでるようになりました!!!
6 or 7 or 8 に合わせて使い分けてください!!ターミナル#Laravel6.x 公式ではこちらに変わってました。 composer require laravel/ui:^1.0 --dev #laravel7の場合 composer require laravel/ui:^2.4 #laravel8の場合 composer require laravel/ui※Laravel6.x 公式
https://laravel.com/docs/6.x/frontend#introduction
※Laravel7.x 公式
https://laravel.com/docs/7.x/frontend#introduction
※Laravel8.x 公式(解説が無いようですが、Updating Dependenciesを参照)
https://laravel.com/docs/8.x/upgrade#updating-dependencies2. LOGIN機能&テーブル作成
ターミナルphp artisan ui vue --auth php artisan migrate3. FrontEndに必要なPackageをインストール
(Node/npmの使用が必要)ターミナルnpm install4. CSS/JSを作成ビルド
ターミナルnpm run dev
welcome R egister Login これでLaravel5/6/7どうようのLOGIN機能が実装できました!
「Laravel DB.com」 をやってます
Laravelをテーブル設計するだけでMigrationが作成できるツール
https://qiita.com/daisu_yamazaki/items/4e13ac43c20bcdedeb40
※是非こちらも見てください~。今回のLogin機能:参考「Laravel ドキュメント」
【ver6.x】https://laravel.com/docs/7.x/frontend#introduction
【ver7.x】https://laravel.com/docs/6.x/frontend#introduction
【ver8.x】https://laravel.com/docs/8.x/upgrade#updating-dependencies
※Laravel8.x 公式(2020/09/17段階では解説が無いようです...Updating Dependenciesを参照)以上
- 投稿日:2020-09-18T10:56:05+09:00
Laravel8で「laravel6/7」と一緒のlaravel/ui ログインを使う場合
Laravle6.x/7.x/8.xのログイン実装コマンドの違いを見る
みなさんこんにちは
ジーズアカデミー 主席講師 山崎ですm(_ _)m
今回はLaravel6(LTS)/7/8にアップデートされLogin画面作成に困った解決策をMemoしておきます。前提条件/検証環境
- LaravelでCRUDを作成した経験がある人
- Laravelの基本を理解している人
- 記事内容的には、Laravel6のAuthを使う場合の自分メモです。
- Laravel6/7=PHP 7.2.x(確認した環境)
- Laravel8 =PHP 7.3.x(確認した環境)
- EC2の場合:t2.small (メモリ2G以上必要 "laravel/ui"に必要なため,t2.microだとコケます)
- Node.js インストール済みであること
【 Laravel6/7/8でのログイン(laravel/ui)画面作成】
Laravel5.xでは「php artisan make:auth」コマンドで簡単にLOGIN機能を作成できていました。
Laravel6.x以降 php artisann make:auth は無くなりました。
Laravel6 / Laravel7 / Laravel8 ログイン画面作成
1. laravel/uiをインストール
【要注意】Laravel7 が出たタイミング・・・だと思いますが、
laravel/ui コマンドにバージョンを付けないとエラーがでるようになりました!!!
6 or 7 or 8 に合わせて使い分けてください!!ターミナル#Laravel6.x 公式ではこちらに変わってました。 composer require laravel/ui:^1.0 --dev #laravel7の場合 composer require laravel/ui:^2.4 #laravel8の場合 composer require laravel/ui※Laravel6.x 公式
https://laravel.com/docs/6.x/frontend#introduction
※Laravel7.x 公式
https://laravel.com/docs/7.x/frontend#introduction
※Laravel8.x 公式(解説が無いようですが、Updating Dependenciesを参照)
https://laravel.com/docs/8.x/upgrade#updating-dependencies2. LOGIN機能&テーブル作成
ターミナルphp artisan ui vue --auth php artisan migrate3. FrontEndに必要なPackageをインストール
(Node/npmの使用が必要)ターミナルnpm install4. CSS/JSを作成ビルド
ターミナルnpm run devこれでLaravel5バージョンからのLOGIN機能が実装できました!
Login機能:参考「Laravel ドキュメント」
【ver6.x】https://laravel.com/docs/7.x/frontend#introduction
【ver7.x】https://laravel.com/docs/6.x/frontend#introduction
【ver8.x】https://laravel.com/docs/8.x/upgrade#updating-dependencies
※Laravel8.x 公式(2020/09/17段階では解説が無いようです...Updating Dependenciesを参照)★研究開発「Laravel DB.com」 を運用中
Laravelをテーブル設計するだけでCRUDが作成できるツール
https://qiita.com/daisu_yamazaki/items/4e13ac43c20bcdedeb40
※是非応援しください。以上
- 投稿日:2020-09-18T09:19:37+09:00
WindowsでMAMPをインストールする
PHPの学習の為にWindows10にMAMPをインストール
初期設定の覚書MAMP公式サイトにてWindows verを選択
Downloadしてexeファイルを解凍
開いた画面で進んでいくとMAMP Proを使用する
App Bonjour~を使用する
の項目に既にチェックが入っているので外しておく。(proは有料)その他は普通のアプリケーションのインストーラーと同じように進むので割愛
Cドライブにインストールインストール完了したら
Windows設定画面>システム環境変数の編集>環境変数
Path>編集>新規
C:\MAMP\bin\php
を作成MAMPを開いて画面左上のMAMP>Preferenceからportをデフォルトにを選択
apache:8888
Nginx:7888
MySQL:8889
が設定できればOKこれで最初の画面に戻ると左側のApacheSERVER/MySQLSERVER自動的につながるはず
一応セキュリティ面も不安なので少し変更を…
WinExplorer>C:>MAMP>conf>apache>httpd.conf
を開いて接続先を自分のパソコンだけにする
元々あった部分はコメントアウトしてあとは画像通りのコードを書き足す。MAMPのMySQLのパスも設定したいが悪戦苦闘した挙句なぜかwebブラウザでphpMyadminが開けなくなってしまったので解決できるようになったら設定する。
ちなみに
MAMPはWindowsとの相性悪いのか?なんなのかMySQL SERVERが止まらなくなってしまうことがある様…
MAMPを閉じる前に必ずSERVER STOPをする。
どうしても止まらなくなったら
C:>MAMP>db>mysqlフォルダにある
mysql-bin.0000001
mysql-bin.0000002
mysql-bin.indexみたいなファイルを削除すると終了できる(自己責任で)
- 投稿日:2020-09-18T01:10:24+09:00
Ubuntu+Nginx (+PHP) でクライアント証明書を発行するWebサイト
防備録です。
PHPから openssl を叩いていますが、直接openssl
を叩くときのコマンドもコメントに併記しています。最終的にしたいこと
以下のような流れです。
- サーバが鍵ペアを発行する。
- クライアントは鍵ペアをブラウザに登録する。
- 以降はその公開鍵を用いてユーザを識別・認証する。
準備
Ubuntuの準備
ConoHa で Ubuntu20.04 をインストールし、ユーザを追加した状態からスタートします。この例では、ユーザ名は
yukatayu
、ドメインがssl-test.yukatayu.tech
で登録してある状態で操作しています。適宜読み替えてください。とりあえず使いそうなものを入れます。特に nginx と openssl と letsencrypt が入っていれば良さそう。PHP は、とりあえず apt で楽に入る
php7.4-fpm
を入れました。sudo apt update sudo apt upgrade -y sudo apt install -y vim tree make git nginx openssl php7.4-fpm letsencryptCA鍵の生成
とりあえず作業フォルダを作ります。
sudo mkdir /var/client_cert sudo chown yukatayu /var/client_cert cd /var/client_cert鍵ペアを作ります。楕円曲線の名前は
512
と見せかけて521
なので注意してください。openssl ecparam -genkey -name secp521r1 -out ca.key鍵ペアにパスワードを付けます。今回は
yukatayu
にしました。openssl ec -in ca.key -out ca.key -aes256鍵ペアを元に証明書を作ります。とりあえず有効期限は100年にします。
openssl req -new -x509 -days 36500 -key ca.key -out ca.crtパラメータは以下のようにしました
項目 自分が設定した値 Country Name JP State or Province Name Tokyo Locality Name Meguro Organization Name Yukatayu Project Organizational Unit Name Engineering Department Common Name ssl-test.yukatayu.tech Email Address (自分のメアド) 読み取り権限をつけておきます。実際の運用ではセキュリティをもっといい感じにしておいてください。
chmod a+r ca.*nginx のセットアップ
面倒なので、このセクションだけは root 権限で操作します。
sudo su - cd /etc/nginxサーバ証明書を発行します。とりあえずメアドを設定しないモードにしています。
設定したい場合は--non-interactive
と--register-unsafely-without-email
を外してください。certbot certonly \ --standalone \ --non-interactive \ --agree-tos \ --register-unsafely-without-email \ --domains ssl-test.yukatayu.tech \ --pre-hook 'systemctl stop nginx' \ --post-hook 'systemctl start nginx'ここで
IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at ...みたいなことを言われたら成功しています。
次に nginx を雑に設定していきます。
vim sites-available/ssl-test.yukatayu.tech
ssl-test.yukatayu.tech (クリックして展開)
server { listen 80; listen [::]:80; server_name ssl-test.yukatayu.tech; location / { return 302 https://$host$request_uri; #301でも良さそう } } server { server_name ssl-test.yukatayu.tech; root /var/www; ssl_certificate /etc/letsencrypt/live/ssl-test.yukatayu.tech/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/ssl-test.yukatayu.tech/privkey.pem; ssl_client_certificate "/var/client_cert/ca.crt"; ssl_verify_client optional; # onだと常時 location / { # 認証不要 } location /private/ { # 認証が必要 if ($ssl_client_verify != SUCCESS) { return 403; } } location ~ \.php$ { #fastcgi_pass 127.0.0.1:9000; fastcgi_pass unix:/run/php/php7.4-fpm.sock; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; fastcgi_param SSL_CLIENT_I_DN $ssl_client_i_dn; fastcgi_param SSL_CLIENT_S_DN $ssl_client_s_dn; fastcgi_param SSL_CLIENT_F_PR $ssl_client_fingerprint; } include /etc/nginx/snippets/ssl.conf; }最初の8行は、
http://
にアクセスが来たらhttps://
にリダイレクトする設定で、必須ではないです。
その後にあるssl_certificate
とssl_certificate_key
はサーバ証明書、ssl_client_certificate
とssl_verify_client
はクライアント証明書の設定です。
その下の行で、/private/
のみ認証が必要にしています。そして2つ目のポイントで、fastcgi_param
が3つ並んでいる箇所は、クライアント認証の認証情報を PHP に受け渡しています。詳しくは 公式サイト を参照してください。次に、SSL のいつもの設定をしていきます。
vim snippets/ssl.conf
ssl.conf (クリックして展開)
listen 443 ssl http2; listen [::]:443 ssl http2; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_prefer_server_ciphers on; ssl_session_cache shared:le_nginx_SSL:1m; ssl_session_timeout 1d; ssl_session_tickets off; gzip on; gzip_types text/plain text/xml text/css application/xml application/xhtml+xml application/rss+xml application/atom_xml application/javascript application/x-javascript application/x-httpd-php; gzip_disable "MSIE [1-6]\."; gzip_disable "Mozilla/4"; gzip_comp_level 1; gzip_proxied any; gzip_vary on; gzip_buffers 4 8k; gzip_min_length 1100; index index.html index.htm index.php; ## Static Resources location ~* \.(css|js|jpeg|jpg|gif|png|ico)$ { expires 3d; break; } location ~ /\.ht { deny all; } location = /robots.txt { access_log off; log_not_found off; } location = /favicon.ico { access_log off; log_not_found off; } # OCSP Stapling --- # fetch OCSP records from URL in ssl_certificate and cache them ssl_stapling on; ssl_stapling_verify on; ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS!DH';
ssl_ciphers
は好みに合わせて変更してください。ラインナップが少し古めですが、現時点(2020年)では十分強いはずです。設定ファイルを有効化します。
cd sites-enabled rm default ln -s /etc/nginx/sites-available/ssl-test.yukatayu.tech設定ファイルをチェックします。
nginx -t # > nginx: the configuration file /etc/nginx/nginx.conf syntax is ok # > nginx: configuration file /etc/nginx/nginx.conf test is successful大丈夫そうなら nginx を再起動します。
systemctl restart nginxPHP を書く
su
状態の人は戻ってください。別に戻らなくてもいいですけれど。
ここからはopensslを叩くだけです。とりあえず nginx でroot
に指定した位置にフォルダを作ります。mkdir -p /var/www sudo chown yukatayu /var/www cd /var/www鍵発行部分の作成
vi keygen.phpコードを書きますが、PHPのコードをコマンドと勘違いすることは無いと思うので折りたたみ無しで書きます。流れとしては先ほどと同じですが、ルートCA証明書で署名する工程と、 pfx ファイルに固める工程が増えています。
$dn
とopenssl_csr_sign
の第 4, 6 引数、及び$password
、$friendlyName
は、発行する相手に合わせて変えてください。あと、
$caPrevPw
は、先程CAキーに付けたパスワードです。この場合はyukatayu
です。<?php // クライアント証明書用の鍵 // openssl ecparam -genkey -name secp521r1 -out ca.key // RSA が好きなら openssl genrsa -des3 -out user.key 4096 $privateKey = openssl_pkey_new([ 'private_key_bits' => 512, // RSAの 15360 bit くらいの強さらしい 'private_key_type' => OPENSSL_KEYTYPE_EC, 'curve_name' => 'secp521r1', // RSA が好きなら // 'private_key_bits' => 4096, // 'private_key_type' => OPENSSL_KEYTYPE_RSA, ]); // 署名 // openssl req -new -key user.key -out user.csr $dn = [ 'countryName' => 'JP', 'stateOrProvinceName' => 'Tokyo', 'localityName' => 'Meguro', 'organizationName' => 'Yukatayu', 'organizationalUnitName' => 'Some Team', 'commonName' => 'yukatayu.tech', 'emailAddress' => 'yukatayu@example.com', ]; $csr = openssl_csr_new( $dn, $privateKey, [ 'digest_alg' => 'sha256', ]); // CSRの署名 // openssl x509 -req -days 365 -in user.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out user.crt $caCert = '/var/client_cert/ca.crt'; $caPrev = '/var/client_cert/ca.key'; $caPrevPw = 'yukatayu'; $x509 = openssl_csr_sign( $csr, "file://{$caCert}", ["file://{$caPrev}", $caPrevPw], 3650, // days ['digest_alg' => 'sha256'], 1 // serial ); // PKCS #12 (PFX)の作成 // openssl pkcs12 -export -out user.pfx -inkey user.key -in user.crt -certfile ca.crt $password = 'nyan'; $friendlyName = 'Yukatayu Secret Key'; $pkcs12 = null; openssl_pkcs12_export( $x509, $pkcs12, $privateKey, $password, [ // 'extracerts' => $CAcert, 'friendly_name' => $friendlyName, ]); // 出力 header('Content-Type: application/x-pkcs12'); header('X-Content-Type-Options: nosniff'); header('Content-Length: ' .strlen($pkcs12)); header('Content-Disposition: attachment; filename="yukatayu_tech_client.pfx"'); header('Connection: close'); print($pkcs12); exit();
curve_name
はprint_r(openssl_get_curve_names());
などをすることで分かります。また、対応する openssl のコマンドをコメントで記述しておきましたので、これらをして手で生成することができます。private エリアの生成
mkdir private cd private vim index.phpとりあえず認証情報を雑に表示するだけです。クライアント証明書なしの場合は nginx で弾かれます。それと、コメント行は表示例です。
<pre> Welcome: SSL_CLIENT_I_DN: <?= $_SERVER['SSL_CLIENT_I_DN'] ?> <!-- emailAddress=yukatayu.dev@gmail.com,CN=ssl-test.yukatayu.tech,OU=Engineering Department,O=Yukatayu Project,L=Meguro,ST=Tokyo,C=JP --> SSL_CLIENT_S_DN: <?= $_SERVER['SSL_CLIENT_S_DN'] ?> <!-- emailAddress=yukatayu@example.com,CN=yukatayu.tech,OU=Some Team,O=Yukatayu,L=Meguro,ST=Tokyo,C=JP --> SSL_CLIENT_F_PR: <?= $_SERVER['SSL_CLIENT_F_PR'] ?> <!-- b6b84c9573998e096d1bea593c79b0dbae862145 -->動作確認
アクセス制限の確認
とりあえず
ssl-test.yukatayu.tech/private/
にアクセスしてみると 403 が返ります。鍵ペアを発行する
ブラウザから
ssl-test.yukatayu.tech/keygen.php
にアクセスすると pfx ファイルが降ってきます。鍵ペアをブラウザに登録する
私はとりあえずFirefox派なので、その手順を説明します。
まずブラウザの設定を開きます。「プライバシとセキュリティ」から「証明書を表示…(C)」を押します。「あなたの証明書」から「インポート(M)…」を押し、先程の pfx ファイルを開きます。
上記のコードでは$password = 'nyan';
となっているので、パスワードのnyan
を入力するとインポートできます。アクセスしてみる
ssl-test.yukatayu.tech/private/
にアクセスしてみると、「個人証明書の要求」というプロンプトが出るはずです。 出ない場合は Shiftを押しながら リロードしてみてください。
先程インポートした証明書を選択して OK を押すと、多分アクセスできるはずです。おわりに
クライアント証明書が流行らない理由がわからないので、誰か教えてください。
それと今回のは説明用なのでなんか雑です。実戦投入したい場合はセキュリティの専門家にきちんと相談してください。
- 投稿日:2020-09-18T00:38:50+09:00
Laravel 設定ファイルの内容を呼び出す
目的
- Laravelの設定ファイルへの追記方法と設定ファイルの読み込み方法をまとめる
- ※本説明でいう設定ファイルとは.envファイルではなく、
アプリ名ディレクトリ/config
直下にあるファイルを指す実施環境
- ハードウェア環境
項目 情報 OS macOS Catalina(10.15.5) ハードウェア MacBook Pro (13-inch, 2020, Four Thunderbolt 3 ports) プロセッサ 2GHzクアッドコアIntel Core i5 メモリ 32 GB 3733 MHz LPDDR4 グラフィックス Intel Iris Plus Graphics 1536 MB
- ソフトウェア環境
項目 情報 備考 PHPバージョン 7.4.3 Homwbrewを用いて導入 Laravelバージョン 7.0.8 commposerを用いてこちらの方法で導入→Mac Laravelの環境構築を行う MySQLバージョン 8.0.19 for osx10.13 on x86_64 Homwbrewを用いてこちらの方法で導入→Mac HomebrewでMySQLをインストールする 前提条件
- 実施環境に記載した環境、またはそれに準ずる環境が用意されておりLaravelアプリが作成されていること。
前提情報
- 筆者は下記の記事で作成したアプリを用いて本記事の動作を確認する。
- 下記に本記事を記載する際に検証で使用したソースコードのリモートリポジトリのリンクを下記に記載する。
読後感
アプリ名ディレクトリ/config
直下の設定ファイルに独自の設定を追記することができる。アプリ名ディレクトリ/config
直下の設定ファイルに記載されている値を読み込み表示することができる。概要
- 設定ファイルの作成と記載
- ルーティング情報の追記
- コントローラファイルの作成と記載
- ビューファイルの作成と記載
- 確認
詳細
設定ファイルの作成と記載
アプリ名ディレクトリで下記コマンドを実行して設定ファイルを作成する。
$ vi config_test.php開いたファイルに下記の内容を追記し保存して閉じる。
アプリ名ディレクトリ/config/config_test.php<?php return [ # 文字列の設定 'config_str' => 'これは設定ファイルで設定された文字列です。', ] ?>ルーティング情報の追記
アプリ名ディレクトリで下記コマンドを実行してルーティングファイルを開く。
$ vi routes/web.php下記の内容を追記する。
アプリ名ディレクトリ/routes/web.phpRoute::get('/config_check', 'ConfigCheckController@config_check')->name('config_check');コントローラファイルの作成と記載
アプリ名ディレクトリで下記コマンドを実行してコントローラファイルを作成する。
$ php artisan make:controller ConfigCheckControllerアプリ名ディレクトリで下記コマンドを実行してただいま作成したコントローラファイルを開く。
$ vi app/Http/Controllers/ConfigCheckController.php下記の様に記載を行う。
アプリ名ディレクトリ/app/Http/Controllers/ConfigCheckController.php<?php namespace App\Http\Controllers; use Illuminate\Http\Request; // 下記を追記する use Illuminate\Support\Facades\Config; class ConfigCheckController extends Controller { // 下記を追記する public function config_check() { // アプリ名ディレクトリ/config直下に存在するconfig_test.phpファイルで定義されているconfig_strの文字列を$strに格納する処理 $str = Config::get('config_test.config_str'); return view('checks.config_check', [ 'str' => $str, ]); } // 上記までを追記する }ビューファイルの作成と記載
アプリ名ディレクトリで下記コマンドを実行してビューファイルを格納するディレクトリを作成する。
$ mkdir resources/views/checksアプリ名ディレクトリで下記コマンドを実行してビューファイルを作成する。
$ vi resources/views/checks/config_check.blade.php開いたビューファイルに下記の内容を記載する。
アプリ名ディレクトリ/resources/views/checks/config_check.blade.php{{ $str }}確認
アプリ名ディレクトリで下記コマンドを実行してローカルサーバを起動する。
$ php artisan serveブラウザで下記にアクセスする。(Authの認証機能が付与されているLaravelアプリで下記にアクセスする場合、ログインが必要になる場合がある。)
下記の様に、設定ファイルに記載した内容がブラウザ上で表示されていれば作業完了である。
*画像
参考文献
- 投稿日:2020-09-18T00:30:54+09:00
[PHP]LINE bot開発でのデバッグ
今回の題
今回は完全に個人的なメモです。
LINEbotのsdkなどに関する説明等はいたしません。どうやるのか
受け取ったリクエストの内容をerror_logでログファイルに書き出し、ブラウザ上で確認できるようにする。
error_log(print_r($event, true) . '\n', 3, '書き込むログファイルへのパス');以下は全体像。
<?php require('vendor/autoload.php'); use LINE\LINEBot\Constant\HTTPHeader; use LINE\LINEBot\HTTPClient\CurlHTTPClient; use LINE\LINEBot; $http_client = new CurlHTTPClient(チャネルアクセストークン); $bot = new LINEBot($http_client, ['channelSecret' => チャネルシークレット]); $signature = $_SERVER['HTTP_' . HTTPHeader::LINE_SIGNATURE]; $request_body = file_get_contents('php://input'); $events = $bot->parseEventRequest($request_body, $signature); $event = $events[0]; error_log(print_r($event, true) . '\n', 3, '書き込むログファイルへのパス');このログファイルをブラウザで表示させると、以下のように表示される。
LINE\LINEBot\Event\MessageEvent\TextMessage Object ( [emojis:LINE\LINEBot\Event\MessageEvent\TextMessage:private] => [message:protected] => Array ( [type] => text [id] => XXXXXXXXX [text] => テスト ) [event:protected] => Array ( [type] => message [replyToken] => XXXXXXXXX [source] => Array ( [userId] => XXXXXXXXX [type] => user ) [timestamp] => 1600355946638 [mode] => active [message] => Array ( [type] => text [id] => XXXXXXXXX [text] => テスト ) ) )以上!
一言
息抜きにLINEbotを作成中です。
もっといいデバッグ方法があればコメントにお願いいたします?♀️