新入社員ブログ 松井(第5回)

こんにちは。松井です。もうすぐ2月になりまだまだ寒い時期が続きますね。

今回はOJTについて紹介します!内部研修が終わって、8月からOJTに参加しています。OJTということで、案件に参加していますが、私の場合は基本設計から参加しました。難しい作業を割り振られることはありませんが、とにかく仕事に慣れることに苦労しました。1月末までどんなことをやってきたか、簡単になりますが紹介します!

基本設計・詳細設計

お客様との打ち合わせや社内会議を聞いてメモを取ったり、画面設計書を見ていました。また、先輩社員がテーブル定義の物理カラム名の名前をつけていました。画面設計書やテーブル定義について「おかしい!」と思ったところは迷わず先輩社員に質問していきました。例を2つ挙げると画面設計書に書いてあることがテーブル定義に書かれていないといった資料での漏れとテーブル定義には必須扱いになっているにもかかわらず画面設計書では必須ではないといった資料間による矛盾です。冷静に資料を見比べることで漏れや矛盾が無いかチェックをしていましたので、該当する部分が資料内にあるか探すのが大変でした。しかし、設計段階で漏れや矛盾を減らしたということにおいてはやりがいを感じられました!

API仕様書・詳細設計書作成

簡単な処理のAPI仕様書・詳細設計書を作成しました。最初はやり方が分からず簡単そうな画面を先輩社員に教えてもらいながら一通り作成しました。最初は簡単な仕様の詳細設計書を書きましたが、やり方が分からず先輩社員が作成した詳細設計書を参考に書くようにしました。ある程度詳細設計書を書いたら「内容は違っても他の詳細設計書にも同じことを書ける」ということを意識するようにしました。その際に自分たちが作った設計書をもとに実装されるので、「仕様が違う」ということが無いように気を付けるようにしました。

API実装・テスト

今は作成したAPI仕様書や詳細設計書を元にAPIを実装しつつ、テストして想定した挙動になっているか確認しています。研修で学んだLaravelで実装しておりますが、実際に仕事として使うのは始めてでプログラムの書き方に戸惑うことがあります。しかし公式ドキュメントやQiita等で使い方を調べて出来る限り自力でプログラムを組めるように努力しています!

今回はここまでです。次回はフォローアップ研修について紹介します。最後まで読んで頂きありがとうございます!

SQLの不思議… 紙屋05

’23年度入社の紙屋です!
2024年もよろしくお願いいたします。

新年一発目の投稿です。
無事に新年を迎えることができました!
昨年は少し実際の案件にも携わらせていただきました。少しずつできることも増えてきたことはうれしいです!
2024年もできることを着実に増やしながら成長したいと思います!

今回はその案件の中であるデータの差分の調査を行っているときに不思議に思ったことを検証してみようと思います。
それはSQLである一定の期間のデータを抽出しようとしたときに、何気なく使っていたある演算子で躓きました。最初は気づかなかったのですが、調査結果のデータ数がおかしいことの指摘もあり気づきました。
それは『BETWEEN』の使い方です!

—————————————-
式 BETWEEN 値1 AND 値2
—————————————-
BETWEEN演算子では、値が「値1以上かつ値2以下」の場合に真になる

と参考書ではあります。
私は1か月分のデータを抽出したかったので、

[/crayon]

というSQL文を作成し抽出しました。
特に疑問に思うこともなく作業を続け、他で分からないところがあったので、質問したときに、指導者とのSQL文の違いに気づきました。

[/crayon]

「ん?演算子ちがうけど、まぁいっか、同じことだし…」
「でも、結果も違うんだよなぁ…、どうしてだろう?」
と思ったことで調べるとどうやらデータ型がdatetime型であることも関係しているらしいということが分かりました。
そこでダミーデータを作って検証してみることにしました。

