- 投稿日:2020-02-21T21:48:57+09:00
CakePHPでの同時ログイン禁止
タイトルの通り、同時ログインを禁止したいときの処理について。
コードは会社にあるので概要だけだが、簡単な内容なので困らないと思う。知らないうちに第三者に勝手にログインされているのはセキュリティ上も怖いので、2重ログインが必要なアプリでなければ実装しておきたい。
いつも頼りにしているスタッコオーバーフローであまり良いスレッドが見つけられず、結局普通に自分で作った。
基本方針
- 後でログインしたセッションを有効とし、過去のセッションは全て強制ログアウトする
- sessionはDB保存している場合を想定
- ログイン時、DBから過去の同一ユーザーのsessionsを削除する(=強制ログアウト)
sessionsテーブルにカラム追加
CakePHP標準のsessionテーブルにはid ,dataカラムがあるが、idはCookieのセッションID(ランダムな文字列)、dataはシリアライズされたセッションデータになっている。
すなわち、どのユーザーのデータか単純に調べられず、過去セッションの削除が簡単にできないため、追加カラム user_idを持たせる。
もし複数アプリでDB共用する場合、applicationカラムも必要。user_id INT, application vachar(255), #複数アプリでDB共用する場合のみ必要カスタムSession Handlerを作成&設定
sessionsテーブルのuser_idに自動で書き込むため、カスタムハンドラを作成。
Cookbookのカスタムセッションハンドラーの作成をベースにすれば簡単に作れる。(自分で書くのは数行くらい)
必要なのはwrite()のみで、ここで継承元のDatabaseSessionを見つつ、
user_idを書き込むように処理を追加する。
またapp.php等に設定も追加する。なお、良いデータ取り回しが今一わからないので、Controllerからuser_idを伝えるのには
Configure::write(), read()で行ったが、終了時(?) Configureのデータがほぼ空になるタイミングでもwrite()が呼ばれるようなので、データがあるか否か確認してから書き込みを行う必要がある。
(何も考えずにConfigure::read()を放り込むと、nullで上書きされてしまう)※Behaviorでもできると思うが、意味的にハンドラの方が良いと思う
コントローラからuser_idをSession Handlerに伝える
ログイン処理(&認証不要処理)アクション、またAppController - isAuthorized()あたりでuser_idを伝えるようにする。
良い方法が思いつかず、Configure::write()/read()でやった。
Singletonかstaticでの情報受け渡し用クラスを作るのが正しいか?追記
AuthComponentを呼べないという意味ではModelでも同じなので、その線でStackOverflowやgithub検索してみたものの、やはりConfigureかstaticでの受け渡し用クラス作る位しか見つけられなかった。ログイン時の過去セッション削除
ログイン処理時、そのuser idの過去セッションをsessionsテーブルから全削除する。
これにより、過去セッションは全てログアウトされる。
※ログアウト処理($this->Auth->logout())でもsessionテーブルのデータを消している
※このタイミングでは今回ログインのデータはまだ書き込まれていないようだが、バージョンによるかもしれない。今回ログインも消える場合は最新以外を消すよう調整。$user = $this->Auth->identify(); if($user){ ログイン成功時の処理... (追加) Sessionsテーブルから user_id = $user['id'] のデータを全削除 (deleteAll) }
- 投稿日:2020-02-21T19:53:33+09:00
EclipseでPHPを開発できるようにする
この記事は以下の記事の続きです
Eclipseのインストール~Java(PHP)の実行まで - Qiitaこの記事でできること
- 既にEclipse(Java環境構築済み)・XAMPPがインストールされている状態でphpの開発ができるようになる。
PHP Development Tools(PDT)のインストール
現状ではPHPプロジェクトは作成できないのでPDTをインストールする。
▼作業タイプはEclipseのバージョン(今回は2019-12)。[プログラミング]→[PHP開発ツール(PTD)]を選択し、次へ
PHPプロジェクトの作成・実行
▼プロジェクト名を入力して「次へ」。JavaScriptのコード補間を使いたいのでJavaSvriptサポートにチェックを入れておいた
パースペクティブがJavaのままだったので切り替える
▼右上のアイコンをクリックすると「パースペクティブを開く」のウィンドウが出てくる。「PHP」を選択し、「開く」。
▼ソースを書くファイルを作成。画面左の「パッケージエクスプローラー」で右クリック→「新規」→「PHPファイル」
▼テンプレートファイルを使用することができる。今回は使用せずに「完了」
実際にコードを書く。
hellowWorld.php<?php echo "Hellow World!!"; ?>ソースを実行する
▼プロジェクト・エクスプローラーのソースを右クリックし「実行」→「サーバーで実行」
▼サーバーを選択する。デフォルトで「PHPビルトイン・サーバー」が選択されているはず。「完了」を押下
▼PHPが実行された。サーバーが動いていれば出力されたURLにWebブラウザからアクセスしても同様に表示される。
以上
- 投稿日:2020-02-21T19:14:42+09:00
【Laravel】DBのレコードを元に生成したcsvのダウンロードを行うためのController
やりたいこと
Controller内でデータを取得し、csvのレスポンスを生成して返すControllerを作成します。
どこかのストレージにすでに存在するcsvをレスポンスとして返すものとは少々異なります。実装
モデル
扱うデータ用オブジェクトは下記のものします。
app\Models\Person.php<?php namespace App\Models; use Illuminate\Database\Eloquent\Model; class Person extends Model { protected $table = 'persons'; protected $fillable = [ 'name', 'age' ]; }ルーティング
リクエストをControllerにつなぎこみます。
ここは普通にGETリクエストを行う場合と同じやり方。routes/web.phpRoute::get('/persons/download/csv', 'PersonController@download_csv');コントローラー
ここでレスポンスでcsvを返す処理を書きます。
app\Http\Controllers\PersonController.php<?php namespace App\Http\Controllers; use Illuminate\Routing\Controller; use Illuminate\Support\Facades\Schema; use App\Models\Person; class PersonController extends Controller { public function download_csv(Request $request) { $persons = Person::all(); $persons = $persons->toArray(); // 全カラム名を配列で取得 $header = Schema::getColumnListing((new Person)->getTable()); // レスポンスストリームにcsv用のデータを書き込み $stream = fopen('php://temp', 'r+b'); fputcsv($stream, $header); foreach ($persons as $row) { fputcsv($stream, $row); } rewind($stream); $csv = str_replace(PHP_EOL, "\r\n", stream_get_contents($stream)); $csv = mb_convert_encoding($csv, 'SJIS-win', 'UTF-8'); $headers = array( 'Content-Type' => 'text/csv', 'Content-Disposition' => "attachment; filename=persons.csv", // ファイル名 ); return Response::make($csv, 200, $headers); }これで、
/persons/download/csv
にアクセスすれば、csvがダウンロードされます。参考記事
- 投稿日:2020-02-21T17:53:29+09:00
composerでサードパーティライブラリを読み込む
composerでサードパーティライブラリを読み込み方法を解説します。carbonという時間操作ライブラリを教材に、サンプルコードを眺めながら進めていきます。なお、サンプルコードの実行にはPHP(7系統)、composerがインストールされている必要があります。
サンプルコード
https://github.com/kaidouji85/php-thrd-party-libサンプルコードを動かす
main.php<?php require("vendor/autoload.php"); use Carbon\Carbon; $tommorow = Carbon::now()->addDay(); print($tommorow);上記コードは、carbonという時間操作ライブラリを使用して実行日 + 1日を表示するプログラムです。なにはともあれ、まずはプログラムを動かしてみましょう。お手元の環境でコマンドラインを開いてください。
cd <作業フォルダ> git clone git@github.com:kaidouji85/php-thrd-party-lib.git php main.php
上記リポジトリにはcarbonが含まれていないので、エラーで落ちます。そんな欠陥リポジトリをアップしたのかよと思いますが、
composer install
を実行してみてください。composer install # vendor配下に色々とファイルがダウンロードされる php main.php今度は成功したと思います。
composer install
でcarbonをダウンロードできたのですが、ここで一つ疑問が生じます。同コマンドにはcarbonが一文字も含まれていませんが、なぜかvendorには正しいファイルが置かれています。carbonをダウンロードせよ、という命令はどこに書かれているのでしょうか。その答えはcomposer.jsonです。composer.json
composer.json{ "require": { "nesbot/carbon": "^2.30" } }composer.jsonを見ると、carbonとハッキリ書かれています。
composer install
はここを見て、必要なライブラリをダウンロードしていました。めでたし、めでたし......、ではありません。先ほどvendorフォルダにサードパーティライブラリがダウンロードされると言いましたが、念のために確認しておきましょう。
※vendor配下の中身は環境、実行日時によって微妙に違うことがあります。vendor配下にはcarbon以外のファイルが含まれています。これらはcomposerで内部的に必要となるおまじないなのかというと、それ以外も含まれます。例えばcarbonが内部的に使っているライブラリなどです。
依存ライブラリ
carbonが自分コードだけで完結しているかというと、そうではありません。carbonもサードパーティライブラリを使っています。下図のように、自分では1個だけライブラリを使っているつもりでも、依存関係を紐解くと沢山のライブラリが内部的に使われていることが分かります。
carbonの依存ライブラリを、少しだけ確認しましょう。
carbon
https://packagist.org/packages/nesbot/carbon「requires」がcarbonが依存しているライブラです。その中に「symfony/translation」となるので、これも見てみましょう。
symfony/translation
https://packagist.org/packages/symfony/translationsymfony/translationも「requires」には色々と書かれています。これをひたすら繰り返して、必要なライブラリを全てリストアップすると膨大な量になることは想像に難くないと思います。
バージョン指定問題
めでたし、めでたし、といきたいところですが、そうは問屋が卸しません。実はcomposer.jsonだと、
composer install
をした時期によって、ダウンロードされるライブラリのバージョンが微妙に違ってきます。もう一度、composer.jsonを見てみましょう。composer.json"nesbot/carbon": "^2.30"composerはセマンティックバージョンに準拠していますが、数字の前についている^が気になります。結論から言うと、
^2.30
という書き方だと2.30 <= (バージョン) < 3.0.0までがダウンロードされる可能性があります。例えば、上の書き方だと、2.5.1がダウンロードされることがあります。バージョン指定の詳細は、composer公式ドキュメントにまとめられています。composer バージョン指定
https://getcomposer.org/doc/articles/versions.md#summary公式ドキュメントによると、
2.30
と書けばそれ以外のバージョンがインストールされることはありません。これで問題が解決するのかというと、依存ライブラリがバージョン固定をしていないと同じ問題が起こります。少なくともcarbonの「requires」を確認するとバージョン固定をしていないので、carbonが依存しているライブラリはインストール時期によって微妙に異なる場合があります。上記の書き方が悪いとは一概に言えず、例えばバグフィックス版を自動的にインストールしてくれるというメリットがあります。ただ、そのメリットよりも、バージョン違いによるデグレの方が痛いですよね。この問題を解決するために、composerにはcomposer.lockという仕組みがあります。
composer.lock
composer.lockとはvendor配下に含まれる全てのライブラリを書き出したものです。もちろんバージョン情報もついているので、全部のライブラリのバージョンをそろえることが出来ます。先ほど
composer install
はcomposer.jsonを見ると言いましたが、より正確には初めにcomposer.lockを確認して、存在しない場合にcomposer.jsonを見る、という挙動をします。また、composer.jsonからダウンロードした場合にはcomposer.lockが作られます。オートロード
ここまでお膳立てができたら、後はライブラリを呼び出すだけです。vendor配下のnesbot/carbonをrequire_onceすれば大丈夫そうな気がしますが、それでは動きません。これまでさんざん説明したように、carbonを使うためには沢山のライブラリが必要になります。論理的にはcarbonが内部的に使っているライブラリをrequired_onceしなければ、動かない可能性があります。また、ライブラリによっては読み込む順番が大いに影響する可能性もあります。これを手動でやるのは面倒なので、composerにはオートロードという便利な仕組みがあります。
vendorフォルダ直下にautoload.phpというフォルダがあります。これは
require_once("vendor/autload.php)
とすることで、vendor配下にある全てのライブラリを自分のプロジェクトに読み込んでくれるというものです。オートロード経由なら読み込む順番、読込漏れを気にする必要はありません。なお、
require_once("vendor/autoload.php")
はエントリポイントで1回書けば大丈夫です。サンプルプログラムではmain.phpでrequire_onceしてますが、それ以外のファイルを作った場合はオートローダーをrequire_onceする必要はありません。gitとcomposer
最後にcomposer関連ファイルでgitに含めるべきもの、そうでないものをまとめます。結論は以下の通りです。
gitに含めるべき
* composer.json
* composer.lockgitignore(gitに含めないべき)
* vendorフォルダcomposer.lockがあればライブラリを完璧に再現することができるので。composer.jsonはいらないと思いますす。しかし、自分が本当に使っているライブラリが書かれているのはcomposer.jsonだけです。composer.lockだけで、自分が使っているのはcarbonだけだと判断できるでしょうか。carbonを使っているという情報がない場合、ライブラリのバージョンアップをする時にとても困ります。composer.json、composer.lockはペアでgit管理しましょう。
vendorフォルダですが、全ライブラリがダウンロードされるためにファイルサイズが大きくなりがちです。また、vendorフォルダはサードパーティライブラリ置き場なので基本的に編集することはなく、
composer install
でいつでも再作成が可能です。なので、原則としてgit管理はしません。まとめ
長かったですが、今までの話をまとめます。
- composer.jsonに自分が使うライブライを定義する
- composer.lockには依存ライブラリが全て書かれている
- vendorにはダウンロードしたライブラリが配置される
- ライブラリ読込はエントリポイントで
require_once("vendor/autoload.php")
とやろう- composer.json、composer.lockはgit管理しよう
- vendorは.gitignoreに追加しよう
以上です。composerを使いこなして、楽しいPHPライフを過ごしましょう。
- 投稿日:2020-02-21T17:25:03+09:00
Composerのインストーラーパッケージからのインストールでエラーが出た話
現象
https://getcomposer.org/
からインストーラーをダウンロードして普通にインストールしようとした。
↓
こんなのが出て先に進めない。
php.ini内にっぽい記述がある。
extension=sqlsrv_72_ts extension=pdo_sqlsrv_72_tsとりあえずコメントアウト
;extension=sqlsrv_72_ts ;extension=pdo_sqlsrv_72_tsインストール自体はできたが、個人的に全然すっきりしていない。。
- 投稿日:2020-02-21T17:16:09+09:00
速攻でLaravelのインストール Mac編
初投稿ということで、私が学習しているPHPのフレームワーク「laravel」のインストール手順をまとめてみます。
ちなみにこれから書く記事は、
「とりあえず上からコピペしていけば動くぜ!」
という端折りまくった内容です。
[環境]
mac
php 7.2.26
Homebrew 2.2.4
Composer 1.9.2
[コマンドをどこで実行するのか]
ターミナルも知らずにいきなりlaravelを勉強している人がいるのか?、って話ですが一応書いておきます。
MacにはデフォルトでターミナルというUNIX端末エミュレータが付属しています。
↑こんなの。
Launchpadで「ターミナル」と検索すれば出てくるので探して起動。
これから書くコマンドは全てそこで実行する。
[Homebrewのインストール]
既にインストールしている場合は必要ないです。
brew -v
と打ってHomebrewのバージョン情報が出てくるようなら既にインストールされてます。
出てこない人は以下のコマンドでインストール。
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
コマンドの終了後に
brew -v
をもう一回打つと、今度はちゃんとバージョン情報が表示されます。
表示されたら次はcomposerのインストール。
[composerのインストール]
composerについてはこちらの記事を読むと吉。
https://qiita.com/niisan-tokyo/items/8cccec88d45f38171c94
まずは、composerが既にインストールされているか以下のコマンドで確認する。
composer -v
って感じで、アスキーアートとバージョン情報、それとcomposerのコマンドのリストが表示される。
出てこないぜ、って人は以下のコマンドでcomposerをインストール。
brew install composer
インストールが終わったら、また
composer -v
で、アスキーアートとかがちゃんと表示されるか確認。
無事に進めたら、次は遂にcomposerを通じてlaravelをインストールしていく。
[Laravelのインストール]
※バージョンを指定してインストールしたい人は、先にこの小見出しの最後の(注※)を呼んでください。
先にインストールしたcomposerを経由して、以下のコマンドでlaravelのプロジェクト作成(インストール)します。
composer create-project --prefer-dist laravel/laravel プロジェクト名
赤字の部分は自分で好きな名前をつけてやってください。
自分で名前つけるのさえ怖い人は以下のコマンドで一緒にやりましょう。composer create-project --prefer-dist laravel/laravel my_laravel
これで、laravelがインストールされました。
注※)バージョンを指定したい場合。例として、laravel5.5をインストール。
composer create-project --prefer-dist laravel/laravel my_laravel
赤字の部分を以下のように
laravel/laravel=5.5
と変更するとそのバージョンがインストールされます。
[インストールしたlaravelを動かしてみる]
プロジェクトに移動します。
プロジェクト名を自分でつけた人は
cd プロジェクト名
自分でやるのが怖かった人は、
cd my_laravel
プロジェクトに移動したら、その状態で
php artisan serve
と打ち込む。
このコマンドでlaravelのビルトインサーバーが立ち上がり、念願のlaravelの初期画面を表示することができます。以下にアクセス。↓
すると、以下のようなlaravelの初期画面が出てきます。
[終わりに]
laravel楽しいです。
次回はデータベース周りの設定をやろうかと。
mampでやるとわかりやすそうだなー。その前にvps環境の構築もやらねば……。
- 投稿日:2020-02-21T17:11:23+09:00
PHPで送信したメールの開封率を計測する方法
恒例
https://www.php.net/manual/ja/function.mb-send-mail.php
Code
mb_language('uni'); mb_internal_encoding('UTF-8'); $from = 'from@me.com';//発信元 $to = 'to@user.com';//送信先のメールアドレス $subject = '開封率を計測する方法';//メールの件名。 $v = '1'; //プロトコルのバージョンです。この値は 1 にする必要があります。 $t = 'event'; //個々のユーザーについて収集された操作の種類です。 $tid = 'UA-123456-1' //データの送り先の Google アナリティクス プロパティを識別するための ID です。 $cid = md5($to); //個々のユーザーに固有の ID です。送信先をmd5して、uidを作ります。 $ec = 'event-category'; //イベントのカテゴリを指定します $el = 'event-label'; //イベントのラベルを指定します。 $ea = 'event-action'; //イベントのアクションを指定します $ev = 'event-value'; //イベントの値を指定します $dp = 'mail/sale/2020'; //ページの URL のパス部分 $dt = $subject; //ページやドキュメントのタイトルです $message = 'メールの本文'; $message.= " <img src='https://www.google-analytics.com/collect?v=1&t={$t}&tid={$tid}&cid={$cid}&ec={$ec}&el={$el}&ea={$ea}&ev={$ev}&dp={$dp}&dt={$dt}' /> ";//開封率を計測する用 $mail_from_text = mb_encode_mimeheader('日本語名前'); $header = "From:{$mail_from_text}<{$from}>\nContent-Type:text/html;charset=UTF-8"; mb_send_mail($to , $subject , $message , $header ,"-f {$from}");開封率を確認します
Google アナリティクスのイベントで確認します
- 投稿日:2020-02-21T16:04:53+09:00
PHPで気をつけること
コードの可読性
if文の順番
foreach ($array as $key => $val) { if (!empty($val)) { // ここに処理を書く } else { continue; } }車輪の再開発❌
- 既存の関数を用いる
コードを書く前に 描く!
- フローチャートを書いてからコーディングする方が開発工数が短い!
コメントは、コードに書けないことを書く
1万時間の訓練
- 週20時間(毎日約3時間)なら、10年で到達
- 週35時間(毎日 5時間)なら、6年弱で到達
- 週49時間(毎日 7時間)なら、4.3年で到達
セキュリティ的に注意するコード (ユーザ引数を渡さない)
- eval
- PHPのコードとして実行
- exec
- 外部プログラムを実行
- file
- ファイルの中身を配列に格納
- file_get_contents
- ファイルを文字列として格納
- fopen
- 指定ファイル/URLを開く
参考
- PHP開発者が心得ておくべき10の鉄則 https://qiita.com/ka215/items/c4bda101e51b7fe82ab2
- プログラマが知るべき97の https://qiita.com/masakinihirota/items/5fd5fffa5ac5e057a9df
- 投稿日:2020-02-21T15:44:25+09:00
PHPのクラスをforeachで回せるようにする
PHPでは普通arrayをforeachしますが、クラスにIteratorAggregate、ArrayAccess、Countableを実装させればforeachで回せるようになります。
配列を直接使うのではなくクラスにすることで、引数に渡せる型を制限したり、クラスにロジックを書けたりして便利です。この考え方をファーストクラスコレクションといいます。
以下は例のコードです。
<?php class ListValue implements \IteratorAggregate, \ArrayAccess, \Countable { private $array; public function __construct(array $array) { // keyが連番の数字になることを強制する $this->array = array_values($array); } public function count(): int { return count($this->array); } /* IteratorAggregateインターフェースの実装 */ public function offsetGet($offset) { return $this->offsetExists($offset) ? $this->array[$offset] : null; } /* ArrayAccessインターフェースの実装 */ public function offsetExists($offset) { return isset($this->array[$offset]); } public function offsetSet($offset, $value) { if (is_null($offset)) { $this->array[] = $value; } else { $this->array[$offset] = $value; } } public function offsetUnset($offset) { unset($this->array[$offset]); } public function getIterator(): ArrayIterator { return new ArrayIterator($this->array); } }
- 投稿日:2020-02-21T12:32:00+09:00
eccube4でアプリケーションエラーがあった際にメールを送信する
おおまかな手順はSymfonyの公式に記載。
今回はローカルからmailtrapに送信する形で試した。
追記分以外はデフォルトの状態dev/public/app/config/eccube/packages/dev/monolog.ymlmonolog: handlers: buffered: type: buffer handler: easylog channels: ["!event"] level: debug easylog: type: service id: easycorp.easylog.handler console: type: console process_psr_3_messages: false channels: ['!event', '!doctrine', '!console'] #追記分 app_error: type: fingers_crossed action_level: critical handler: deduplicated deduplicated: type: deduplication handler: swift swift: type: swift_mailer from_email: error@example.com to_email: example@example.com # to_email: [' dev1@example.com ', ' dev2@example.com ', ...] # カンマ区切りで複数に指定できる subject: 'エラーを検知しました' #メールの件名 level: error #本文に記載するどのレベルのErrorを記載するか formatter: monolog.formatter.html content_type: text/html #htmlメールで送信する場合に必要 services: easycorp.easylog.handler: class: EasyCorp\EasyLog\EasyLogHandler public: false arguments: - '%kernel.logs_dir%/%kernel.environment%/site.log'順番に解説していこう。
app_error: type: fingers_crossed action_level: critical handler: deduplicatedまずはfingers_crossedに実行するための条件を設定する。
action_level別に設定できる。
この場合はlog_levelがcriticalの時にhandlerで設定している処理を呼び出す。
つまりはdeduplicatedを呼び出す。action_level別条件の詳細
critical error 5xx系のHTTPコードエラー 4xx・5xxレベルのHTTPコードエラー deduplicated: type: deduplication handler: swift公式をgoogle翻訳で直訳するとdeduplicationの役割は重複するメッセージを削除した後に次のhandlerに処理を渡すイメージかな?
今回はswiftにいく
deduplicatedハンドラーは、要求のすべてのメッセージを保持し、それらが特定の期間(デフォルトでは60秒)にわたって一意である場合にのみ、一度にネストされたハンドラーにそれらを渡します。 レコードが重複している場合、それらは破棄されます。 このハンドラーを追加すると、特に重大な障害シナリオでは、通知の量が管理可能なレベルに減少します。 timeオプションを使用して期間を調整できます。
timeオプションはよくわかってない。
swift: type: swift_mailer from_email: error@example.com to_email: example@example.com # to_email: [' dev1@example.com ', ' dev2@example.com ', ...] # カンマ区切りで複数に指定できる subject: '[%%level_name%%][%%datetime%%]エラーを検知しました' #メールの件名 level: error #本文に記載するどのレベルのErrorを記載するか formatter: monolog.formatter.html content_type: text/html #htmlメールで送信する場合に必要subjectには以下のフォーマットを出力することが出来る。
フォーマット 出力する項目 %%datetime%% 日付 %%channel%% チャネル名 %%level_name%% レベル %%message%% メッセージ内容 %%context%% コンテキスト情報 %%extra%% 追加情報 最後にメール処理に関する設定を記述すれば完成。
細かい部分は見せられないがこんな感じでメールが届く。
入れ子になってないからイメージしづらいが、fingers_crossedから順に処理をつなげていくイメージでいいかと思う。
slackに飛ばすことも可能なので有料会員であればslackに投げるのもあり。
(無料だとログが残らない)概念的な理解は以下の記事が非常にわかりやすかった
PHPのロガーMonologを理解しよう
PHPのロギングmonologを理解する
- 投稿日:2020-02-21T09:32:29+09:00
docker-composeでPHP開発環境
docker-composeでRails5.2開発環境 に続き、PHPの開発環境もdocker-composeで構築してみました。本当はPHP5系の検証環境が欲しかったのですが、5.4のイメージを使うとコンテナ間の通信がどうしてもうまくいかずに断念しました。当初の目的には使えませんでしたが、7系では問題なく動いたので備忘のための投稿しています。
必要なのは以下の2つのファイルです。
DockerfileFROM php:7.3-apache RUN docker-php-ext-install pdo_mysqldocker-compose.ymlversion: '3' services: db: image: mysql:5.7 volumes: - ./mysql:/var/lib/mysql environment: - MYSQL_ROOT_PASSWORD=secret php: build: . volumes: - ./html:/var/www/html ports: - 8080:80 depends_on: - dbファイルを設置後、以下のコマンドを実行します。
docker-compose build docker-compose up別のターミナルからデータベースの作成コマンドを実行します。
docker-compose exec db mysql -e "create database mydb default charset utf8" -p今回は、以下のようなプログラムで動作確認しています。htmlフォルダ下に置いてください。
index.php<p> <?php echo "Hello PHP on Docker!"; ?> </p> <p> <?php // docker-compose exec db mysql -e "create database mydb default charset utf8" -p $pdo = new PDO("mysql:host=db;dbname=mydb","root","secret"); $pdo->exec("create table if not exists t (v varchar(255))"); $pdo->exec("insert into t values ('Hello MySQL on Docker!')"); foreach ($pdo->query("select * from t") as $row) { echo $row['v'] . "<br/>"; } ?> </p>ブラウザで http://localhost:8080 にアクセスすると以下のようなページが表示されます。
ハマりどころ
- phpのイメージで
apt-get
は動作しませんでした、代わりにdocker-php-ext-install
でモジュールを追加します。- volumesで永続化した領域を意識しましょう。例えば、一度でも起動した後から、MYSQL_ROOT_PASSWORDを変更しても効きません。環境構築中であれば、少しでもおかしくなったなと思ったら躊躇なく削除してやり直すのが早いと思います。
- docker-compose.ymlから何でもやろうとすると、細かいところで詰まります。今回だとデータベースのエンコード設定などです。
docker-compose exec
なんかも組み合わせる必要がどうしてもあるような気がします。参考URL
- 投稿日:2020-02-21T09:15:54+09:00
【php】文字列の出現回数を調べる
substr_count()
文字列の出現回数を検索する ※大文字小文字を区別する
文字列の出現数を調べる「substr_count()」
<?php $text = 'This is a test'; echo substr_count($text, 'is').'<br/>'; // 実行結果 2 ?>4文字目から検索
<?php $text = 'This is a test'; // 文字列は 's is a test' になっているので, 1 が表示される echo substr_count($text, 'is', 3).'<br/>'; ?>4文字目から3文字検索
<?php $text = 'This is a test'; // テキストは 's i' になっているので, 0 が表示される echo substr_count($text, 'is', 3, 3).'<br/>'; ?>6文字目から10文字検索
<?php $text = 'This is a test'; // 5+10 > 14 なので、警告が発生する echo substr_count($text, 'is', 5, 10).'<br/>'; //PHP Warning: substr_count(): Invalid length value in ?>重なった場合
<?php $text2 = 'ABBABBA'; // 重なっている副文字列はカウントされないので、1 が表示される echo substr_count($text2, 'ABBA').'<br/>'; ?>
- 投稿日:2020-02-21T07:08:39+09:00
Laravel バリデーション
ファームなどを使って、データを送信するとき、正しい形式で書かれているか検証する仕組みがバリデーション。
なぜバリデーション必要か?
ユーザーが意図しないデータを入力してしまったり、そもそも正しく入力をしようとしていない人がデータを送信してくることもある。ユーザーからの入力を、必ず正しい形式で入力されているかチェックして、間違った所があれば再入力をもとめるようにすることが必要。
これをチェックしてくれる機能が『バリデーション』。
ユーザー入力画面
name:
mail:
age:↓
フォーム送信
↓アクション
バリデーション→→エラー→ユーザー入力画面に戻す入力データに問題なければ、
↓
処理を実行どうやってやるか?
コントローラーのvalidateメソッド使う。validateはアクションメソッドから呼び出す
$this-> validate($request,[検証設定時の配列]);第一引数にはリクエスト。
第二引数には検証する設定情報を配列にまとめたものを用意。