- 投稿日:2019-05-12T23:43:09+09:00
PHPのfinally
以下のときの
finally句の挙動function test($argument) { try { echo "try\n"; return $argument; } finally { $argument++; unset($argument); echo "finally\n"; } } $counter = 2; $result = test($counter); var_dump($result);7.1.25-7.3.5try finally int(2)5.5.0-try finally Notice: Undefined variable: argument in /in/0oTE9 on line 8 NULL
メモ
try句のreturn文でファイルを使用してfinally句でファイルをunlinkするとfile busyになりました。
- 投稿日:2019-05-12T23:42:58+09:00
php-master-changes 2019-05-11
今日は typo の修正、不要コードの削除、config.guess、config.sub の更新、テストで使われていた *.jpeg の *.jpg へのリネーム、テストの並列実行対策、不要なドキュメントの削除、テストのコメント内に maintainer zts とあったのを単に zts とする修正があった!
2019-05-11
cmb69: Fix typo
- https://github.com/php/php-src/commit/3759c6316dc7756bef7aa7bdcb7e9ae631c195a8
- [7.2~]
- AppVeyor の設定にあった typo の修正
petk: Remove unused variables
petk: Bump config.guess and config.sub
- https://github.com/php/php-src/commit/e586d3f447e35fa0ddb7fc831dea36bcf5739104
- [7.4~]
- config.guess、config.sub の更新
petk: Rename *.jpeg files to *.jpg
- https://github.com/php/php-src/commit/a68e0767b349360344fcdfa0f853bf577c37adbd
- [7.4~]
- テストで使われていた *.jpeg の *.jpg へのリネーム
cmb69: Prevent race condition
petk: Remove ffi README in favour of docs
- https://github.com/php/php-src/commit/4bfb86cdcab4451cef184d3770420bb9cf7ca121
- [7.4~]
- ext/ffi で、README ファイルの削除
- ソースコード内のドキュメントはある程度 PHP マニュアルに一本化していくノリ
petk: Fix comment to match the future zts configuration option
- https://github.com/php/php-src/commit/8ef2121ee10b9741fb306cf5eb2b12c427c7ee07
- [7.4~]
- テストのコメント内に maintainer zts とあったのを単に zts と修正
- 投稿日:2019-05-12T23:30:10+09:00
docker-compose.ymlとDockerコンテナのPHPで環境変数を使用する
はじめに
これは個人的な備忘録になります。
docker-compose.ymlで環境変数を使用する
docker-compose.ymlがあるディレクトリ直下に、「.env」 を用意する。そのファイル内で定義した値を使用できる。
例えば、以下のように定義をした場合
.env# REDIS関係 REDIS_PORT=6379 REDIS_PASSWORD=passworddocker-compose.ymlでは、以下のように使用できる
docker-compose.ymlredis: image: redis:alpine3.9 command: redis-server --requirepass ${REDIS_PASSWORD} ports: - "${REDIS_PORT}:${REDIS_PORT}"dockerコンテナで環境変数を使用する
dockerコンテナ内で環境変数を使用する場合は、docker-compose.ymlで定義する。
環境変数を1個〜2個指定する場合は、「environment」で定義をする。
以下のファイルでは、DATABASE_HOST/REDIS_HOSTを定義している。docker-compose.ymlapp: build: ./app env_file: .env environment: DATABASE_HOST: db REDIS_HOST: redis depends_on: - db - redis volumes: - ./data/html:/var/www/htmlまた、複数指定したい場合は、「env_file」として、環境変数を記載しているファイルを指定する。
この時に、「.env」ファイルを使い回すことで、環境変数を「.env」ファイルに集約ができる。
PHPのコンテナでPHP.iniで注意点
PHP.iniでは、環境変数を使う、使わない、または有効にする変数の優先順位設定があります。
それが「variables_order」になります。デフォルトでは、「GPCS」となっていますので、環境変数は使えないです。
Dockerの環境変数が読み込めなくてハマりました。
「EGPCS」にすると、環境変数を優先して使ってくれます。php.ini; This directive determines which super global arrays are registered when PHP ; starts up. G,P,C,E & S are abbreviations for the following respective super ; globals: GET, POST, COOKIE, ENV and SERVER. There is a performance penalty ; paid for the registration of these arrays and because ENV is not as commonly ; used as the others, ENV is not recommended on productions servers. You ; can still get access to the environment variables through getenv() should you ; need to. ; Default Value: "EGPCS" ; Development Value: "GPCS" ; Production Value: "GPCS"; ; http://php.net/variables-order variables_order = "GPCS"これでPHPのコード内で環境変数を使えるようになります。
$redis = new Redis(); $redis->connect($_ENV['REDIS_HOST'], $_ENV['REDIS_PORT']);コードだけではなくて、PHP.iniの中でも環境変数は使えるようです。
php.inimemory_limit=${PHP_MEMORY_LIMIT}参考文献
- 投稿日:2019-05-12T22:38:45+09:00
ポートフォリオ「継続支援アプリ CHIRITSUMO!!」について
はじめに
はじめまして。
今回、PHPの基礎のアウトプットを兼ねてポートフォリオを作成しましたので、説明します。目的
PHP言語を用いてフルスクラッチ開発をすることで、下記事項が理解できているかを確認する
・セッション
・GET送信、POST送信
・条件分岐、繰り返し処理
・DB関連(DB接続、SQL実行)
・DBデータの編集、画面への出力スペック
■言語
PHP, HTML, CSS, JavaScript(jQuery)■DBMS
MySQL■フレームワーク
なし■サーバー
XSERVERポートフォリオ
URL:http://chiritsumo.nyankormotti.com
サンプルユーザ
email:test@sample.com
pass:111111ポートフォリオの概要
勉強時間、実施内容を記録するWEBサービス
ポートフォリオの機能
■ユーザー情報関連
・ユーザー登録
・ログイン・ログアウト
・ユーザープロフィール編集
・パスワード変更
・パスワードリマインダー
・退会■メイン機能
・マイページ(実績一覧)
・実績登録
・実績編集
・実績削除
・実績詳細
・カテゴリー編集
・実績検索■その他
・お問い合わせ何ができるか
■実績を投稿できる
(勉強した日にち、勉強時間、内容、内容の画像を保存できる。POST送信にて対応)
■実績詳細にて保存した画像を拡大して閲覧できる(lightboxを使用)
■実績をカテゴリーで検索、また実績日を範囲指定して検索できる。
実績登録した日にちの昇順、降順でソートを実施できる。
ページネーション後も検索情報を保持している。
(GET送信にて対応)
※多くのデータ数が必要なため、ユーザーを変更しています。
■その他
・パスワードリマインダーにて、登録されたメールアドレス宛に認証キー、新しいパスワードを送信する。作成方法
1.機能の洗い出し
3.テーブル設計、DB作成
4.各画面、機能を実装
ログイン、ユーザー登録機能などセッション周りから作成。
→パスワード変更など非機能要件
→POST・GET送信関連などのメイン機能を実装
→細部の調整5.テスト
・各機能の処理が正常終了すること。
・商品一覧表示機能に関しては、境界値のデータを作成し、実施。
・URL直打ちした際にセッションが保持されているか確認。 など工夫したところ
■検索条件の保持
実績詳細画面からマイページへ遷移する際や、ページングにてページを移動する際に、検索条件を保持するために、GET送信を用いています。
実績詳細画面から戻る際は、実績テーブルのキーであるIDのみGET送信から削除して遷移しています。(遷移時のURLにて「p_id」を削除しています)■お問い合わせ機能
セッション情報の有無(ログイン前後)にて、お問い合わせ画面のメールアドレス入力フォームの表示・非表示を制御しています。
(ログイン後はセッションIDよりDBからメールアドレスを取得し、メールを送信する仕様にしています。)■マイページ画面の余白
マイページ画面の余白を確保するために、検索フォームをモーダルで出力するようにしています。
また、ヘッダーのメニューをドロップダウンにするようにして、空間を確保し、ゆとりを持たせています。
(実績一覧の表示にはcssのoverflow:scrollにてスクロールして表示しています。)ポートフォリオの課題
・カテゴリー名変更機能の追加(登録、削除機能のみ)
・FWによるMVCモデルの適用(保守性が低い)
・SASSを用いたCSS実装(保守性が低い)
・レスポンシブ対応(1000px以下だと崩れる)現在の学習内容(2019.05.12現在)
・Laravel
・JavaScriptの基礎
・React、Vue.js(主にVue.js)
・SASS
・CSS設計(FLOCSS)→Laravelでポートフォリオ作成予定
最後に
Github: https://github.com/nyankormotti/CHIRITSUMO.git
- 投稿日:2019-05-12T19:56:49+09:00
ログイン認証について
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>display</title> </head> <body> <?php $dsn = 'xxxxxx'; $user = 'xxxxxx'; $password = 'xxxxxx'; try { // メアドとパスワードの入力チェック if (empty($_POST['mail']) || empty($_POST['pass'])) { echo "メールアドレスかパスワードが入力されていません。"; } else { //DB接続 $dbh = new PDO($dsn, $user, $password); $stmt = $dbh->prepare("SELECT * FROM members where mail = :mail AND pass = :pass"); $stmt->bindParam(':mail', $_POST['mail'], PDO::PARAM_STR); $stmt->bindParam(':pass', $_POST['pass'], PDO::PARAM_STR); $stmt->execute(); $result = $stmt->fetch(PDO::FETCH_ASSOC); //配列名前だけ表示 } //レコードがない場合の表示 echo "メンバーが存在しません。"; } } catch (PDOException $e) { exit ('データベース接続失敗。' . $e->getMessage()); } ?> </body>ひとまずはここまでできている。
あとはMySQLから引っ張ってきたレコードの名前を表示すれば終わりのはず。
配列を使って名前を表示するのだが、いまいちやりかたがわからず。
ぐぐるのみ。
- 投稿日:2019-05-12T16:19:42+09:00
PHPのアクセス修飾子: public, private, protected の使い分け
はじめに
アクセス修飾子が必要な理由として第一に保守の容易さに挙げられます.
オブジェクト志向のカプセル化を想像するとわかりやすいかもしれません.
チーム開発をしていて自分がクラスを作る際は基本的に, 他の人がそのクラスを使いやすいように、使って良い機能だけ公開し、使ってほしくない機能は隠します。
このようなシステムを作るときこのアクセス修飾子が役に立ちます.アクセス修飾子
アクセス修飾子はpublic, protected, private の三つがあり, 下に行くほどアクセスできる範囲が狭くなります.
アクセス修飾子 意味 public 外部から参照できる protected 変数、関数を宣言したクラスと継承されたクラスから参照できる private 変数、関数を宣言したクラス内のみ参照できる 下記は説明のために作成したものです.
変数名にpublicなどをつけるという愚かな行為をしているため
コピペはしないでください親class Parent{ //$public, #protected, $private全てアクセスできる public $public; protected $protected; private $private; //privateで読み込みだけしていい場合このように公開する public function getPrivate{ return $this->pra; } }Mainを継承
子クラスclass Child extends Parent{ // $privateはアクセスできない // $public, $protectedはアクセスできる }クラス外//$private, $protected はアクセスできない //$publicはアクセスできる参照リンク
- 投稿日:2019-05-12T15:41:32+09:00
__debugInfo の隠れ仕様的なもの
__debugInfo の隠れ仕様的なもの
php 5.6 より
__debugInfoでvar_dumpの出力を弄れる様になってますが、その挙動についてドキュメントで触れられていないことがあるので少々補完します。
※ アンドキュメントってことは正しい仕様ではなく「現在たまたまそうなっているだけ」の可能性があります
※ 確認は全て手元の php 7.1.14 で行いましたおさらい
class Debug { private $privateField = 1; protected $protectedField = 2; public $publicField = 3; } $debug = new Debug(); $debug->dynamicField = 4; var_dump($debug);このようなコードを実行すると下記のような出力が得られます。
class Debug#2 (4) { private $privateField => int(1) protected $protectedField => int(2) public $publicField => int(3) public $dynamicField => int(4) }このクラスにマニュアル通りに
__debugInfoを実装します。class Debug { private $privateField = 1; protected $protectedField = 2; public $publicField = 3; public function __debugInfo() { return [ 'propSquared' => $this->privateField ** 2, ]; } } $debug = new Debug(); $debug->dynamicField = 4; var_dump($debug);出力は下記のようになります。
class Debug#2 (1) { public $propSquared => int(1) }まぁ仕様どおりですね。
隠れた仕様1(アクセスレベル)
実際、上記のような完全カスタムの用途が多いと思いますが、私が今回やりたかったのは「でかいプロパティを伏せる」でした。
巨大フィールドを抱えているとvar_dumpの出力がでかすぎて視認性が悪いからです。
これはその過程で気づいた仕様です(private とかを維持したままカスタムする方法がわからなかった)。ドキュメントに一切記載がないのですが、どうも
__debugInfoの返り値はオブジェクトを配列キャストしたものであるべきのようです。
- https://github.com/php/php-src/blob/php-7.1.14/ext/standard/var.c#L63-L77
- https://github.com/php/php-src/blob/php-7.1.14/Zend/zend_compile.c#L1327
public フィールドを配列キャストしても普通のキーになるため、素の配列を返すと public と判定されます。上記で
public $propSquaredとなっているのはそのためです。
つまり、それらしい配列を返してやれば__debugInfoで private/protected(っぽい)出力をすることができます。public function __debugInfo() { return [ "\0Debug\0dummy1" => 'this is private', "\0*\0dummy2" => 'this is protected', ]; }この出力は下記のようになり、あたかも dummy1 という private フィールドと dummy2という protected フィールドがあるかのような出力になります。
class Debug#2 (2) { private $dummy1 => string(15) "this is private" protected $dummy2 => string(17) "this is protected" }ここで冒頭に戻り、「でかい(特定)プロパティを伏せる」ためには配列キャストしてからそれらを伏せれば良いことが分かります。
public function __debugInfo() { $properties = (array) $this; unset($properties["\0Debug\0privateField"]); return $properties; }class Debug#2 (3) { protected $protectedField => int(2) public $publicField => int(3) public $dynamicField => int(4) }それらしいキーを伏せているため、
$privateFieldが消えています。隠れた仕様2(再帰参照)
再帰参照を含むオブジェクトで
__debugInfoを実装すると出力がやべぇことになります。class Debug { public function __debugInfo() { return (array) $this; } } $debug = new Debug(); $debug->dynamicField = $debug; var_dump($debug);上記の出力は下記のようになります(長すぎるので抜粋)。
class Debug#2 (1) { public $dynamicField => class Debug#2 (1) { public $dynamicField => class Debug#2 (1) { public $dynamicField => class Debug#2 (1) { public $dynamicField => class Debug#2 (1) { ... } } } } }上記のインデントのズレは私のミスでもなんでもなく、本当に大量にネストされて遥か右方へ追いやられた結果です(前後は省略)。
なお、__debugInfoを実装しなければこのようなことは起きません。多分組み込みなら再帰の検出ができるけど、
__debugInfoを自前実装した結果、(配列なので)再帰の検出ができなくなってるのかな?(だとしても最終的に...が出るのが謎い)。
__debugInfoを実装するときは再帰に注意するか、明示的な(シンプルな)配列を返したほうが良さそうです。隠れた仕様3(print_r)
これもドキュメントにないのですが、
__debugInfoを実装するとprint_rにも影響が出ます(https://github.com/php/php-src/blob/php-7.1.14/Zend/zend.c#L186)。class Debug { public function __debugInfo() { return ['field' => '__debugInfo の返り値です']; } } print_r($debug = new Debug());実行すると下記のような出力になり、
print_rにも影響が出ていることが分かります。Debug Object ( [field] => __debugInfo の返り値です )
- 投稿日:2019-05-12T13:31:51+09:00
【PHP】オブジェクト指向を学ぶ[その1]
オブジェクト指向
オブジェクト指向を学ぶために軽い自己紹介するコードを作ってみます。
まず
・class設計・・・設計図
・インスタンス ・・・もの
と言う考えを念頭におきます。コード
index.php<?php //クラス定義 class Self_Introduction{ // プロパティー // 変数定義 private $name; private $age; // インスタンスが生成されると同時に処理が走る public function __construct($name, $age){ $this->name = $name; $this->age = $age; } // メソッド public function hello(){ echo "私の名前は{$this->name}です。<br>年齢は{$this->age}才です。"; } } // インスタンス生成 $user = new Self_Introduction("太郎", "35"); // メソッド呼び出し echo $user->hello(); // 結果 // 私の名前は太郎です。 // 年齢は35才です。classの中には、定数や変数そして関数 ("メソッド" といいます) を含めることができます。
解説
まずclassを定義します。
class名の一文字目は大文字にする習わしがあるみたいです。このclassの中で変数を定義したりconstructを書いたりメソッドを書いたりします。
そして、
$user = new class名(引数);とすることでclassを使うインスタンスと言うものを生成し、メソッドを呼び出すことで一連の流れは終了です。インスタンス生成で何が起きているか
$user = new Self_Introduction("太郎", "35");この部分で何が起きているのか。インスタンスが生成されると同時にclass内の
__construct()に処理が走ります。
すると、インスタンスが生成された時の引数「("太郎", "35")」が__construct()で処理されます。メソッド呼び出し
echo $user->hello();最後にメソッドを呼び出します。
$userはclass Self_Introductionを使ったインスタンスです。
Self_Introductionの中のhello();メソッドを使用しますと言った意味合いが近いと思います。そして、メソッドに処理が走る結果として、自己紹介が行われると言った流れになります。
アクセス権について
3つのアクセス権があります。
public・・・どこからでもアクセス可能
private・・・クラスとサブクラスからアクセス可能
proected・・・クラスからアクセス可能こちらを踏まえて以下のコードを見てみます。
index.phpclass Access{ public $public = "publicです"; private $private = "privateです"; protected $protected = "protectedです"; function accessHello(){ echo $this->public; echo $this->private; echo $this->protected; } } $hoge = new Access(); echo $hoge->public; //publicです echo $hoge->private; //出力されません echo $hoge->protected; //出力されません $hoge->accessHello(); //publicですprivateですprotectedですと出力されます実際インスタンスを生成してアクセスしてみるとこのような結果になります。
privateとpritectesdは外部からはアクセスできないので出力はされません。ですが
accessHello()はどうでしょうか?
全てが表示されています。
どう言うことかというとprivateでもprotectedでも同じクラス内のメソッドの中で処理が書かれています。
そして、メソッド自体のアクセス権は何も記されていないのでpublicです。なので外部で
accessHello()と呼び出すとクラス内で処理された結果が呼び出されるので、privateでもprotectedでも出力されるんですね。次回はセッター、ゲッターについて書きます。
※何か間違っていること、これも覚えておいた方がいいと言うことがあれば是非教えてください