今回、ダミーデータはLaravelのマイグレーションとシーダーを利用して’2023/11/01 00:00:00’から’2023/12/31 23:59:59’までのデータを100件作成しました。
そして、同じ条件式で行数をカウントしました。

[/crayon]

この条件式の結果は、条件式1は50件、条件式2は56件と件数の差が出ました。
ちなみに、抽出条件の範囲を変えると、条件式3は53件、条件式4は3件でした。
抽出する条件のデータ型がdatetime型だったので、範囲指定には注意が必要そうです。

ちなみにdate型でもデータ数のカウントを行いましたが、時間が無い分、選ぶ演算子での差はみられませんでした。
今回の始まりは演算子の疑問で始まりました。
BETWEENを使う際は抽出される範囲とデータ型を十分に理解したうえで使う必要があります。
私みたいな初学者や不慣れな方は、データの範囲を指定して抽出する場合はまず比較演算子を利用する方が良いということを覚えておきましょう!

今回は文献を調べるだけでなく、自分でも実際のデータを使って結果の違いを理解できたので、引き続き今回のように検証しながら自分の理解を深めたいと思います。

では、また次回!!

ヘルパー関数のあれこれ!紙屋03

おつかれさまです!
‘23年度入社の紙屋です!
9月に入って朝晩の暑さがすこーーしずつ和らいでいたような気がしますね。早く日中の暑さも和らいでいくといいですね。

8月で課題の会員登録のアプリケーションを作り終えました。
外部研修でもLaravelでwebアプリケーションをつくりましたが、そのときはとりあえずの実装を優先して、「この関数がどんな仕事をしているのか、どんな機能があるのか」ということを考えていませんでした。
そこで、今回はLaravelにおけるヘルパ関数に焦点をあてて振り返ろうと思います!

ヘルパ関数とは?
Laravelに搭載されている独自の関数のことで、いろいろなところで呼び出せる便利な関数です。

Laravelの公式ドキュメントをみえると数えただけで213個ありました(今回Laravel ver9で実装)。
まだまだ分からないことが多いので、今回は使ったものに触れながら振り返ります!
今回の会員登録フォームで使用したヘルパ関数は、
・view ・redirect ・route ・request ・session
・old ・dd ・dump ・config
でした。
Contollerや入力フォーム、処理の確認で使うものが多く、外部研修でも使っていたので、コードレビューいただく前から使っていました。しかし、config関数は教えていただいてからの導入でした。

よくアドバイスいただく内容として、同じコードで内容量が多く、その処理を複数個所で使用する場合は、可読性や再利用性を考えてコーディングした方が良いと教えていただきます。
今回config関数をどこに用いたかというと、formタグで会員情報の登録や編集を行う箇所でバリデーションを実装するときに、バリデーションの中身は同じものなので、バリデーション時にコードが冗長にならないように利用しました。

まずは、config関数の公式ドキュメントを確認します。
config関数は設定変数の値を取得します。設定値はファイル名とアクセスしたいオプションを「ドット」記法で指定します。
とあります。

となっており、「/config/(.phpファイル)」内に記述されている配列を呼び出します。
では、私はどのように実装したかというと、
Controller内には以下のように記述し、

「/config/mySetting.php」ファイル内に

と記述しました(教えてもらいながらですが…)。

これでバリデーションチェック時の項目をController内に何度も記述する必要が無く、バリデーション内容の変更・修正時も配列の中身を記述することでスッキリします。

ちなみに、ヘルパ関数がどんな処理をしているのかは、「/vender/laravel/framwork/src/illuminate/Foudation/helpers.php」ファイル内に記述してありました。

確かに配列があればキーを返してくれているみたいです。

ちなみに、今回使用した「ドット記法」についてちょっと触れると、配列からの値の取得時にキーを「.」でつなげることで、多次元配列の場合、より深い階層へネストし値を取得してくれます。
例えば、Arr:get()関数の公式ドキュメントを参照すると、

となっています。$arrayのような多次元配列から値を取得したい場合は、第2引数のキーの部分をドット記法で、欲しい値までネストしていきます。
ちなみにArr::get()関数に第3引数をセットすると、第2引数に指定したキーが存在しない場合の値を返してくれます。

改めて振り返ってみると、「なるほど!」と思いました!
今後も、いろいろと忘れないようにまとめていきたいと思います。
では、また次回!!


パスワードはハッシュ化する!!紙屋02

こんにちは!
’23年度入社の紙屋です!
日に日に暑さが増すなか、台風もやってきて大変ですね。
私は出身が鹿児島県なので台風には慣れっこです。
学生のうちは台風が来ると「学校が休みになるんじゃないか」とそわそわしていましたが、社会人になると「台風きたら出勤どうしよう…」と不安でそわそわしてしまいます(笑)

現在は、課題として会員登録フォームをPHPでの実装、その後フレームワークを使った実装がひと段落終えたところです。調べながら、分からないところが教えていただきながらの実装だったので、ちょっとずつまとめをしていこうと思います。

まずはとりあえず機能の実装を!と考え、新規登録フォーム、検索機能、編集・削除機能を実装しました。その中でセキュリティ対策への考えはまだまだ足りず、データベースへ登録する際に、エスケープ処理を行わなければならないことは覚えていましたが、パスワードに対しては何も処理をしていませんでした。
レビューいただいた際に、「え・・ハッシュ化って?」「まだ処理がいるの?」と混乱しました…。なので、今回はハッシュ化について調べてみました。

今回、PHPプログラミングで実装した内容は、

です。
最初は直観的に

をそのままDBに登録していました。

レビューいただいた際に、このままでは、DBを攻撃された場合、個人情報が盗まれてしまう危険性があると教えていただきました。

確かに!ログイン情報を盗まれてしまったらなりすましなんて簡単にできますね。

password_hash関数をマニュアルで調べてみると、


◦$passwordには登録するパスワードの値が入って、
◦$algoにはハッシュ化に使用するパスワードアルゴリズム定数が入って、
◦$optionsには各アルゴリズムがサポートするオプションが入る
とのこと!

アルゴリズム定数のPASSWORD_BCRYPTを使うと
◦”$2y$” crypt フォーマットを使ったハッシュになる
◦長さは常に 60 文字
◦オプションのcostは省略時はデフォルトの10が入り、ハードウェアの性能が許容できるなら高くも設定可

とのことでした。
上記のpassword_hash()関数で登録しなおすことで、

ちゃんとハッシュ化されていました。
これで一安心です!

知らないことが多くて調べて、コーディングして、エラーと闘う日々です。
今後も、いろいろと忘れないようにまとめていきたいと思います。
では、また次回!!

WordPressのデフォルトアバターが表示されない(404エラーになる)問題

WordPressでデフォルトのアバターを表示させると、以下のようなGravatarのURLを生成します。

https://secure.gravatar.com/avatar/?s=60&d=mm&r=g

このURLが2023年8月9日現在404エラーとなっています。

次のようにパラメータの順番を変更すると正常に表示されます。

https://secure.gravatar.com/avatar/?s=60&r=g&d=mm

さすがにこれが仕様ということは無いと思うので、何かしら不具合が発生していると思われます。

Gravatarにお知らせしたいのですが、不具合を報告したり、お問い合わせするようなフォームが見つけられなかったので諦めました。

Gravatarの中の人ー!見てたら直してくれー!

Workaroundとしては、WordPressが生成するURLのパラメータを並べ替えることが考えられます。

以下のようにURLの生成箇所に用意されているフィルターでパラメータを並べ替えればよいでしょう。

Gravatarが修正されるまでの一時的な物なのでプラグイン化するほどではないかなと思います。

お使いのテーマのfunctions.phpに入れればよいのではないでしょうか。

新入社員ブログ 中島06『chatGPTでカレンダーアプリを作ってみた』 

こんにちは。22年度入社の中島です。

今回は、最近流行りのChatGPTを使ってプログラムをやってみました。
それを簡単にまとめましたので、紹介したいと思います。

ChatGPTとは?
ChatGPTは、高度なAI技術によって、人間のように自然な会話ができ、無料で利用できるAIチャットサービスです。2022年11月に公開されてから、多種多様な質問に対する返答が面白いとSNSなどでバズっています。

実際に使ってみた
プログラムについてもできると聞いたので、簡単なプログラムが作れるのか実際に使ってみました。
仕様としては
・『ブラウザ上で見られるスプリクトで、
 カレンダーの日にちをタッチすると赤色になるプログラムを作ってください』
と入力しました。

出てきたプログラムがこちらです

<!DOCTYPE html> <html> <head> <meta charset=”UTF-8″> <title>Calendar</title> <style> /* カレンダーのセルをスタイル付け */ td { padding: 10px; border: 1px solid black; text-align: center; cursor: pointer; } /* 赤い背景色を追加 */ .selected { background-color: red; } </style> </head> <body> <table> <thead> <tr> <th colspan=”7″>March 2023</th> </tr> <tr> <th>Sun</th> <th>Mon</th> <th>Tue</th> <th>Wed</th> <th>Thu</th> <th>Fri</th> <th>Sat</th> </tr> </thead> <tbody> <tr> <td></td> <td></td> <td></td> <td></td> <td>1</td> <td>2</td> <td>3</td> </tr> <tr> <td>4</td> <td>5</td> <td>6</td> <td>7</td> <td>8</td> <td>9</td> <td>10</td> </tr> <tr> <td>11</td> <td>12</td> <td>13</td> <td>14</td> <td>15</td> <td>16</td> <td>17</td> </tr> <tr> <td>18</td> <td>19</td> <td>20</td> <td>21</td> <td>22</td> <td>23</td> <td>24</td> </tr> <tr> <td>25</td> <td>26</td> <td>27</td> <td>28</td> <td>29</td> <td>30</td> <td>31</td> </tr> </tbody> </table> <script> // カレンダーのすべての日付セルを取得 const dateCells = document.querySelectorAll(‘tbody td’); // カレンダーの各日付セルにクリックイベントを追加 dateCells.forEach(cell => { cell.addEventListener(‘click’, () => { // クリックされたセルに ‘selected’ クラスを追加 cell.classList.add(‘selected’); }); }); </script> </body> </html>

それをブラウザで開くとこんな感じです。

日付をクリックしたら赤くなるカレンダー


入力通りのものができました。
ですが、これでは赤色にしてしまうと元の戻らないので、仕様を追加します。

・上記のプログラムに以下の仕様を追加してください
 『日付がクリックされるたびに 赤→青 青→白 白→赤に切り替わる』

出てきたプログラムがこちらです

<!DOCTYPE html> <html> <head> <meta charset=”UTF-8″> <title>Calendar</title> <style> /* カレンダーのセルをスタイル付け */ td { padding: 10px; border: 1px solid black; text-align: center; cursor: pointer; } /* 赤い背景色を追加 */ .red { background-color: red; } /* 青い背景色を追加 */ .blue { background-color: blue; } </style> </head> <body> <table> <thead> <tr> <th colspan=”7″>March 2023</th> </tr> <tr> <th>Sun</th> <th>Mon</th> <th>Tue</th> <th>Wed</th> <th>Thu</th> <th>Fri</th> <th>Sat</th> </tr> </thead> <tbody> <tr> <td></td> <td></td> <td></td> <td></td> <td>1</td> <td>2</td> <td>3</td> </tr> <tr> <td>4</td> <td>5</td> <td>6</td> <td>7</td> <td>8</td> <td>9</td> <td>10</td> </tr> <tr> <td>11</td> <td>12</td> <td>13</td> <td>14</td> <td>15</td> <td>16</td> <td>17</td> </tr> <tr> <td>18</td> <td>19</td> <td>20</td> <td>21</td> <td>22</td> <td>23</td> <td>24</td> </tr> <tr> <td>25</td> <td>26</td> <td>27</td> <td>28</td> <td>29</td> <td>30</td> <td>31</td> </tr> </tbody> </table> <script> // カレンダーのすべての日付セルを取得 const dateCells = document.querySelectorAll(‘tbody td’); // カレンダーの各日付セルにクリックイベントを追加 dateCells.forEach(cell => { cell.addEventListener(‘click’, () => { if (cell.classList.contains(‘red’)) { cell.classList.remove(‘red’); cell.classList.add(‘blue’); } else if (cell.classList.contains(‘blue’)) { cell.classList.remove(‘blue’); } else { cell.classList.add(‘red’); } }); }); </

それをブラウザで開くとこんな感じです。

日付をクリック色が切り替わるカレンダー

今度こそ思い通りのものができました。
このように仕様を途中から追加しても、ちゃんと入れてくれます。
このプログラムを基盤に書き換えながら別のプログラムを作れます。

まとめ
いかがでしたか?
今回は、話題となっているChatGPTを使ってみました。
私は、ここ最近わからないことがある時にChatGPTを使って聞いていますが、会社で使う際は、直接仕事の具体的な情報を入力しないように心がけます(これは先輩からもよくよく言われています)。仕事と関係なく、サンプル的なアプリを作る時は、非常に便利なのでChatGPTを使いながらプログラムを学んでいきたいと思います。

今回はここまで
最後までご覧いただきありがとうございました!

virtualboxでPHPの環境構築を作成してみた

皆さん、こんにちは入社2年目の鹿倉です。今回は、virtuakboxでPHPの環境構築を作成してみました。

何故:virtualboxでPHPの環境構築を構築しようと考えたのか。

 PHPを学習し始めた人々や研修を受けた人々では、PHPで環境構築する際に、xampp やmampなどのパッケージを利用してPHPを学習している人は、多いと思っています。
 しかし、私がこれまで、関わっていたプロジェクトでは、xampp やmampを使用して開発は、1度もありませんでした。では、何を使って開発しているのでしょうか。
 結論から言えば、プロジェクトによります。しかし、私の経験上、最も開発環境構築で利用したのは、virtualboxで環境構築を作成するケースが多かったです。そこで、今回はvirtualboxでPHPを環境構築を作成しようと考えました。

開発手順

事前定義:今回のPHPの環境構築では、以下の条件を元に作業を行う。また、VirtualBox,Vagrant,centOSは、インストールされた状態とする。

・VirtualBox バージョン6.1
・Vagrant バージョン2.2.18
・centOS バージョン7.8
・PHP バージョン 5.4

1.作業ディレクトリから仮想環境に接続までの手順
1-1.作業ディレクトリの作成
仮想環境に必要なディレクトリを用意する。ディレクトリは、以下の例で作成する。
[crayon-65d6a2d0a2127829762217  ]$ mkdir  F:\space_php[/crayon]

1-2.Vagrantfileを作成
ディレクトリを作成したらcdコマンドで移動して、vagrant initのコマンドを実行してVagrantfileを作成します。Vagrantfileとは、IP、ポートなど構築時に設定を記述する事が出来るファイルです。


[crayon-65d6a2d0a2134931803553  ]$ vagrant init[/crayon]

1-3.仮想環境を起動します。
以下のコマンドを実行する事で、Vagrantを起動します。

1-4.仮想環境にssh接続を
sshで接続するコマンドを実行します。ssh接続をする事で、仮想環境上で、PHPやApacheのインストールなど仮想環境上で操作を行う為にssh接続で仮想環境に接続します。



2.仮想環境でのサーバー構築
2-1.PHPとApacheのインストール
ssh接続に成功したら、いよいよ、仮想環境にPHPとApacheのインストールを行います。
以下のコマンドでインストールを実行します。

2-2.Vagrantfileの設定
Vagrantfileでネットワークの設定を行い、ローカルから仮想マシンを見られる様に、編集します。その為に一旦、ssh接続を解除します。以下のコマンドで解除出来ます。
[crayon-65d6a2d0a2148532281264  ]$ exit[/crayon]
Vagrantfileで以下の記載されている内容を#を外してコメントアウトします。


コメントアウト後、再起動を行い、再び,ssh接続を行います。


ssh

2-3.Apacheのファイル編集
phpを表示させる為、Apacheファイルを修正をします。
以下のコマンドでファイル内を閲覧します。


移動後、ファイル内で以下の記載されているのか確認をします。。
[crayon-65d6a2d0a2161266208282  ]AddType application/x-compress .Z [/crayon]
[crayon-65d6a2d0a2169789433492  ]AddType application/x-gzip .gz .tgz[/crayon]
上記の2行を発見したら以下の内容に変更します。


[crayon-65d6a2d0a2175691157419  ]AddType application/x-httpd-php-source .phps[/crayon]
この変更をする事でApacheは拡張子がPHPのファイルをPHPプログラムとして処理を行う事が出来ます。

2-4.phpファィル作成と動作確認
これで、設定を完了しました。最後に、phpファイルを作成して、ブラウザで表示されるか動作確認を行います。以下のディレクトリに移動して、phpファイルを作成します。



test.phpは以下の内容を記載しました。

記載後、ブラウザで

でこんにちは、PHPと表示されたら成功です。

最後に

 今回の環境構築を作成してみて、構築は簡単ではないですか、作業をする事でどの様にして、ブラウザで表示されるには、どの様な条件でなければならないのか理解するいい経験でした。
 しかし、プログラマーの年数が上がるにつれて、今度は、開発環境で、何か必要なのかを見極める事が必要なのだと考えています。
 今度、Laravelの導入だったり、Chefを使った自動構築など色々調べて学習を継続する事が今度、未来の私が困った時にその経験が助けになると考えています。

それでは、また次の記事でお会いしましょう。アディオス😃

コーディング規約の重要性 

皆さん、こんにちは、入社2年目の鹿倉です。今回はコーディングの重要性を語ろうと思います。

コーディングとは

 コーディング規約の前にコーディングとは、何でしょうか。
 コーディングとは、プログラミング言語を使ってソースコードを作成する事です。曖昧な事ですが、詳細には、仕様書に沿って、ソースコードを作成して、ブラウザで見える化をする事です。
 読者は、あれ?、それってプログラムじゃないかと疑問に思っているかもしれませんが、実は、コーディングはソースコードを書く事だけを指しています。一方でプログラムは、書くだけではなく、設計したり、テストする事を指しているのです。

コーディング規約の重要性

 コーディングの意味を知った所で、いよいよコーディング規約を説明します。
 コーディング規約とは、開発者がプログラム言語でソースコードを記述する際に、形式や書き方を決める事です。簡単に言えば、プロジェクトで開発する際に、ソースコードの形式のルールを決める事です。
 実は、コーディング規約を決めるのは、とても重要な事なのです。何故なら、コーディング規約を決める事で、作業効率が上がる事が出来るからです。
 例えば、プロジェクトで複数メンバーで開発する際、メンバーそれぞれがコーディングを自由に書いたらどの様な事が起きるのでしょうか。
 他者のソースコードを見る際に独特なソースコードが書かれた場合、理解するのに時間が掛かる事でしょう。そうなると、理解するのに時間が掛かり、効率が悪くなってしまいます。それを阻止する為に、コーディング規約は、非常に重要なのです。

PHPにおけるコーディング規約の例

 では、実際にコーディング規約には、どんなルールがあるのでしょうか。
今回は、PHP言語で、コーディング規約の例を説明しようと思います。
 PHPのコーディング規約で代表的なのは、PSR-2 と呼ばれるコーディング規約です。この規約は、PHPでソースコードを記述する際に、PHPのコーディングスタイルつまり、形式についての規約が記載されています。では、PSR-2にはどの様なコーディング規約があるのでしょうか。

簡単なプログラミングを例に説明します。以下のプログラミングは、readline関数でユーザーのコンソールで年齢を入力したのが$ageに代入されます。その後、関数で年齢の範囲を判定して、関数の結果を出力しています。

■PSR-2のコーディング規約の一部の例

・if文の「{」の前では改行してはいけない。
・elseやelseifの前後括弧は同じ行に配置。
・else ifではなくelseifで1語でまとめられる様にする。
・インデント(字下げ)をする際は、半角スペースを4つ開ける。

ここに、記載されていている、PSR-2は、一部に過ぎません。
 他にも、PSR-2では、PHPのコーディング規約は多くあるので、以下のURLでも参考にしても良いと考えています。是非、参考にして見てください。

URL:http://www.php-fig.org/psr/

コーディング規約の記事を作成した考えた事

今回のコーディング規約について記載して思った事は、プログラマーは、決められたコーディング規約の中で最適なコーディングを書く事が重要だと考えました。
 ソースコードには、エラーが起こらない限り書き方は、自由です。しかし、自由にし過ぎると他者がソースコードを見た時に、理解出来るのかの方で重要です。
 そうしなければ、結局は、私しか理解する事が出来ないコードになってしまって、開発する際に、大きく足を引っ張ってしまいます。
 プロのプログラマーを目指す人には、ただソースコードを書くだけではなく、自分が書いたソースコードを他者に説明するスキルを身につける事が必要だと私は、考えています。

それでは、また、次の記事でお会いしましょう。アディオス!!😁

新入社員ブログ 中島04 『PHPテキスト学習1』

こんにちは!そして明けましておめでとうございます。

22年度入社の中島です。

新年が明けたと思ったらもう一ヶ月が終わりました…
とても早い気がします。

『一月往ぬる二月逃げる三月去る』という言葉があるように、ぼーっとしていたらあっという間に四月になるかもしれませんね。

このままだとまずいと思い、今年の1月から技術力向上のためPHPのテキストで学習に取り組んでいます。

今回はその復習も兼ねて、簡単にブログにまとめていきます。

学習に使用したPHPのテキストはこのテキストです。

そして、学習した内容を大まかにまとめると

・PHPの基本
変数、定義、データ型、配列など

・演算子
代入演算子、比較演算子、論理演算子、ビット演算子など

・制御構文
if命令、switch命令、while/do命令、for命令、foreach命令など

・組み込み関数
文字列関数(mb_strlen関数、mb_substr関数、str_replace 関数)
配列関数(count 関数、array_merge 関数、implode関数)
正規表現(PCRE)関数(preg_match 関数、preg_replace関数、preg_split 関数)
ファイルシステム関数(fopen/fclose関数、fwrite関数、fgetcsv関数)

など現在進行形で学習しています。
そして表紙に書いてあるように
『手を動かしながら学ぶ』と書いてあるので、実際にプログラムを打って実行して動きを確認しながら学習しています。

[/crayon]

『テキストを読む』→『プログラムを打ち込む』→『プログラムを実行する』
この流れで学習を行い、理解できない部分は上司に聞いたりGoogleで調べながらより理解を深めていきます。
先ほどもお話ししたように現在進行形で学習中です。テキストのページも半分ほどでまだまだこれからなので、一生懸命取り組んでいきます。

今回はここまで
最後までご覧いただきありがとうございました!

[bug]マルチプロセスでlog4netのファイルローテーション時に一部ログが欠損して困った

福岡の香月です。

log4netのRollingFileAppenderを使って日付で出力ファイルが切り替わる設定をしていたところ、日付が変わって新しいファイルへの出力が始まると先頭に出力されるであろうログがなぜか出力されない現象に遭遇しました。
設定はこうです。
複数のプロセスで同じ設定を用いて、同じファイルに対してログ出力します。

[/crayon]

AppenderはRollingFileAppenderを指定しています。複数プロセスで使用するため、lockingModelはInterProcessLockを指定します。これによりファイルストリームを開きっぱなしにして、mutexで排他制御しながら末端にシークし書き込みを行うことで、複数プロセスから効率的にログ出力を行ってくれます。
複数プロセスから使う場合はこれ以外にもMinimalLockを指定できますが、書き込むたびにファイルのオープンクローズを実施するため速度が求められる場合は不向きでしょう。さらに複数プロセスからの出力が同時に走った場合、片方はオープンできないためログが出力されません。

この設定でビルドし、業務終わりにアプリを起動して一晩中実行させ、翌朝出社して確認しても日付が変わった後のログの内容が足りませんでした。
最初はlog4netの使い方が悪いのか、自分のプログラムにバグがあるのかさんざん悩んだんですがさっぱりわからない。トレース用に埋め込んだログも当然のように出ていないのでどうしたものかと思いました。

しかし、プロセスが1つの場合はちゃんと期待通りのログが出ていました。問題があるのは複数プロセスの場合だけだったのです。

そこでlog4netのロジックを確認することにしました。 幸いなことにソースはこちらから取得できます。
https://github.com/apache/logging-log4net
すると、ファイルが切り替わったあとは最後に書き込んだプロセスのログが先頭に来て、それ以前のログが破棄される作りになっていたのです。

少しずつソースを見てみましょう。今回使っているのはRollingFileAppenderです。日付が変わるときにファイルを切り替える部分は、RollOverTime()という関数であることがわかりました。こうなっています。
https://github.com/apache/logging-log4net/blob/master/src/Appender/RollingFileAppender.cs

[/crayon]

ふむふむ、SafeOpenFile()で新しいファイルをオープンしに行くわけね。そして第二引数がfalseと。そしてSaveOpenFile()の実態はベースクラスFileAppenderにありました。
https://github.com/apache/logging-log4net/blob/master/src/Appender/FileAppender.cs
ここから次の順番で呼び出されていきます。

  • RollingFileAppender.OpenFile()
  • FileAppender.OpenFile()
  • FileAppender.InterProcessLock.OpenFile()
  • FileAppender.LockingModelBase.CreateStream()
[/crayon]

ここでSafeOpenFile()の第二引数で指定されたfalseは、CreateStreamのappendに代入されていることがわかりました。この場合FileMode.Createが指定され、FileStreamインスタンスが作成されます。
ではこのFileMode.Createはどのような動きをするかというと、

オペレーティング システムが新しいファイルを作成することを指定します。ファイルが既に存在する場合は上書きされます。これには Write 許可が必要です。
FileMode.Create は、ファイルが存在しない場合は CreateNew を使用した要求、ファイルが存在する場合は Truncate を使用した要求と等価です。

https://docs.microsoft.com/ja-jp/dotnet/api/system.io.filemode?view=netcore-3.1

複数のプロセスでログ出力を行う場合、FileStreamを最後に作成するプロセスによりそれまでのプロセスが作成したログファイルの中身がTruncateされて、つまり削除されてしまうわけです。
発生している現象とも合致するのでこれが問題であることを確信しました。

対応するためにはRollingFileAppender.RollOverTime()から呼んでるSafeOpenFile()の第二引数をtrueに知ればよいわけです。実際に修正して確認してみると、見事欠損することなく必要なログが出力されていました。
めでたしめでたし。

なお、SafeOpenFile()はRollingFileAppender.RollOverSize()内からも呼び出しているのでここも忘れずにtrueに変更しましょう。