アフィリエイト広告を利用しています
検索
<< 2023年03月 >>
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
最新記事
タグクラウド
カテゴリーアーカイブ
ファン
最新コメント
プロフィール
ゼロから始めるシステム開発さんの画像
ゼロから始めるシステム開発
 こんにちは!ナビゲータのEVEです。各種研究室を用意し、次期EVEシステムを製造しようと日々頑張っています。現在一番力を入れているのが、資金調達です。このブログもその一環ですので、ご協力いただければ嬉しいです。

広告

この広告は30日以上更新がないブログに表示されております。
新規記事の投稿を行うことで、非表示にすることが可能です。
posted by fanblog

2023年03月31日

金融危機 [Coffee Time]

 こんにちは!
 ナビゲータのEVEです。

 今朝起きて、デスクに向かったら、頭がくらくらします・・・。起きた直後は問題なかったのですが、どうも風邪を引いてしまったようです。家からほとんどでないので、 新型コロナっというわけではないと思うのですが ・・・。
 そのため本日は午前中ひたすら眠り、午後から活動しました。以上の理由により、プログラミングまで手が回らず、進捗が遅れている状況です。
 体調は、午前中よりはかなり良くなりましたが、まだ、ちょっと、おぼつかないところがあります。
 今日は早く寝て明日からがんばろうかなって考えています。
 以上により、本日は、ブログネタがないので、久しぶりに時事ネタでブログを書きたいと思います。
 本日は、金融危機です。

[アメリカ発の金融危機]
 アメリカ発の金融危機と聞いたら、多分 リーマンショック を思い出される方が多いと思いますが、つい最近また、このキーワードでニュースになっていました。

?シリコンバレーバンク経営破綻
?シグネチャーバンク経営破綻
?シルバーゲート銀行自主廃業

 ??は、歴代 2番目、3番目の経営破綻 だそうです。その2銀行の経営破綻により、再びリーマンショックのようなことになるのじゃないのか?なんてテレビなどのメディアはかなり強いトーンで報道していましたが、私は心配はしていませんでした。なぜかというと、リーマンショックの時とは、政府や世間の雰囲気が違うからです。
 リーマンショックの時は、 大きすぎてつぶせないような事態にならないように、適切な対応をする と、オバマ大統領が発言するなど、金融機関への世間の風当たりはかなり冷たいものがありました。
 金融機関は、リーマンが倒産する直前まで、金儲け主義にはしり、 サブプライムローン などの一見優良を装った悪徳商品を販売していました。その商品価値のバブルがはじけ、あの事態になったのだから当然です。リーマンショックにより失業した人などは、多分、金融機関を恨むというか 呪っていた と思います。
 しかし、今回はどうでしょうか?政府は、預金者の全額保護を確約し破綻のショックを沈静化しようとしています。

[クレディスイスの倒産危機]
 以上のような理由で、アメリカの方は心配していなかったのですが、まずいな〜?って思ったのは、 クレディスイス の方です。こちらは、クレディスイスの大口投資家の、「もうこれ以上出資できない」といった発言から信用不安が発生し、もしかして、経営破綻かと言われました。
 名前にスイスとついているので、ご想像通りスイスの銀行です。スイスって、今まで世界の銀行の中の銀行とか言われていて、信用が高く、破綻という言葉から一番遠い所にあったような気がします。だからだと思うのですが、今まで、このような金融に関する財政出動の話を聞いたことがありません。そのため、適切に対応できるのかという疑問と、救済するだけの資金があるのかどうか非常に心配でした。
 そんな心配している中、どこぞやのエコノミストは、 大きすぎて救済できないかもしれない なんて発言していたりして、その当日かなりやきもきしました。
 ただ、私の気持ちとは裏腹に、テレビなどはほとんど報道することはなかったですね・・・?私の感覚からすると、 意味が分かりません が???シリコンバレー銀行よりは、こっちだろっていう感じです(笑)。

[今後はどうなる?]
 クレディスイスも、UBS銀行に買収され、一旦は信用不安はなくなったようです。この時の、スイス国立銀行の対応は早かったですね!!!日本時間の金曜日の夕方、ニュースになってから、日本時間の月曜日の朝には、買収が決まっていたのですから・・・。
 という状況で、世界的に協調し、金融不安は沈静化したようです。まっ、 適切に各国が対応すれば、問題ないという事でしょう

 以上については、まだ、この手の話については素人のブログの筆者が、勝手に思っていることです。専門家の方が見たら、突っ込みどころ満載の内容となっているかもしれませんが、その点については、お許しください。現在、詳しい分析できるように勉強中です。

 正直言って、テレビのニュースってあまり信用できないっていう印象を持っているので・・・。そういう場合、自分で分析できる能力をつけなければいけません。
 いつになるか分からないのですが、経済学、経営学の知識を生かしたシステムを作りたいな〜♪って思っています。その時のためにも、知識は必要です。システムを作ろうとした場合、その仕様まで理解していないと作れません!!!

 では、また!!!

2023年03月30日

ドツボにはまっています [プログラム研究室]


 こんにちは!
 ナビゲータのEVEです。

 昨日の検討を受けて、プログラムを修正、試験をしているのですが、ドツボにはまっています。

[今日の確認状況]
 何が問題かというと、 PDO で接続してできた、インスタンスをサーバーサイト・セッションに設定しそれを各プログラムで使いまわそうとしているのですが、 エラー になります。ちなみに、Transaction、Insert、Commit処理を実施後、PDOインスタンスをサーバーサイト変数として再設定するという作業を行えば、とりあえず、Transaction、Insert、Commitの機能は利用することができます。ただ、やはり、エラーが表示されます。
 エラーメッセージは、以下の通り・・・。

Fatal error: Uncaught Exception: Serialization of 'PDOStatement' is not allowed in [no active file]:0 Stack trace: #0 {main} thrown in [no active file] on line 0

  エラーの発生個所は、New Prototype EVEのレコード追加メソッド内のプリシアードステートメントへバインド変数を設定している所で起きているっぽい・・・。ぽいっというのは、細かいレベルまで、トレースが終わっていないためです。
 通常のメモリから、サーバーサイト変数、セッション変数に設定するときに何かしらの変換がされているようなのですが、その変換のせいでエラーとなっているということだと思われます。
 これが、Warningならまだかわいいのですが、Fatal errorです。無視もできず、現在も対応策を考えています。

[あとがき]
 以上のメッセージをうけて、 serialize unserialize メソッドを利用して、上記メッセージを回避しようとしましたが、今のところ解消できていない状況です。いい考えだと思ったのですけれどね・・・。PDOインスタンスをサーバーサイト、セッション変数で共有して各プログラムで利用する方法・・・。
 インターネットでは、1件だけ同じ悩みを抱えている人がいましたが、そちらのほうは、PDOインスタンスをサーバーサイトへ設定することがマストではなかったようで、PDOから中身を取り出して、それを、サーバーサイト変数として設定していました。
 私は、そのような手法は利用できませんし・・・。やはり、大本から仕様変更しないとだめかもしれません・・・。

 もうちょっと、粘ります!

 では、また!!!

■PHPのシリアライズを知ろう!便利な使い方徹底解説(SAMURAI ENGINEER Blog)
https://www.sejuku.net/blog/80079

2023年03月29日

仕様の再検討〜Prototype EVE〜 [プログラム研究室]


 こんにちは!
 ナビゲータのEVEです。

 昨日の問題点を受けて、本日Prototype EVEシステムの仕様について再検討を行いました。

[仕様の再検討]
 昨日、New Prototype EVEをの仕様の再検討をするという話をしましたが、そちらは、しなくていいようです。仕様の再検討が必要なのは、Prototype EVEの方・・・。
 再検討の結果としては、

1つのインスタンスで処理を完結する

 DB関連クラスの中には、データベースに関する基本的な機能が全て入っています。そのため、一度インスタンスを作成すれば、そのインスタンスでデータベースに関する操作を一通りすることができます。そのインスタンスを、昨日お話しした通り、 サーバーサイト変数 に設定し、プログラム内で共有します。
 以上の考えに則って作成したのが、下記のプログラムです。本日は、Insertだけ作成してみました。もしかして、考えが変わった、足りないなどがあったら、本日中に追加・修正します。もし、考えに変わりがなければ、トランザクション、コミット、ロールバック関数を作成後、明日から試験に入りたいと思います。



/*************************************************
*【メソッド名】DBinsert 関数(Prototype EVE)
*【 引 数 】
* p_sub 種別
* p_table テーブル名
* p_item 項目名(配列)
* p_data 入力データ(配列)
*【返 却 値】
* 正常時:""
* 異常時:""以外
*【製 造 者】EVE
*【製造年月日】2005年02月20日
*【更新年月日】2023年03月29日
*【リリース日】
*【バージョン】
*【 概 要 】
* [2023/03/29]
* レコードを追加する
*************************************************/

function gb_dbinsert($p_table,$p_item,$p_data ) {
//変数定義
$rtn = ""; //返却値
$db = ""; //コネクトインスタンス

//引数の入力データチェック
//テーブル名を確認する

if ( $p_table != "" ) {
//テーブル名が設定されていない場合
return "テーブル名が設定されていません。";
}
//項目数とデータの数を比較する
if ( count($p_item) != count( $p_data ) ) {
//違いがあった場合エラーメッセージを返却地にセットする
return "カラムとデータに不整合があります。";
}

//サーバーサイト変数の判定を行う
if (session_id()) {
//セッションIDが設定されている場合
//コネクトインスタンスを取得する

$db = $_SESSION['db'] ) {
} else {
//セッションIDが設定されていない場合
//セッションを開始する

session_start();
}

//コネクトインスタンスの判定を行う
if ( $db == "" ) {
//コネクトインスタンスが設定されていない場合
//インスタンス作成

$db = new getInfDB(db,host,'utf8',user,pass);
}

//データベースの登録の初期設定を行う
//SQLを実行する

$rtn = $db->recInsert($p_table,$p_item,$p_data);

//返却値を設定する
if ( $rtn == false ) {
//サーバーサイト変数を削除する
unset($_SESSION("db"));
//返却値が異常の場合
$rtn = $db->getErrorMessage();
} else {
//インスタンスをサーバーサイト変数として設定する
$_SESSION['db'] = $db;
}

//返却値の返却
return $rtn;
}



 以上のプログラムは、テキストエディタでプログラミングしたばかりのもので、デバックも何もしていません。多分、動かないと思います。こんな感じで作成してるんだな〜♪っぐらいに見てください。

[あとがき]
 やっと、頭の中がすっきりしました。方針がほぼきまり、いけそうだといった印象を持つことができました。
 方針が決まらないと、もんもんとしてしまい、なかなか、他の作業が手がつかないので、ひと段落です。ただ、デバックしてみないと最終的にはわかりませんが(笑)。

 うまくいくといいな〜♪

 では、また!!!
タグ: php

2023年03月28日

なめすぎ・・・。 [プログラム研究室]


 こんにちは!
 ナビゲータのEVEです。

 Prototype EVEの修正に入っています。ただ、問題が・・・。

[考えが足りなかった・・・。]
 Prototype EVEを修正してわかったこと・・・。考えが足りませんでしたね・・・。何って、オブジェクト指向言語って、最初のデータベースへの接続インスタンスを使って、トランザクションの開始、コミットをしますが、その インスタンスをPrototype EVEから見ることができません
 Prototype EVEでは、ループでレコードを1件つづ、レコード追加、レコード更新が行われる処理があります。現在は、そのループ処理の開始位置で、トランザクションを開始させ、そのループ処理が終了した時点で、コミットしています。
 何も考えずにプログラム修正をしようと思いましたが、最初の段階で手が止まってしまいました。

[じゃ、どうする?]
 インスタンスを、 サーバーサイト変数 に設定し、各処理は同サーバーサイト変数を使って、制御することにします。できますかね・・・・?New Prototype EVEを抜けた段階で、インスタンスが廃棄され、コミットされるような気がしますが・・・?希望的観測から言うと、クラスを抜けた段階ではなく、プログラムが終了した段階でオブジェクトが廃棄され、コミット、データベースクローズしてくれれば助かるのですが・・・。ここにきて、挫折しています。

[今後の予定]
 今後の予定としては、とりあえず、現在考えている案で、New Prototype EVEの改修を行います。そして、試験をしてうまくいったら、横並びでDMLの処理を修正(selectを除く)を行います。
 2023年3月31日までに、改修作業を完了したかったのですが、難しそうです。今回の改修作業なめすぎていたようです。

 オブジェクト指向言語のプログラムになれてきている現在、EVEシステムを作り始めた方が早いかもしれないと思った、本日の製造報告でした。

 では、また!!!

2023年03月27日

Prototype EVEの仕様変更 [プログラム研究室]


 こんにちは!
 ナビゲータのEVEです。

 昨日自宅に帰宅しました。

 今回の旅行は、ひたすら寝ていました。やはり、寝不足だったようです???いつもなら、AmazonのPrime Videoを見てそのリポートをするのですが、ビデオを見ている途中で寝てしまい、昨日、早速ブログを更新しようとしたのですが、更新するネタがありません(笑)。夢を見ているなら、夢リポートするなんてこともできるのですが、ここ数年夢を見ることがなくなりました。起きているときは、よく夢を見るのですが(笑)?

[Prototype EVEの仕様変更]
 とりあえず、Prototype EVEのデータベース関連プログラムの仕様を変更しようとしたのですが、EVEシステムにおいて、基本的な機能として、テーブルロックが入っていないことに気づきました。

独習PHP 第4版 [ 山田 祥寛 ]

価格: 3,740円
(2023/3/27 17:54時点)
感想(1件)



 「 独習PHP 」でテーブルロックについて調べたのですが、記述が見つかりません。そのため、インターネットから情報を集めようとしたのですが、ほとんどないという状況です。その理由なのですが、 トランザクション に関係しています。

[トランザクションの機能]
 IPAの試験などを受験していると、トランザクション処理には、 ACID特性 が求められるとされています。
 ACID特性とは、トランザクション処理の以下の特性の頭文字をとって、付けた呼称です。

・Atomicity(原子性)
・Consistency(一貫性)
・Isolation(独立性)
・Durability(耐久性)

 それぞれについて解説すると、 Atomicity ( 原子性 )は、個々のプロセスが「すべて実行される」、か「1つも実行されないか」のどちらかの状態になるという性質を指します。
Consistency ( 一貫性 )は、トランザクション前後で整合性が保たれ、矛盾のない状態が継続されることを指します。
Isolation ( 独立性 )は、トランザクション実行中の処理の過程が外部から隠蔽され、他の処理などに影響を与えない性質を指します。
 そして、最後に、 Durability ( 耐久性 )ですが、トランザクション処理が完了したら、その結果は記録され、システム障害などが生じても失われることがない性質を指します。
 ようは、トランザクション処理を使用しているプロセスでは、テーブルロックは不要だというのです。確かにそうです。

 Prototype EVEの初期のバージョンでは、MySQL自体にトランザクション処理がなかったため、テーブルロックを使用していたのかもしれませんが・・・?っと、思うのですが、過去を振り返って、どんな経緯でこのようなプログラムになったのか思い出せませんし、資料もありません。

[MySQL]
 MySQLの機能を改めて調べていないのですが、MySQLは、Oracleのように 行ロック できません。ロックする場合は、 テーブルロック です。そのため、トランザクションを開始すると更新対象となるテーブルはすべてテーブルロックがかかり、そのロックにより、ACID特性が保証されると思われます。ただ、処理のどの辺で、テーブルにロックがかかるのでしょうか?
 夜間のバッチなどは、処理する量が膨大です。
 夜間処理において、トランザクションを開始します。Aと言うテーブルを10分間更新処理を行い、それからテーブルBへ処理が移ります。その場合、Bのテーブルがロックされるのは、トランザクションを開始した時点でしょうか?それとも、Bの処理が開始されてからでしょうか?
 PHPはインタプリタ言語なので、Bの処理の更新が開始されてからと思われのですが、そう考えると、トランザクションの機能として片手落ちのような気がします。
 これは、調べる価値がありそうですね・・・。ただ、仕掛けが大がかりになります。Prototype EVEの改変後になると思いますが、時間がありましたら、調べてみたいと思います。
 ただ、やらないという可能性もあるので、以上について知っている方がいましたら教えてください。

[Prototype EVEの改修作業]
 以上のような事を考えていると、トンドン改修作業が遅れていきます。そのため、前回お話ししたとおり、何も考えずに一気に改修作業を進めます。
 最初、データベース関連のプログラムを修正していくのですが、以下のような状態です。EVEシステムが1,000ステップ弱なので、力仕事の量としては、少ないかもしれません。ただ、それに加え、他の関数でも直接データベースを見に行っているモノも修正対象です。それを、まだ把握していません。近日中にどのくらいあるのか把握して作業量を見積もりたいと思います。できれば、3月中に改修作業を終えたいのですが、その希望が実現するかどうかは、直接データベースを見に行っているプログラムの数に影響されます。

 帰ってきた初日はこんな感じです。これから、がんがん修正していきます。
 作業は、それでいいのですが、明日以降のブログに困っています。公開できるプログラムがほとんどないと思われるので、どうしましょうか??っと今から困っている状況です。
 何かしらの作業はやっているので、その作業について何かネタがありましたら、つぶやいていきます!

 では、また!!!

■Prototype EVE変更プログラム
 修正プログラム本数 26本
 修正プログラムステップ数 2233ステップ

《参考サイト》
■IT用語事典(e-Words)
https://e-words.jp/w/ACID%E7%89%B9%E6%80%A7.html

2023年03月23日

今後の予定・・・。 [プログラム研究室]


 こんにちは!
 ナビゲータのEVEです。

 開発に戻りました。っといっても、一通り作ってしまっており、その過程において、開発のコンセプトもしっかりとしてきました。そして、本日は、ソースの見直しと今後の予定をたてています。

[ソースの見直し]
 先日作った setter getter の一部に バグ があったので修正しています。前回の試験結果をうけて、今後、プロパティへのデータの設定・取得は、setter、getterを用いて行うことにしました。これにより、 親で利用しているプロパティを子でも自由に設定、取得することができるようになります 。子から親のプロパティにデータを設定しようとすると、エラーにはならないのですが、設定・取得できないという事象からこのような対策をしています。
 そして、すべての機能をメソッドとして定義することにより、 クラスにどんな機能があるのか明確になります 。1カ月ぐらいはどこにどんな機能があるのか覚えている自信はありますが、1年もたてば、多分忘れているでしょう(笑)。そんなことを考慮に入れると、今回の対策は適切だったと思っています。
 あと、ソースのコメントに一部誤植があるようです。 コメントが大事 なんてブログに書いていながら、残念なことですが、デバックできないコメントって、バグをつぶすのに時間がかかります。思い込みもありますし・・・。こっちは、時間をかけて徐々につぶしていきたいと思います。こんな時に思いますが、最初が肝心だなって感じます。

[今後の予定]
 今後の予定ですが、以下のように考えています。

?Prototype EVEシステムのデータベース関連関数をすべて、New Prototype EVEに書き換えます。
?Prototype EVEでは、データベース関連関数を通さずに、データベースへ直接見に行っている関数(セキュリティ関数など)があるので、そちらは、New Prototype EVEのデータベース関連クラスに書き換えます。
?以上の作業完了後、Prototype EVEのフレームワークにログインを試み、PHP8と、Prototype EVEの不整合を確認します。

 なお、以上の作業においては、最初に方針を決めたのち、その方針に基づき、個別に何も考えることなく一気に作り上げます。多分、一度歩みを止めたら、いろいろと考え作業をやめてしまうような気がするからです・・・。
 もし、?の段階で使えないという判断になったら、再度検討し作り直す予定です。

[あとがき]
 以上のように考えているなら、今からすぐにでも始めればいいのですが、明日からちょっと、骨休みに旅行に行く予定です・・・。毎日、こんなことをやっているとやはり、休みが必要です。
 近頃、頭痛がひどいと思い原因を考えたのですが、多分、睡眠不足です・・・。いろいろやっていると夜遅くなってしまいます。しっかり休んで、万全な体調で、来週からシステム改修に入りたいと思います。

 では、また!!!

追伸・・・。
 継承を利用することにより、EVEシステムと同じような機能のNew Prototype EVEのソースコードが半分になりました。いちいちそれ用にソースを書き換えていたら大変です。継承って便利ですね!

New Prototype EVE 484行
EVEシステム   914行
タグ: getter setter 継承 php

2023年03月22日

WBC日本優勝おめでとう! [Coffee Time]


 こんにちは!
 ナビゲータのEVEです。

 本日は、WBCの決勝でした。結果は、皆さんご存じの通り、日本の優勝!おめでとうございます。

 テレビのオンタイマーを7時50分に設定して決勝戦を見ようとしたのですが寝過ごしました(笑)。テレビは、タイマー通りついたのですが、起きれませんでした。布団を出ることができたのは、3回ぐらいだったと思います。
 そのときは既に、2対1となっており、もしかして勝つかもしれないと言うことで、手に汗握ってドキドキしていました。しかし、試合展開は凪・・・?アメリカも得点するのですが、ホームランですし、なかなかドキドキする展開はありませんでした。
 ただ、私が日本No1ピッチャーだと思っているダルビッシュが8回に、ホームランを打たれ、スコアが3対2になった後ぐらいですかね?ちょっと、 ドキドキ したの・・・。ホームラン打たれれば同点ですし、誰か出塁して、ホームランを打てば逆転です・・・。よからぬ妄想を抱いていましたが、最後に 大谷君 が出てきて、ピッシリ押さえて試合終了!大谷君本当にすごいです。結局彼が MVP を取りましたが、文句を言う人はいないでしょう?

[アメリカチーム]
 3年前のWBCも、テレビで日本vsアメリカ戦を見たのですが、そのときの印象は、3Aの選手が多いな???このチームに勝っても、アメリカに勝ったことにならないじゃないっていう印象だったのですが、今回は違ったようです。3年前とは比べものにならないぐらい、実績において、 一線級の選手 が出てきたようです。そこに勝ったことは大変意味があり、給料という面から言うとかなりの バリューを感じました
 次の2026年は、2023年以上の選手をそろえてくれることを期待しています!まっ、そのときも、両チームとも、決勝戦まで勝ち抜いていかなければならないのですが・・・。今回も、大変でしたが、多分3年後はもっと、大変な状況になっていると思います。

[世界を舞台にした試合]
 チームプレーが必要な世界レベルの試合において、日本は、ラグビー、サッカーと来て、野球と本当にいい勝負をするようになりました。ただ、野球が、ラグビー、サッカーと大きく違うのは、 優勝 したこと!本当に嬉しいです・・・・。試合が終わった後も、しばらく、ぼ〜〜〜〜〜〜〜〜〜〜〜〜〜っとしていました。次の2026年のWBC楽しみにしています!

 では、また!!!

2023年03月21日

WBC準決勝 [Coffee Time]


 こんにちは!
 ナビゲータのEVEです。

 昨日寝苦しく、本日、10時過ぎに起きました。そんな日本は、休日だったので、ゆっくりしていたのですが、テレビを見ると、WBCがやっている・・・。そういえば、22日の朝っていう宣伝を聞いたことを思い出しました。

[今日もやることがてんこ盛り]
 本日まで全勝でここまできた日本ですが、今日の対戦相手はメキシコで、テレビの下の方のスコアは、3対0になっていました。しかも7回・・・。メキシコの出場選手は全員メジャーリーガーって聞いていましたし、7回まで0点と言うことは、ここで日本も終わりかな?って思いながら、朝食を食べながら、そろそろ本日の活動をしようと思った矢先、4番に入っている、 長淵剛似の吉田 くんが、 3ランホームラン を打って同点!!!興奮しますよね?ここで、本日の予定が全て狂ってしまいました。
 この段階で、大型テレビで見るのを諦め、自分の机上にあるハンディテレビで見れば良かったのですが、この興奮状態では、自分の部屋に行くなんて気分になれません。
 結局9回まで、大型テレビの前に居座ってしまいました。同点になった後また先行され、9回裏の日本の攻撃を迎えるのですが、先頭の 大谷君 2塁打 で出塁!そして、 長淵剛似の吉田君 フォア−ボール で出塁で、1、2塁となりました。ここで、今回絶不調の 村上様 !WBCで悪かった分際で、ペナントレースで調子がよかったら、月に代わってお仕置きよ!っなんて、悪態をつきながら、祈るように見ていたのですが、さすが去年の三冠王です! センターを抜くヒット !これで、サヨナラ勝ちです!本当にいいタイミングで起きたなって思いながら、テレビを切りました。

[佐々木朗希しっかいしろ!]
 この試合の先発は、どうも、 佐々木朗希君 だったらしいのですが、彼、3ランホームランを打たれ降板したようです。7回から見たWBCですが、ベンチを時々映すのですが、佐々木朗希君の表情が暗い・・・。その表情からは、「 どうしよう・・・。僕のせいで日本が負けたら・・・。日本に帰れないかもしれない・・・ 」なんて心の悲鳴が聞こえそうな表情でした。
 まっ、どんなにいいピッチャーでもミスはあるし、打たれることはありますよね?もっと、図太い神経を持って欲しいと、日本のベンチを見て思いました。

[開店休業]
 以上のような状況で、本日、開発まで手が回りませんでした。そのため、開発に関する報告はございません。まっ、WBC楽しめたからいいですか?
 本日も、 8時ちょっと前から、テレビ朝日系列でWBCの決勝が放送 されます。一番見たかった組合せです。 日本vsアメリカ !じっくり見たい!ただ、それだと、午前つぶれますよね・・・。とりあえず、明日は、テレビをつけて横目で見ながら、予定をこなします。
 興奮するような試合だったら、どうなりますかね?多分、今日のような状態になると思います。しかし、大差で負けるような試合だったら、開発等に集中します!っていう予定をしています!

 明日は早いので、寝ます!

 では、また!!!

2023年03月20日

Transaction、Rollback、Commit試験 [プログラム研究室]


 こんにちは!
 ナビゲータのEVEです。

 本日から、Transaction、Rollback、Commitに関する試験をしていますが、その試験に付随して、 継承 について疑問がたくさん出てきました。
 問題を整理し、今後どうしたらいいのか検討していきたいと思います。

[Transaction、Rollback、Commitでの問題点]
New_Prototype_EVE.png
 EVEシステムで利用しているTransaction、Rollback、Commitは、EVEシステムのフレームワーク側で、フラグ制御し処理しようとしています。しかし、New Prototype EVEは、アプリケーション群側で行っているため、アプリケーションから、Transaction、Rollback、Commit処理を実行しています。
 New Prototype EVEでは、オーバーライドで作成したTransaction、Rollback、Commitは、普通に利用できます。ただ、フラグ制御していないNew Prototype EVEへ、確定予約フラグを設定すると、Rollbackしようとしても、Rollbackできません。ようは、Rollbackする前に、オーバーライド前の、EVEシステムフレーム側のCommit処理が動作するのです・・・???よく分かりません・・・。インポートしているのは、New Prototype EVEなのに・・・?New Prototype EVEでは、フラグ制御していない、Transaction、Rollback、Commitが定義されているだけなのに・・・?

[以上の結果を受けて]
 以上の結果を受けて、すべてのプロパティを カプセル化 することにしました(一部はあきらめました)。そこでまた問題が・・・?
オーバーライド しているメソッドでは、親クラスのprivateプロパティは見ることができるのですが、オーバーライドしていない子クラスのメソッドでは、privateプロパティは見ることができません。
 また、子クラスから親クラスのメソッドを呼び出して親クラスのプロパティへ設定した値を参照できますが、子クラスから、親クラスのプロパティへ、直接設定した値は、見ることができませんし、エラーにもなりません。
 仕方がないので、値を取得する項目については、子クラスから直接親クラスのプロパティを覗くのではなく、 setter getter を用意して見ることにしました。getterだけでは、無理そうです・・・?違いますか???

[どんな機能があるか分からない]
 以上のような経験を踏まえて、作らないといっていた、setterやgetterを用意することにしたのですが、作ってメリットがあることが分かりました。
 メソッドを作ったことにより、クラスにどんな機能があるのか明確になるのです。
 昨日、今日クラス継承するプログラムを作ってみて分かったことは、

1)当該クラスを利用しようとした場合、当該クラスの「親クラス+子クラス」の全ての機能を利用できる
2)メソッド、プロパティ名が同じものについては、オーバーライドされ、子クラスのものが優先されます。

 当然、親クラスから、子クラスまで全てのプログラムソースを見れば分かるのですが、面倒です。ただ、メソッドを定義しておけば、クラスとしての機能が一目で分かります。ただ、オーバーライドされているかどうかは、親と子両方見なければ分かりませんが・・・。

 という状況で、もうちょっと、継承について調べてみます。それが終わってから、New Prototype EVEの全面改修工事にかかります。

 では、また!!!

2023年03月19日

残りの製造 [プログラム研究室]


 こんにちは!
 ナビゲータのEVEです。

 本日、 継承 で作らなければならない部分を一通り作ってみました。簡単な試験では、Update、Deleteの処理は正常に動いているようです。本日の製造は、これぐらいにして、明日に、Transaction,、Rollback、Commit処理が、Insert、Update、Delete処理を正しく制御できるか確認したいと思います。

[New Prototype EVE]
 以下が本日製造したプログラムです。昨日のブログで説明していませんでしたが、クラスの継承には、 extends しなくてはいけません。同部分については、赤く表示してるのでご確認ください。extendsの最後のsを忘れがちですが、気を付けてください。私だけですかね?
 なお、一度修正したロジックの一部を削除したプログラムですので、解説は不要でいいですよね?


<?php
require_once "EVESystemDB,php"; //DB関連クラス
/*************************************************
*【クラス名 】DB関連クラス(New Prototype EVE対応)
*【製 造 者】EVE
*【製造年月日】2023年3月17日
*【更新年月日】2
*【リリース日】
*【バージョン】
*【 概 要 】
* データベースに関する基本的な機能を提供する
*************************************************/

class getInfDB extends getDB {
/*************************************************
*【メソッド名】レコード更新メソッド(New Prototype EVE)
*【 引 数 】$tbName :テーブル名
* u_Clum   :カラム名(配列)
*       u_Data   :データ(配列)
*       u_where   :更新条件("99"の場合は、"")
*【返 却 値】
* 正常時:true
* 異常時:false
*【製 造 者】EVE
*【製造年月日】2023年3月19日
*【更新年月日】
*【リリース日】
*【バージョン】
*【 概 要 】
* レコードを更新する
*************************************************/
//レコードを更新する

public function recUpdate(string $tbName, //テーブル名
array $u_Clum, //追加用項目
array $u_Data, //追加用項目
string $u_where){ //更新条件

//変数定義
static $i;
static $u_array = array();
static $strSql;
static $rtn;

//引数の判定を行う
//テーブル名を判定する

if ( $tbName == "" ) {
//異常の場合メッセージを設定し呼び出し元へ制御を移す
$this->processMessage = "テーブル名が設定されていません";

//呼び出し元へ制御を移す
return false;
}

//引数(配列)の判定を行う
if ( count( $u_Clum ) != count($u_Data) ) {
//引数の指定に誤りがある場合
$this->processMessage = "引数の指定に誤りがあります";

//呼び出し元へ制御を移す
return false;
}

//引数条件が設定されているかどうか判定する
if ( $u_where == "" ) {
//異常の場合メッセージを設定し呼び出し元へ制御を移す
$this->processMessage = "更新条件が設定されていません。";

//呼び出し元へ制御を移す
return false;
}

//SQL文を編集する
$u_array[] = "update ";
$u_array[] = $tbName;
$u_array[] = " set ";

//カラム配列終了まで以下の処理を実行する
for ( $i = 0; $i < count( $u_Clum ); $i++ ) {
//カラムを編集する
$u_array[] = $u_Clum[$i];
$u_array[] = " = ?";

//最終処理かどうか判定する
if ( count( $u_Clum ) == $i + 1 ) {
//最終処理の場合
//forを終了する

break;
} else {
//最終処理でない場合
$u_array[] = ",";
}
}
//検索条件の判定を行う
if ( $u_where != "99" ) {
//データの編集を開始する
$u_array[] = " where ";
$u_array[] = $u_where;
}
//SQL文を編集する
$strSql = implode( "",$u_array );

//プリシアードステートメント設定をする
$this->stmt = $this->getDbConnect->prepare($strSql);

//バインド変数終了まで以下の処理を実行する
for ( $i = 0; $i < count($u_Data); $i++ ) {
//バインド変数へデータを設定する
$this->stmt->bindParam($i+1,$u_Data[$i]);
}

//SQL文実行処理
try {

//レコード更新メソッドを実行する
$rtn = $this->stmt->execute();

} catch (PDOException $e) {
//更新処理が失敗した場合
//異常処理結果のメッセージを設定する

$this->processMessage = $e->getMessage();
//返却値を設定して呼び出し元へ制御を移す
return false;
}
//取得したレコード件数を設定する
if ( !($rtn = $this->recCount()) ) {
//返却値でエラーが発生していた場合
//処理結果を設定し呼び出し元へ制御を移す

return $this->processMessage;
}

//返却値を設定し呼び出し元へ制御を移す
return true;
}
/*************************************************
*【メソッド名】レコード削除メソッド(New Prototype EVE)
*【 引 数 】$tbName :テーブル名
*       d_where   :更新条件
*【返 却 値】
* 正常時:true
* 異常時:false
*【製 造 者】EVE
*【製造年月日】2023年3月19日
*【更新年月日】
*【リリース日】
*【バージョン】
*【 概 要 】
* [2023/03/06]
* レコードを更新する
*************************************************/
//レコードを削除する

public function recDelete(string $tbName, //テーブル名
string $d_where) { //更新条件

//変数定義
static $i;
static $strSql;
static $rtn;

//引数の判定を行う
//テーブル名を判定する

if ( $tbName == "" ) {
//異常の場合メッセージを設定し呼び出し元へ制御を移す
$this->processMessage = "テーブル名が設定されていません";

//呼び出し元へ制御を移す
return false;
}

//引数条件が設定されているかどうか判定する
if ( $d_where == "" ) {
//異常の場合メッセージを設定し呼び出し元へ制御を移す
$this->processMessage = "削除条件が設定されていません。";

//呼び出し元へ制御を移す
return false;
}

//SQL文を編集する
$d_array[] = "delete from ";
$d_array[] = $tbName;
$d_array[] = " where ";
$d_array[] = $d_where;

//SQL文を編集する
$strSql = implode( "",$d_array );

//プリシェアードステートメント設定する
$this->stmt = $this->getDbConnect->prepare($strSql);

//SQL文実行処理
try {
//レコード追加メソッドを実行する
$rtn = $this->stmt->execute();

} catch (PDOException $e) {
//削除処理が失敗した場合
//異常処理結果のメッセージを設定する

$this->processMessage = $e->getMessage();

//返却値を設定して呼び出し元へ制御を移す
return false;
}

//取得したレコード件数を設定する
if ( !($rtn = $this->recCount()) ) {
//返却値でエラーが発生していた場合
//処理結果を設定し呼び出し元へ制御を移す

return $this->processMessage;
}

//返却値を設定し呼び出し元へ制御を移す
return true;
}
/*************************************************
*【メソッド名】トランザクション開始メソッド(New Prototype EVE)
*【 引 数 】なし
*【返 却 値】なし
*【製 造 者】EVE
*【製造年月日】2023年3月19日
*【更新年月日】
*【リリース日】
*【バージョン】
*【 概 要 】
* トランザクションを開始する
*************************************************/
//トランザクションを開始する

public function setTran() {
//トランザクション情報を設定する
$this->getDbConnect->setAttribute(PDO::ATTR_ERRMODE,
PDO::ERRMODE_EXCEPTION);
//トランザクションを開始する
$this->getDbConnect->beginTransaction();
}
/*************************************************
*【メソッド名】コミットメソッド(New Prototype EVE)
*【 引 数 】なし
*【返 却 値】なし
*【製 造 者】EVE
*【製造年月日】2023年3月19日
*【更新年月日】
*【リリース日】
*【バージョン】
*【 概 要 】
* 処理を確定する
*************************************************/
//データベースを確定する

public function setCommit() {
//確定処理を実行する
$this->getDbConnect->commit();
}
/*************************************************
*【メソッド名】ロールバックメソッド(New Prototype EVE)
*【 引 数 】なし
*【返 却 値】なし
*【製 造 者】EVE
*【製造年月日】2023年3月19日
*【更新年月日】
*【リリース日】
*【バージョン】
*【 概 要 】
* トランザクションを発生した処理をロールバックする
*************************************************/
//データベースをロールバックする

public function setRollback() {
//処理をロールバックする
$this->getDbConnect->rollBack();
}
}
?>




[あとがき]
 これで、 Prototype EVEのデータベース関連関数の全てが修正できます 。明後日以降、一気に修正しようかなって考えています。ただ、ですね・・・。個人的に、便利なプログラムをたくさん作った関係で、今まで作ったところは全体の1/3になります。作るだけなら、数日でできると思いますが、デバックは、ちょっと、時間が必要だと思われます。まっ、全体を作りながらデバックするっていう方法もありますが、まだ、どんな変更点があるのか分からない場合、修正している途中で、 何がなんだかわからなくなる可能性 があります。どうしましょうか?
 データベース関連の修正ができれば、Prototype EVEのログインシステムが利用できるようになるので、そこから、 Prototype EVEとPHP8の不整合の確認ができる 予定です。
 という状況で、 今月末ぐらいで、今後の見通しがなんとなく立ちそうな予感が してきました。

 今までは、システムの基本的な部分で、誰が作っても同じようなロジックになる所なので、公開してきましたが、 以降は、取捨選択して、お見せできるものだけ、公開していく予定 です。

 では、また!
タグ: php 継承 extends

2023年03月18日

親クラスを継承することにより子クラスでは何を定義したらいいのか調べた見た [プログラム研究室]


 こんにちは!
 ナビゲータのEVEです。

 本日は、オブジェクト指向プログラミングの 継承 について学習し、プログラムを作ります。

[継承の目的]
 私は、あまり継承の便利さが分かっていませんでした。今回、既存の、Prototype EVEを利用しながら、EVEシステムを作ろうとした場合、そのメリットを大いに感じています。
 それは、フレームワークというプログラムにおいて、新旧のシステムにも 共通の部分 があります。その共通の部分を生かしつつ、新規に追加になる機能のみをプログラミングしていくという方法が取ることが可能なのです。
 今回は、新規のシステム、EVEシステムの構想の基に、New Prototype EVEを、EVEシステムを継承することにより作っていきます。

[New Prototype EVEの製造]
 Select、FetchはそのままEVEシステムのものを利用できるため、今回継承で、作るメソッドは、Insert、Update、Delete、Transaction、Rollback、Commitになります。早速、Insertのメソッドを作りました。以下がそのプログラムになります。


<?php
require_once "EVESystemDB.php"; //DB関連クラス
/*************************************************
*【クラス名 】DB関連クラス(New Prototype EVE)
*【製 造 者】EVE
*【製造年月日】2023年3月17日
*【更新年月日】
*【リリース日】
*【バージョン】
*【 概 要 】
* データベースに関する基本的な機能を提供する
*************************************************/

class getInfDB extends getDB {
//プライベート変数定義
//パブリック変数定義
/*************************************************
*【メソッド名】レコード追加メソッド(New Prototype EVE)
*【 引 数 】
* $tbName:テーブル名
* i_Clum :カラム名(配列)
* i_Data :データ(配列)
*【返 却 値】なし
* 正常時:true
* 異常時:false
*【製 造 者】EVE
*【製造年月日】2023年3月17日
*【更新年月日】
*【リリース日】
*【バージョン】
*【 概 要 】
* レコードを追加する
*************************************************
//レコードを追加する

public function recInsert(string $tbName //テーブル名
array $i_Clum, //追加用項目
array $i_Data) { //追加データ

//変数定義
static $i; //ループインデックス
static $i_array = array(); //追加用配列
static $strSql; //SQL文
static $rtn; //返却値

//引数の判定を行う
//テーブル名を判定する

if ( $tbName == "" ) {
//異常の場合メッセージを設定し呼び出し元へ制御を移す
$this->processMessage = "テーブル名が設定されていません";

//呼び出し元へ制御を移す
return false;
}

//配列個数を比較する
if ( count( $i_Clum ) != count($i_Data) ) {
//引数の指定に誤りがある場合
$this->processMessage = "引数の指定に誤りがあります";

//呼び出し元へ制御を移す
return false;
}

//SQL文を編集する
$i_array[] = "insert into ";
$i_array[] = $tbName;
$i_array[] = " (";

//カラム配列終了まで以下の処理を実行する
for ( $i = 0; $i < count( $i_Clum ); $i++ ) {
//カラムを編集する
$i_array[] = $i_Clum[$i];

//最終処理かどうか判定する
if ( count( $i_Clum ) == $i + 1 ) {
//最終処理の場合
$i_array[] = ")";

//forを終了する
break;
} else {
//最終処理でない場合
$i_array[] = ",";
}
}

//データの編集を開始する
$i_array[] = " value (";
//データ終了まで以下の処理を実行する
for ( $i = 0; $i < count( $i_Data ); $i++ ) {
//データを編集を開始する
$i_array[] = "?";

//最終処理かどうか判定する
if ( count( $i_Data ) == $i + 1 ) {
//最終処理の場合
$i_array[] = ");";

//forを終了する
break;
} else {
//最終処理でない場合
$i_array[] = ",";
}
}
//SQL文を編集する
$strSql = implode( "",$i_array );

//SQL文実行処理
try {
//プリシェアードステートメント設定する
$this->stmt = $this->getDbConnect->prepare($strSql);

//バインド変数終了まで以下の処理を実行する
for ( $i = 0; $i < count($i_Data); $i++ ) {
//バインド変数へデータを設定する
$this->stmt->bindParam($i+1,$i_Data[$i]);
}
} catch (PDOException $e) {
//ロールバックする
$this->setRollback();

//検索が失敗した場合
//異常処理結果のメッセージを設定する

$this->processMessage = $e->getMessage();
//返却値を設定して呼び出し元へ制御を移す
return false;
}

//SQL文実行処理
try {
//レコード追加メソッドを実行する
$rtn = $this->stmt->execute();

} catch (PDOException $e) {
//追加処理が失敗した場合
//異常処理結果のメッセージを設定する

$this->processMessage = $e->getMessage();
//返却値を設定して呼び出し元へ制御を移す
return false;
}
//取得したレコード件数を設定する
//返却値を設定し呼び出し元へ制御を移す

return true;
}
}
?>



 インターネットで、「 コンストラクタは、インスタンス作成時、親クラスのコンストラクタが起動する 」と書いてあったので、調査する意味で、EVEシステムのInsertメソッドの部分のみを切り出し、New Prototype EVEとして製造しました。
 EVEシステムとPrototype EVEシステムのInsertメソッドの違いは、以下の通りです。

・New Prototype EVEシステムへEVEシステムのDB関連クラスのファイルをインポートしました。
・プリシアードステートメントを設定するところに、try〜catchを入れました。
・トランザクション処理、ロールバック処理、コミット処理を削除しました。
・ドライバのインポートファイルを、New Prototype EVEシステムに変更しました(変更前はEVEシステム)
・インスタンス作成のクラス名をgetDB(EVEシステム)から、getInfDB(New Prototype EVEシステム)に変更しました。

 以上のような状態で、前回デバックで利用した2023年3月4日のInsertメソッドを実行したところ、正常に終了しました。

[今回の試験で分かったこと]
 以下の点が今回の試験で分かりました。





 まだ、たった1本作った後の感想なので、正しいかどうか分かりませんが、明日、予定しているプログラムを作れるところまで作ってみます。そして、過去に作成・利用した試験用ドライバで以上の印象が正しいか、確認します。

 では、また!

2023年03月17日

取得レコード件数カウントメソッドとEVEシステム製造の問題点の報告


 こんにちは!
 ナビゲータのEVEです。

 本日は、お約束した、レコード件数カウントの部分の解説です。そして、 露見した問題 というか、当初から想像はしていたのですが、その問題と対応について解説をします。

[Prototype EVE、EVEシステムインターフェース]
 以下が、レコード件数を取得するロジックになります。今回は、ステップ数が少ないため、パブリック変数定義、取得レコード件数カウントメソッド呼び出し元、そして、取得レコード件数カウントメソッドなど、件数をカウントに関連する部分のすべてを掲示しています。


---変数定義---------------------------------
//?パブリック変数定義
public $Count = 0; //SQL実行件数


---レコードカウント呼び出し元---------------------------------
//?取得したレコード件数を設定する
if ( !($rtn = $this->recCount()) ) {
//返却値でエラーが発生していた場合
//処理結果を設定し呼び出し元へ制御を移す

return false;
}

//異常処理結果のメッセージを設定する
return true;


---取得レコード件数カウントメソッド呼び出し元---------------------------------
/*************************************************
*【メソッド名】取得レコード件数カウントメソッド
*【 引 数 】なし
*【返 却 値】
* 正常時:true
* 異常時:false
*【製 造 者】EVE
*【製造年月日】2023年3月15日
*【更新年月日】
*【リリース日】
*【バージョン】0.1
*【 概 要 】
* 取得したSQLオブジェクトから件数を取得する
*************************************************/

//データベースを検索する
public function recCount() {

//件数をカウントする
try {
//?件数をカウントする
$this->Count = $this->stmt->rowCount();

} catch (PDOException $e) {
//?例外メッセージを格納する
$db->processMessage = $e->getMessage();
//返却値を設定し呼び出し元へ制御を移す
return false;
}

//?カウントした結果を返却値に設定し呼び出し元へ制御を移す
return true;
}



?は、今回の取得レコード件数カウントメソッドで取得した情報を格納します。Privateにしようかな?っとも思ったのですが、Privateにしたことにより、getをわざわざ作る意義を感じることができなかったため、Publicとしました。但し、後日、Privateになっていることもあるかもしれません。
?は、呼び出し元のプログラムです。Select、Insert、Update、Delete処理などの実行後にこのような形で定義しています。
?以降が、メイン処理になります。Select、Insert、Update、Delete処理の実行結果を用いそれぞれのレコード件数を取得し、取得したデータを?の[SQL実行件数]へ設定しています。
?は、エラーになった場合の処理になります。レコード件数をカウントするだけでエラーにあるとは考えにくいのですが、念のため設けました。
?そして、最後に、返却値にtrueを設定し、呼び出し元?へ制御を移しています。

[レコード件数メソッドを作り終えて]
 普通ならこのようなロジックをにプログラミングのたびに製造しなくてはいけないのですが、メソッドとして外だしすることにより、SQL実行結果のレコード件数を、?のプロパティの中を除くだけで、取得することができます。やはり、常時使うものは、このような形で 共通化 することにはメリットがあります。

[今まで作ったプログラムの問題点]
 今まで作ったオブジェクト指向のプログラムには、1つ問題がありました。それは、EVEシステムでは、トランザクションの開始、処理のコミットはほぼ自動で、フレームワーク側で行うというコンセプトで製造していました。しかし、前も一度触れているのですが、Prototype EVEでは、呼び出し元のアプリケーション群で、トランザクションの開始、コミットを制御しています。このため、今まで作ったプログラムをそのまま利用しようとした場合、修正は一切加えないとしている、 アプリケーション群に変更を加えなければなりません 。ただ、それは、 制約上許されません
New_Prototype_EVE.png
 じゃ、仕方がないので、トランザクションの開始をアプリケーション側で行うようにEVEシステムを作り直したら、それは、EVEシステムではなくなってしまいます。じゃ、どうしたらいいのか?そこで出てきたのが、EVEシステムを 継承 し、 New Prototype EVE を新たに製造するというアイディアです。昨日プログラマとして初体験の技術を使うと話していた技術は、この継承です。
 継承を使うことにより、生産性が上がるのと同時に、今まで通り次期システムの製造も同時平行的に行うことができます。ただ、New Prototype EVEは作らなければなりませんが・・・。

 この 初体験 ですが、心配なのが、親と子の関係がどのくらい有効で、どのようなふるまいをするのか、明確に想像できないということです。作りながら、親と子のクラスがどんなふるまいをするのか調べながらの製造になりそうです。

 明日以降は、Insert、Update、Delete、Transaction、Rollback、Commitに関する部分を オーバーロード して作り直す予定です。ロジックはほぼそのまま利用できる予定なので、継承における親と子のクラスがどのようにふるまうのかという調査に時間を掛ける予定です。

 では、また!

2023年03月16日

Prototype EVE検索用インターフェースプログラムの解説 [プログラム研究室]


 こんにちは!
 ナビゲータのEVEです。

 本日は、昨日製造した、プログラムの解説をします。

[Prototype EVE、EVEシステムインターフェース]
 昨日、件数カウントの部分をメソッドに出すかもしれないと話していましたが、出した方がすっきりしますし、Selectだけでなく、 DML (Data Manipulation Language)実行時にも件数が取得できるらしいので、DMLへも横並びでロジックを追加しました。DMLの部分は、実行結果の返却値でないとエラーになるかもしれないと思ったのですが、実行するとエラーにはなりませんでした。後日デバックして問題なければ、このロジックで行きたいと思います。


/*************************************************
*【メソッド名】DB検索関数(新)
*【 引 数 】
* p_sql :Sql文
* p_count:想定取得レコード件数
*【返 却 値】
* 正常時:検索結果
* 異常時:異常メッセージ
*【製 造 者】EVE
*【製造年月日】2005年2月20日
*【更新年月日】2023年3月16日
*【リリース日】
*【バージョン】
*【 概 要 】
*************************************************/

function gb_dbselect($p_sql,$p_check ) {

//?変数定義
$rtn = ""; //返却値
$ans = ""; //Fetch結果
$Bind = array(); //バインド変数配列
$db; //データベース検索格納オブジェクト
$count = 0; //件数カウント
$array = array(); //編集結果格納オブジェクト
$i = 0; //編集用インデックス

//?インスタンス作成
$db = new getDB(db,host,'utf8',user,pass);

//?Fetchメソッドを実行する
$ans = $db->selectFetch(1,$p_sql,$Bind);

//?返却値の判定を行う
if ( $ans == false ) {
//Fetchメソッドでエラーが発生した場合、
//返却値を設定し呼び出し元へ制御を移す

return db->$processMessage;
}

//?件数をカウントする
$count = $db->Count;

//?チェックフラグが"on"の場合、件数チェックを行う。
if (( $count == $p_check ) || ( $p_check == NULL )) {
} else {
//予想外の結果だった場合返却値を設定し呼び出し元へ制御を移す
return "Count Error";
}

//?件数カウントの結果0件の場合呼び出し元へ制御を戻す
if ( $count == 0 ) {
//取得結果が0件だった場合、件数カウントをセットし呼び出し元へ制御を移す
return $count;
} else {
//オブジェクトの編集
//?取得データ終了まで以下の処理を実行する
foreach ($ans as $row0) {
//?カラム終了まで以下の処理を実行する
foreach ($row0 as $row1 => $value) {
//?返却値オブジェクトへ毛策結果をセットする
$array[$i][$row1] = $value;
}
//?行数カウンタに1加算する
$i++;
}
}

//?検索結果を返却値に設定し呼び出し元へ制御を移す
return $array;
}



?この関数で利用するすべての変数を定義しています。Prototype EVEではここら辺の基準が明確ではありませんでしたが、EVEシステムでは、すべて定義することを規約としました。
?データベースへ接続するためのメソッドを作成しています。なお、ここで、db、user、passとリテラルで記述していますが、ここは、別ファイル内において(require_onceで取り込み) define でそれぞれの値を定義しているため、このような記述になっています。
?Fetchメソッドで実行しています。
?Fetchメソッドでエラーが発生していないか判定しています。発生している場合は、呼び出し先で設定したメッセージを取得し呼び出し元へ制御を移しています。
?昨日のプログラムでは、長々となりましたが、1行にまとめることができました。実行自体は、Fetchメソッドから呼び出されている、データベース検索メソッド内で取得しています。ここについては、明日解説をします。
?取得件数が予め分かっている場合、チェックフラグとして、件数をこのフラグに設定しています。そのチェックフラグと取得件数を比較し、もし違っていたら、エラーとしています。このロジックは、テストをすべてのロジックでできなかったため、 実行した時の結果で、バグを見つけることができるように作ったロジック です。
?取得した件数を判定しています。取得した件数が0件なら、返却値を編集するのは手間になるので、返却値を設定し呼び出し元へ制御を移しています。
?では、検索結果からのレコードを取得し、?でレコードからカラムを取得しています。?では、レコードを添え字にした、連想配列の二次元テーブルへ取得結果を設定し、返却値データを編集しています。
?では、格納レコードのポインタをずらすために、カウンタに1加算しています。
?編集結果を設定し、呼び出し元へ制御を移しています。

[あとがき]
 明日、件数カウントの部分の解説をします。簡単なプログラムなので、解説自体は、お手間をとらせないと思います。
 但し、今後開発するうえで、問題が1つ露見しました。同部分、実はまた、プログラマとして 初体験 の技術を使います。簡単ならいいのですが・・・。明日、件数カウントのメソッドの後にご説明します。

 では、また!!!
タグ: DML php define

2023年03月15日

Prototype EVE検索用インターフェースプログラム [プログラム研究室]


 こんにちは!
 ナビゲータのEVEです。

 本日は、昨日ご紹介した、Prototype EVEをインターフェース用プログラムに編集しました。編集した結果、機能自体がインターフェースだけになるため、短くなるのでは?っと想定していましたが、 ステップ数は逆に長くなりました ・・・???
 難しかったというか、時間がかかったところが、検索結果の 件数をカウント するところ・・・。使ったことがなかったということもあるのですが、サイトにより記述がまちまち・・・。検索、追加、更新、削除した結果の返却値を利用しているサイトもあれば、インスタンスを作成した後、プリシアードステートメントを設定した時のオブジェクトを使用しているものがあったりして、いろいろ試した結果、後者で件数をカウントすることができました。Fetchした結果は、プリシアードステートメントを設定後のオブジェクトを使用しないと検索結果はとれないようです。

[Prototype EVE、EVEシステムインターフェース]
 以下が、本日作成したプログラムです。


/*************************************************
*【メソッド名】DB検索関数(新)
*【 引 数 】
* p_sql :Sql文
* p_count:想定取得レコード件数
*【返 却 値】
* 正常時:検索結果
* 異常時:異常メッセージ
*【製 造 者】EVE
*【製造年月日】2005年2月20日
*【更新年月日】2023年3月15日
*【リリース日】
*【バージョン】
*【 概 要 】
*************************************************/

function gb_dbselect($p_sql,$p_check ) {

//?変数定義
$rtn = ""; //返却値
$ans = ""; //Fetch結果
$Bind = array(); //バインド変数配列
$db; //データベース検索格納オブジェクト
$count = 0; //件数カウント
$array = array(); //編集結果格納オブジェクト
$i = 0; //編集用インデックス

//?インスタンス作成
$db = new getDB(db,host,'utf8',user,pass);

//?Fetchメソッドを実行する
$ans = $db->selectFetch(1,$p_sql,$Bind);

//?返却値の判定を行う
if ( $ans == false ) {
//Fetchメソッドでエラーが発生した場合、
//返却値を設定し呼び出し元へ制御を移す

return db->$processMessage;
}

//?件数をカウントする
try {
//件数をカウントする
$count = $db->stmt->rowCount();

} catch (PDOException $e) {
//?例外メッセージを格納する
$db->processMessage = $e->getMessage();
//返却値を設定し呼び出し元へ制御を移す
return false;
}

//?チェックフラグが"on"の場合、件数チェックを行う。
if (( $count == $p_check ) || ( $p_check == NULL )) {
} else {
//予想外の結果だった場合返却値を設定し呼び出し元へ制御を移す
return "Count Error";
}

//?件数カウントの結果0件の場合呼び出し元へ制御を戻す
if ( $count == 0 ) {
//取得結果が0件だった場合、件数カウントをセットし呼び出し元へ制御を移す
return $count;
} else {
//オブジェクトの編集
//?取得データ終了まで以下の処理を実行する
foreach ($ans as $row0) {
//?カラム終了まで以下の処理を実行する
foreach ($row0 as $row1 => $value) {
//?返却値オブジェクトへ毛策結果をセットする
$array[$i][$row1] = $value;
}
//?行数カウンタに1加算する
$i++;
}
}

//?検索結果を返却値に設定し呼び出し元へ制御を移す
return $array;
}




 本日は、デバックがきちんとできていないので、これから精査、デバックしてから、明日正式なプログラムソースを用いて、解説をします。

[あとがき]
編集オブジェクト.png
 事前にこのプログラムのアウトプット?について説明すると、右の図のような配列を作成することを目的としています。この編集により、HTMLのテーブル等に出力するときに、行数とカラム名を指定すれば、 出力したい行の出力したいカラムを出力することができます 。性能は悪くなるのは分かっていますが、これにより、HTML画面の生産性が飛躍的に上がります。
 明日の解説の前にこのプログラムで何を実現したいのか、事前に解説をさせていただきました。
 このブログを書いているうちに、件数カウントの部分、メソッドに出したほうがいいかななんて気がしてきまして、ちょっと、外に出してみました。うまく動いたら、上記プログラムを修正し、ご紹介します。

 では、また!

2023年03月14日

Prototype EVEシステム改修検討・開発 [プログラム研究室]


 こんにちは!
 ナビゲータのEVEです。

 本日から、Prototype EVEシステムと、EVEシステムとのインターフェースの検討・開発に入ります。まず、開発に入る前に、どんな点に注意したらいいのか、検討をしてみましょう。
解説.png
 今回、Prototype EVEシステムとEVEシステムとのインターフェースの部分で気を付けなければいけない点はどんなところでしょうか?
 図1は、Prototype EVEでどんなところを改修するのか以前紹介した資料の一部を修正したものです。前回の図は、イメージ図でしたが、今回は データの流れを厳格に記述 しました。
 EVEシステムで、実際の処理を行い、Prototype EVEシステムでは、EVEシステムで実行した結果をアプリケーション群に正確に渡すという流れになります。
 その具体的な処理の流れを拡大したのが、図2になります。明日からPrototype EVEシステムの改修をしていきますが、返却値を事前に十分に調べた上で、 正しい返却値を、従来通りに渡すことができるかどうかと言ったところが、注力するところ になりそうです。

[Prototype EVEのプログラム]
 EVEシステムについては、どのように作るのか直近紹介していますが、Prototype EVEでは御紹介していなかったので、一部になりますが、見ていただきましょう!


/*************************************************
*【関 数 名】DB検索関数(新)
*【 引 数 】p_sql :sql(select)文
* p_check :チェックフラグ
*【返 却 値】配列  :正常終了時
*       配列(0) :異常時(メッセージ)
*【製 造 者】EVE
*【製造年月日】2005年 2月20日
*【更新年月日】
*【 備 考 】
*************************************************/

function gb_dbselect($p_sql,$p_check ) {

//返却値の初期化
$rtn = "";

//****************DB Connect******************
$rtn = gb_dbconnect();
if ( $rtn[1] != "") {
return $rtn[1];
}
//*******************************************

//?クエリー
$result = mysql_query( $p_sql );

//エラーが発生している場合返却値を取得する
//返却値の判定を行う

$ans = mysql_error();

//?返却値を判定する
if ( $ans != "" ) {
//?何かしらのエラーが設定されている場合
//返却値を設定し呼び出し元へ制御を移す

return $ans;
}

//?件数カウント
$count = mysql_num_rows( $result );

//エラーが発生している場合返却値を取得する
$ans = mysql_error();

//返却値の判定を行う
if ( $ans != "" ) {
//何かしらのエラーが設定されている場合
//返却値を設定し呼び出し元へ制御を移す

return $ans;
}

//?チェックフラグが"on"の場合、件数チェックを行う。
if (( $count == $p_check ) || ( $p_check == NULL )) {
} else {
//件数カウントでエラーが発生している場合
return "システム的なエラーがあります。";
}

//?件数カウントの結果0件の場合呼び出し元へ制御を移す
if ( $count == 0 ) {
//返却値が0件の場合、返却値を設定し呼び出し元へ制御を移す
return $count;
} else {
//?オブジェクトの編集
$idx = 0;
//取得データ分以下の処理を実行する
while ($row = mysql_fetch_row( $result )) {
//?取得したデータを編集する
//エラーを取得する

$ans = mysql_error();
//エラーが発生しているかどうか判定する
if ( $ans != "" ) {
//エラーが発生している場合
//返却値を設定し呼び出し元へ制御を移す

return $ans;
}
//返却値オブジェクトを編集する
//?カラム数分以下の処理を実行する

for ( $i = 0;$i < count( $row );$i++ ) {
//?返却値オブジェクトの編集
$array[$idx][mysql_field_name($result,$i)] = $row[$i];
}
//ループカウンタをカウントする
$idx++;
}
}

//?返却値を設定し呼び出し元へ制御を移す
return $array;
}



以上のソースは、他人が見てもいいようにコメントを追加し、かつコメントで間違っている部分については、修正させていただきました。ちょっと、ショックだったのが、 引数が間違っていました ・・・。ヘッダコメントの製造日が2005年なので、その当時、PHPが未熟だったことと、必死だったのだと思います?それと、すべて一人で作ろうと意気込んでいましたし、自分が分かれば良いと思っていたのかもしれません。
 DB検索関数(新)とあるから、多分旧があって、作り直しているんでしょうね?なんて、懐かしみながら見ていますが、今回カラム名が必要だと言っていた部分が、?の部分になります。解説は明日するとして、この1行のために、当初考えていたプログラムに加えて、Fetchメソッドを作ることになりました。

[あとがき]
 今日から改修に入るのですが、最初に検討した部分に気を付けたいと思います。っと書きながら、件数カウントの部分が気になりました。PDOだったら、どうなっているかな?って調べたら、従来通り、それ用のメソッドが用意されているようです。件数について気にしない人、多いですが、件数って処理において意外と重要なんですよ?それと、返却値は従来通りのものを返さなくてはいけないので、ほっとしています。また、メソッドを作らなければいけないかと思ってしまいました(笑)

 明日から以上の検討を元に、製造に入ります。

では、また!!!

タグ: php PDO

2023年03月13日

Fetchでカラム名とデータを配列で一度に取得する [プログラム研究室]


 こんにちは!
 ナビゲータのEVEです。

 お約束通りfetchAll(PDO::FETCH_XXXXX);のXXXXXの部分が変数で持てるかどうかやってみましたが、 無理 っぽかったです・・・。カッコの中身全部変数にしてみたりして、いろいろなパターンを試してみたのですが・・・・。無理っぽかったと言うのは、私がやって無理でも別の人がやったらできましたと言うことが多々あるためです。

 できるかもしれないけれど試していないということが1つあります。defineを使って、定数としてPDO::FETCH_XXXXXを定義すれば、できるような気がする・・・。ただ、そうやった場合、ロジック的にはすっきるするけれど、別ファイルにdefineで定義するなど、運用的に煩雑になるような気がするからやめました。PDO::FETCH_XXXXXの部分が、他でも使うなら、それもするんですけれど、ここだけでしょ?利用するの・・・・。っということで、Fetchメソッドについて解説をします。

[Fetchメソッドの解説]
 昨日アップロードしたソースを清書したものを、解説します。昨日のロジックと微妙に違います。


/*************************************************
*【メソッド名】Fetchメソッド
*【 引 数 】
* sub:種別
* 1;連想配列
* 2;一般配列
* 3;一般配列/連想配列
* 4;Fetchを実行する
* 5;オブジェクト
* 6;スカラー値
* 7;bindColumnメソッドのバイン変数
* 8;要求されたクラスの新規インスタンス
* strSql:SQL文
* Bind :バインド変数
*【返 却 値】
* 正常時:Fetchオブジェクト
* 異常時:False
*【製 造 者】EVE
*【製造年月日】2023年3月12日
*【更新年月日】
*【リリース日】
*【バージョン】0.1
*【 概 要 】
* レコードをFetchする
*************************************************/

//データベースを検索する
public function selectFetch(int $sub, //種別
string $strSql, //SQL文
array $Bind ) { //バインド変数

//?変数定義
static $i; //ループインデックス
static $rtn; //返却値

//?データベース検索メソッド
$rtn = $this->selectDb($strSql,$Bind);

//?返却値の判定
if ( $rtn == false ) {
//エラーの場合
$this->processMessage = "Serch Error";

//返却値を設定し呼び出し元へ制御を移す
return false;
}

//?SQL文実行処理
try {
//種別を判定する
if ( $sub == 1 ) {
//Fetchを実行する
//連想配列

$rtn = ($this->stmt->fetchAll(PDO::FETCH_ASSOC));
} else if ( $sub == 2 ) {
//Fetchを実行する
//一般配列

$rtn = ($this->stmt->fetchAll(PDO::FETCH_NUM));
} else if ( $sub == 3 ) {
//Fetchを実行する
//一般配列/連想配列

$rtn = ($this->stmt->fetchAll(PDO::FETCH_BOTH));
} else if ( $sub == 4 ) {
//Fetchを実行する
//連想配列

$rtn = ($this->stmt->fetchAll(PDO::FETCH_NAMED));
} else if ( $sub == 5 ) {
//Fetchを実行する
//オブジェクト

$rtn = ($this->stmt->fetchAll(PDO::FETCH_OBJ));
} else if ( $sub == 6 ) {
//Fetchを実行する
//スカラー値

$rtn = ($this->stmt->fetchAll(PDO::FETCH_COLUMN));
} else if ( $sub == 7 ) {
//Fetchを実行する
//bindColumnメソッドのバイン変数

$rtn = ($this->stmt->fetchAll(PDO::FETCH_BOUND));
} else if ( $sub == 8 ) {
//Fetchを実行する
//要求されたクラスの新規インスタンス

$rtn = ($this->stmt->fetchAll(PDO::FETCH_CLASS));
} else {
//?想定外の種別が設定されていた場合
$this->processMessage = "Assortment Error";

// 返却値を設定し呼び出し元へ制御を移す
return false;
}
} catch (PDOException $e) {
//?Fetchが失敗した場合
//異常処理結果のメッセージを設定する

$this->processMessage = $e->getMessage();

//返却値を設定し呼び出し元へ制御を移す
return false;
}
//?処理結果のメッセージを設定する
return $rtn;
}



?本メソッドのみで利用する変数をすべて定義しています。
?受け取った引数を2023年03月03日のブログでご紹介したデータベース検索メソッドへそのまま引き渡して、データベースを検索します。引数のチェック等データベースの基本的な所については、データベース検索メソッドで行うようにしています。
?データベース検索メソッドからの返却値を判定しています。データベース検索メソッドで異常が発生していた場合、falseを設定しているので、falseかどうか判定し、falseの場合、返却値にfalseを設定し呼び出し元へ制御を移します。なお、エラーメッセージは、データベース検索メソッドで既に設定済みのため、セットしていません。
?引数で受け取った、種別を判定しそれぞれの処理をしています。それぞれの定数について説明すると
・種別1:PDO:FETCH_ASSOC
 ┗取得形式:連想配列
・種別2:PDO:FETCH_NUM
 ┗取得形式:一般配列
・種別3:PDO:FETCH_BOTH
 ┗取得形式:一般配列/連想配列
・種別4:PDO:FETCH_NAMED
 ┗取得形式:連想配列
・種別5:PDO:FETCH_OBJ
 ┗取得形式:オブジェクト
・種別6:PDO:FETCH_COLUMN
 ┗取得形式:スカラー値
・種別7:PDO:FETCH_BOUND
 ┗取得形式:bindColumnメソッドでバインドされたPHP変数
・種別8:PDO:FETCH_CLASS
 ┗取得形式:指定されたクラスにフェッチ
 以上は、「独習PHP」に掲載されているものをそのまま転記しています。詳しい解説等については、「独習PHP」でご確認ください。

独習PHP 第4版 [ 山田 祥寛 ]

価格: 3,740円
(2023/3/13 18:27時点)
感想(1件)



?種別(1〜8)以外が指定されている場合、メッセージを設定し、呼び出し元へ制御を移します。
?tryでエラーが発生した場合、catchし、呼び出し元へ制御を移します。
?プログラムの仕様として、処理で異常が発生した場合、その場で処理を止める仕様としています。そのため、ここで返却する値は、正常処理で得た結果を返却することになります。
 今までの処理、Select、Insert、Update、Deleteでは、データベースに接続し、プリシアードステートメントを設定、バインドしたオブジェクトで、処理結果を受け取っていましたが、Fetchの場合は、正常に処理された返却値を使用します。そのため、他の処理とは違い、ここでは、trueではなく、PDO::Fetchメソッドから取得した 返却値を設定することが絶対条件 となります。

[あとがき]
 今月にはいり、プログラムを毎日のように公開していますが、コメントヘッダの引数の欄の記入が漏れていました。本日、すべてのヘッダに引数に関する記述を追加しました。

 最終的には、このヘッダに書かれている情報は、 構成管理システム で行う予定です。まだ仕様は決定していないのですが、構成管理システムの内容がここに反映されるようにしようかな???って考えています。できれば、プログラムを検索してその結果から、引数、返却値などが取得できればいいな〜って思いますが、難易度がかなり上がりますね・・・。 今後の開発の状況を見て判断したいと思います。

 では、また!!!

タグ: php FETCH

2023年03月12日

Fetchでレコードを取得する [プログラム研究室]


 こんにちは!
 ナビゲータのEVEです。

 本日、宣言通り Fetch によりレコードを取得しカラム名及びレコードを取得するプログラムを作りました。結論からいうと、Fetchを使うことにより、項目名もデータも同時に使用できます。

 今日も、できるかどうか分からなかったため、予想通り、 時間がかかりました 。問題は、ダンプした結果を見て、1次元なのか、2次元なのかといったところが、ピンとこないこと・・・。配列のダンプをとり、どのような配列か予想をたてて、ループさせてみて使えるのかどうか確認しています。
 Fetchもいろいろ種類があって、説明を読みましたが、ピンとこないので、以下のような感じで、結局全てを検証してみました。

[ソースを作成してみて]
 忙しい中、時間があまりないので、解説は明日にしますが、ソースはこんな感じになりました。


/*************************************************
*【メソッド名】Fetchメソッド
*【 引 数 】
* sub     :種別
* strSql    :SQL文
* Bind    :バインド変数
*【返 却 値】
* 正常時:Fetchオブジェクト
* 異常時:False
*【製 造 者】EVE
*【製造年月日】2023年3月12日
*【更新年月日】
*【リリース日】
*【バージョン】
*【 概 要 】
* レコードをFetchする
*************************************************/

//データベースを検索する
public function selectFetch(int $sub, //種別
string $strSql   //SQL文
array $Bind ) { //バインド変数

//変数定義
static $rtn; //返却値

//データベース検索メソッド
$rtn = $this->selectDb($strSql,$Bind);

//返却値の判定
if ( $rtn == false ) {
//異常の場合
$this->processMessage = "Serch Error";
return false;
}

//SQL文実行処理
try {

//種別の判定を行う
if ( $sub == 1 ) {
//Fetchを実行する
//連想配列

$rtn = ($this->stmt->fetchAll(PDO::FETCH_ASSOC));
} else if ( $sub == 1 ) {
//Fetchを実行する
//一般配列

$rtn = ($this->stmt->fetchAll(PDO::FETCH_NUM));
} else if ( $sub == 2 ) {
//Fetchを実行する
//一般配列/連想配列

$rtn = ($this->stmt->fetchAll(PDO::FETCH_BOTH));
} else if ( $sub == 3 ) {
//Fetchを実行する
//連想配列

$rtn = ($this->stmt->fetchAll(PDO::FETCH_NAMED));
} else if ( $sub == 4 ) {
//Fetchを実行する
//オブジェクト

$rtn = ($this->stmt->fetchAll(PDO::FETCH_OBJ));
} else if ( $sub == 5 ) {
//Fetchを実行する
//スカラー値

$rtn = ($this->stmt->fetchAll(PDO::FETCH_COLUMN));
} else if ( $sub == 6 ) {
//Fetchを実行する
//bindColumnメソッドでバインドされたPHP

$rtn = ($this->stmt->fetchAll(PDO::FETCH_BOUND));
} else if ( $sub == 7 ) {
//Fetchを実行する
//指定されたクラスにフェッチ

$rtn = ($this->stmt->fetchAll(PDO::FETCH_CLASS));
} else {
//予想外の種別が設定されている場合
//返却値を設定し呼び出し元へ制御を移す

$this->processMessage = "Assortment Error";
return false;
}
} catch (PDOException $e) {
//Fetchが失敗した場合
//異常処理結果のメッセージを設定する

$this->processMessage = $e->getMessage();

//返却値を設定し呼び出し元へ制御を移す
return false;
}
//異常処理結果のメッセージを設定する
return $rtn;
}



 まだきちんと検証が終わっていないのが、$sub(種別)の判定を1から7まで実施していますが、その中身、(PDO::FETCH_XXXXX)の部分・・・。この部分が 変数で持てるかどうか まだ、検証をしていません。今月にはいり、PDOに関するプログラムを複数作っていますが、その経験から、多分できないなと瞬時に思い、以上のプログラムになりました。ただ、正直いって不格好でスマートではありません。以上のプログラムは、きちんと動くことは分かったので。明日、試験的に試してみます。ダメそうな気はしているのですが・・・?

[あとがき]
 本プログラミング開始当初、うまくいっていないのは、仕方がないとして、そのうまくいかない理由をインターネットで調べていると、あるサイトでは、ループを用いず一気にデータを取得するために、便利なメソッドって紹介されているなど、プログラミングの気力をくじくような情報が多々ありました。
 この手の情報はループで処理できないと使い物になりません。それを考えると、メソッド提供側としては、ループで利用できることを想定して作っているはずです。っという自分の考えを信じ、作り続けてなんとか自分が考えるプログラムが作ることができました。

 明日、苦労した点や、本プログラムの機能などをご紹介します。それと、時間をかけるつもりはないのですが、(PDO::FETCH_XXXXX)の部分を変数に置き換えることができるかどうか試してみます。それについても、明日ご報告します。

 では、また!
タグ: php FETCH

2023年03月11日

PHPの配列がよく分からない??? [プログラム研究室]


 こんにちは!
 ナビゲータのEVEです。

 今日、早速古いプログラムに、EVEシステムへのインターフェースを入れようとしたのですが、 悪戦苦闘 しています。
 それは、 カラム名が取得できない から・・・。カラム名が取得できないのが理由で、なんでインターフェースの部分が作れないかは、明日以降にお話しするとして、PDOでExecuteした結果から、カラム名とデータを取り出そうとしているのですが、きれいな形で取得できません。EVEシステムはCoolなプログラミングを心がけているのですが、この段階で躓いています。

[Executeした結果を調査する]
 これが、PDOでExecuteして取得した結果です。


array(18) {
["Column1"]=> string(8) "aaaaaaaa" [0]=> string(8) "aaaaaaaa"
["Column2"]=> string(10) "bbbbbbbbbb" [1]=> string(10) "bbbbbbbbbb"
["Column3"]=> string(6) "cccc" [2]=> string(6) "cccc"
["Column4"]=> string(32) "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" [3]=> string(32) "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
["Column5"]=> string(13) "ddddddddddddd" [4]=> string(13) "ddddddddddddd"
["Column6"]=> NULL [5]=> NULL
["Column7"]=> string(10) "2022-09-28" [6]=> string(10) "2022-09-28"
["Column8"]=> string(8) "00:48:26" [7]=> string(8) "00:48:26"
["Column9"]=> "eeeeeeeeee" [8]=> "eeeeeeeeee" }



 上記の結果は、取得結果をダンプし、テキストエディタで見やすく編集した結果です。
 取得結果を見ると、取得した1レコードの情報を2つの配列に格納して情報を提供してくれているらしい・・・?
 1カラムにつき、もっている2つの配列は、連想配列と添え字という変わった形です。そのため、foreachで取得した結果を再度、for文で添え字でループさせると、一部のデータがundefinedで画面上に表示されます。
 項目名もあるし、データもあります。ということは、この結果から両方の情報が取れるかと思いきや、そううまくいかない・・・。keys_arrayで取得を試みたが、Coolな感じで取得できない。直近、うまくいきそうな方法としては、foreachで取得した情報を、入れ子で再度foreachで回して各配列の中身を取り出そうというやり方・・・(複数のレコードを取得することを想定しているため。但し、1レコードだけなら、foreachに入れ子を作る必要はありません。)。ただ、これも、カラム9個しかないのに、配列が18個あるから、入れ子のforeachで取捨選択して必要な情報を取り出さなくてはいけません。

[明日の予定]
 以上のやり方でもいいのですが、明日 fetchAll でデータを取得するメソッドをもう1本だけ作ろうと思います。返却値を見てからですが、使えそうなら、fetchAllでPrototype EVEとEVEシステムのインターフェースを作ります。ダメだったら、今日調べた結果を使うかも・・・?

 という状況で、予定が変わってしまいましたが、明日は、fetchAllのメソッドを製造します。

 では、また!!!
タグ: 配列 php

2023年03月10日

Prototype EVEの改修検討 [プログラム研究室]


 こんにちは!
 ナビゲータのEVEです。

 本日から、Prototype EVEシステムとEVEシステムとのインターフェースの製造に入ります。ただ、その前に、まずは、問題がないか検討をしてから製造に入ります。

[Prototype EVEの特長]
 開発したPHPプログラム、Prototype EVEの特長について考えてみたいと思います。

?オブジェクト指向プログラム ではない。
?インポートファイルをすべて、 requireで定義 している。
? 生産性を優先 している。
?関数への 引数をすべて文字列 として引き渡している(すべての関数ではない)。

 開発した当時PHP4で、以下の本を片手に開発をはじめました。
 この本にCD-ROMが添付されており、環境はOS、メール以外は、CDから構築しています。


 今そのバージョンを確認してみると、PHPはPHP4.2.3で、MySQLは、MySQL2.0.14でした。この両ソフト、PHPは、 セッション管理はできず 、MySQLは トランザクションは使用できず 、業務で利用するのはかなり無理のあるソフトだったと記憶しています。当然、オブジェクト指向で開発できるわけもなく、プログラムはベタ打ちでした(?)。ただ、生産性はよかったです。変数の型を考える必要はなく、作ったプログラムはすぐに動作したといった記憶があります。そのため、集中できれば、当時数千行のプログラムをコーディングをしていました。
 誤解を招かないようにセッション管理について、解説を付け加えさせていただくと、C言語で作られているPHPの一部を変更すれば、セッション管理は利用できたようです。そういった情報を見ました。ただ、当時の私のスキルでは対応できませんでした。しかし、トランザクションは、そういった記事を見たことがないので、無理だったんじゃないかな?って思っています。
 ?については、誤解から始まっています。 require_onceはリソースを消費する ・・・。そんなことを、当時のブログに書いたような気がします。同じ処理において同じ関数を格納したファイルを、複数回定義するのがいやで、1つの処理(呼び出し元プログラム、呼び出し関数を通して・・・)は、1度しかよばないというルールを自分に課していました。そのため、すべてのプログラムのインポートは、requireで統一しています。その設計思想は、当時システム運用環境はかなり脆弱で、そういう部分まで気を使いながら開発しなければならないという側面もありました。しかし、現在は、違います。今回は、クラスを作った後は、使い時に使いたい関数を定義し、利用しようかな?って考えています。特に関数側なのですが、便利な関数を作ったのに、呼び出し元で利用しているため、呼び出し先の関数では利用できないということはたびたびありました。それにより生産性を落とし、ロジックが冗長的になりました。今、昔のプログラムソースを見ながら、そう感じています。
 ?ですが、明日から、Prototype EVEとEVEシステムとのインターフェースの部分を作っていこうと考えていますが、生産性を重視したプログラムから紹介していきたいと思います。生産性を重視したため、 プログラムの作りがひどい と思う方もいるかと思いますが、使用してみると分かりますが、想像したほど処理が重くありません。前回のPrototype EVEは、多くの人に使ってもらっていないからなのかもしれませんが、作った当初そう感じたため、生産性を重視したシステムを開発しています。Xserver上のシステムを、New Prototype EVEと言ったらいいでしょうか?New Prototype EVEでは、その設計思想を当初はひきずっています。それについては、リリース後、徐々に書き換えていこうと考えています。
 ?は、直近のブログの中で触れましたが、Prototype EVEは、引数はすべて、文字列で渡すようにしています。文字列を受け取った関数では、PHPのマニュアルに書かれている引数の型に変換し利用するという作りになっています。
 2016年ぐらいから始めたことなので、すべての関数が対応できているわけではありません。この開発方針にした理由は、PHP側で用意している関数の引数の型がマニュアルに厳格に定義されているから、っというのが理由です。
 プログラマだと自分を定義したとき、以上のプログラムの作りはエラーにはならないのですが、違った型の引数をPHPで用意している関数に渡すのがいやになってしまったのです。
 この方式を導入することにより、今まで通りの生産性を維持できるとともに、自己満足もできるようになりました。なお、EVEシステムでは、 PHP8 を利用して、オブジェクト指向でプログラムを作ろうとしていますが、クラスまたはメソッドでは、引数の型を指定する必要があります。クラス、メソッドで定義している型と呼び出し元でセットしたデータの型に相違がある場合、エラーが出ます。そのため、今までのような苦労はしなくてよくなりました。

独習PHP 第4版 [ 山田 祥寛 ]

価格: 3,740円
(2023/3/10 18:53時点)
感想(1件)




[あとがき]
 以上のPrototype EVEの特徴を踏まえて、かつ、「独習PHP」をよく読み、EVEシステムとのインターフェースを作っていきます。
 もうひとつ考えなければいけないのが、EVEシステムで実際にどんなセキュリティ、どんなシステムにするのかということ・・・。それが、まだ検討が終わっていません。こういう状態で開発を進めると、作った後作り直しっていうことが多いのですよね・・・。今までの経験上・・・。

 とりあえず、オブジェクト指向言語の開発になれる意味でも作り始めます。以前書いたブログの中で、 分析麻痺症候群 の話をしましたが、そのような状態にはなりたくありませんので・・・。

 では、また!!!

2023年03月09日

レコード削除メソッド [プログラム研究室]


 こんにちは!
 ナビゲータのEVEです。

 本日の解説は、レコード削除メソッドの解説になります。
 これで、基本的なSQL関連のプログラムの製造は終わりです。

独習PHP 第4版 [ 山田 祥寛 ]

価格: 3,740円
(2023/3/9 18:41時点)
感想(1件)



 ここ数日、プログラムを製造し、ここで解説しながらプログラムを評価することにより、オブジェクト指向のPHPの製造方法と、PDOクラスの使い勝手を、理解することができました。これで、本格的に、EVEシステムの製造に入ることができます。ただ、気になるのが、「独習PHP」を読み終えていないこと・・・。PHP5から シャドーコピー ディープコピー が出てきていたりして・・・。「独習PHP」を斜め読みしていたら、ダブルコーテーションと、シングルコーテーションでは、文字リテラルの扱いが違うとか・・・。こちらは、間違えても致命的なエラーにはならないようですが、このような事例が他にもあるような気がします。がんがん作って、最後にプログラムソースを全て修正するというのは、困ったもんです。早めに、読み終えようと思います。
 「 独習PHP 」は、不満な点もありますが、ほぼ満足しています。私が知らない情報が多々載っており、プログラムミングという作業は最新の注意をもってやらなければいけないということを教えてくれます。PHPで製造しようという人がいましたら、お勧めの一冊です。
 では、解説に入りましょう!

[レコード削除メソッドの解説]
 以下が、レコード削除メソッドのプログラムソースです。


/*************************************************
*【メソッド名】レコード削除メソッド
*【 引 数 】$tbName :テーブル名
*       d_where   :更新条件
*【返 却 値】
* 正常時:true
* 異常時:False
*【製 造 者】EVE
*【製造年月日】2023年3月6日
*【更新年月日】
*【リリース日】
*【 概 要 】
* [2023/03/06]
* レコードを更新する
*?@トランザクションを開始したくない場合は、開始前に
*トランザクションプロパティに"off"を設定
*?Aコミットしたい場合は、本メソッド開始前に、
*コミットプロパティに"on"を設定
*?B検索条件を指定しない場合は、d_whereに、"99"を
*指定する
*************************************************/

//レコードを削除する
public function recDelete(string $tbName,
string $d_where) {

//?変数定義
static $i;
static $strSql;

//?引数の判定を行う
//テーブル名を判定する

if ( $tbName == "" ) {
//異常の場合メッセージを設定し呼び出し元へ制御を移す
$this->processMessage = "テーブル名が設定されていません";

//呼び出し元へ制御を移す
return false;
}

//引数条件が設定されているかどうか判定する
if ( $d_where == "" ) {
//異常の場合メッセージを設定し呼び出し元へ制御を移す
$this->processMessage = "削除条件が設定されていません。";

//呼び出し元へ制御を移す
return false;
}

//?SQL文を編集する
$d_array[] = "delete from ";
$d_array[] = $tbName;
$d_array[] = " where ";
$d_array[] = $d_where;

//SQL文を編集する
$strSql = implode( "",$d_array );

//プリシェアードステートメント設定する
$this->stmt = $this->getDbConnect->prepare($strSql);

//SQL文実行処理
try {
//?トランザクションを開始する
$this->setTran();

//?レコード追加メソッドを実行する
$this->stmt->execute();

} catch (PDOException $e) {
//?処理が失敗した場合、処理をロールバックする
$this->setRollback();

//?検索が失敗した場合
//異常処理結果のメッセージを設定する

$this->processMessage = $e->getMessage();

//?返却値を設定して呼び出し元へ制御を移す
return false;
}

//?プロセス確定メソッドを実行する
$this->setCommit();

//?返却値を設定し呼び出し元へ制御を移す
return true;
}



?から?までの項番をふって、改めて解説しようとしましたが、Select、Insert、Updateで既に解説しており、ここで改めて解説することはありません。私が当初考えていた完成のレベルに達したようです。
 ただ、1つ バグ がありました。


//トランザクションを開始する
public function setTran() {
//トランザクションプロパティがオンになっているかどうか判定する
if ( $this->setTran == "on" ) {

//トランザクションプロパティがオンになっている場合
$this->getDbConnect->setAttribute(PDO::ATTR_ERRMODE,
PDO::ERRMODE_EXCEPTION);
//トランザクションを開始する
$this->getDbConnect->beginTransaction();

//トランザクションプロパティを実行中に変更する
$this->setTran = = "exe";
}
}



 トランザクション開始メソッドなのですが、トランザクションプロパティに"exe"を設定し、現在のプロセス状況を管理しようとしていたのですが、イコール"=="が二つになっていました。判定するならいざ知らず、シャドーコピーするだけなら、イコール"="
だけでいいはずです。本日、削除処理を実行しようとしたら、削除できないので、いろいろ調べていたら気づきました。途中から処理を作ったので、気づくのが最終日になってしまいました。2023年03月07日のブログも変更しましたので、ご確認下さい。

[あとがき]
 今日、ブログを書きながら、明日何しようかなって考えてしまいました。セキュリティ関数の製造に入ろうかと思いましたが、それでは、ブログに書けませんし、「独習PHP」を読み終えたとき、修正するプログラムがたくさん出てきて、最初から見直ししなければいけないというのもいやです。それが、普通のメソッドならいざしらず、セキュリティ関数です。現段階で製造に入るのは時期尚早のようです。
 そこで、思いついたのが、Prototype EVEとEVEシステムとのインターフェースの部分・・・。当然、DB関連の部分になるのですが、ここなら、古いシステムと基本的なロジックになるので、問題にならないと思います。
 それと、Prototype EVEとEVEシステムのインタフェースで、できることとできないことを明確にしておいた方が、後になって慌てないでしょう?

 なんて、考えています。予定は、未定・・・。予告が変更されることもありますので、ご了承ください。

 では、また!

2023年03月08日

レコード更新メソッドの解説 [プログラム研究室]


 こんにちは!
 ナビゲータのEVEです。

 本日は、レコード更新メソッドの解説です。
 ここ数日間、コンストラクタ、コネクトメソッド、データベース検索メソッド、レコード追加メソッド、トランザクション開始メソッド、コミットメソッド、ロールバックメソッド、デストラクタと解説をしてきて、ブログを書きながら、修正点を見つけてきましたが、このレコード更新処理は、その検討結果をすべて取り込んだ処理になります。今日も何か気づくことがあるでしょうか?
 では、早速解説していきましょう!

[レコード更新メソッド解説]
 以下が、レコード更新メソッドになります。どんなふうに製造できたか見ていきましょう!


/*************************************************
*【メソッド名】レコード更新メソッド
*【 引 数 】$tbName :テーブル名
* u_Clum   :カラム名(配列)
*       u_Data   :データ(配列)
*       u_where   :更新条件("99"の場合は、"")
*【返 却 値】
* 正常時:true
* 異常時:False
* 正常時:true
* 異常時:False
*【製 造 者】EVE
*【製造年月日】2023年3月6日
*【更新年月日】2023年3月7日
*【リリース日】
*【 概 要 】
* [2023/03/06]
* レコードを更新する
*?@トランザクションを開始したくない場合は、開始前に
*トランザクションプロパティに"off"を設定
*?Aコミットしたい場合は、本メソッド開始前に、
*コミットプロパティに"on"を設定
*?B検索条件を指定しない場合は、u_whereに、"99"を
*指定する
* [2023/03/06]
* コミット処理を更新処理直前に移動
* [2023/03/07]
*?@トランザクション開始処理の冗長ロジックを削除
* ⇒冗長の部分は、トランザクション開始処理へ移動
*?Aバインド変数の設定をtry以前実施する
*************************************************/

//レコードを更新する
public function recUpdate(string $tbName, //テーブル名
array $u_Clum, //追加用項目
array $u_Data, //追加用項目
string $u_where) { //更新条件

//?変数定義
static $i; //ループインデックス
static $u_array = array(); //追加用配列
static $strSql; //SQL文

//?引数の判定を行う
//テーブル名を判定する
if ( $tbName == "" ) {
//異常の場合メッセージを設定し呼び出し元へ制御を移す
$this->processMessage = "テーブル名が設定されていません";

//呼び出し元へ制御を移す
return false;
}

//引数(配列)の判定を行う
if ( count( $u_Clum ) != count($u_Data) ) {
//引数の指定に誤りがある場合
$processMessage = "引数の指定に誤りがあります";

//呼び出し元へ制御を移す
return false;
}

//引数条件が設定されているかどうか判定する
if ( $u_where == "" ) {
//異常の場合メッセージを設定し呼び出し元へ制御を移す
$processMessage = "更新条件が設定されていません。";

//呼び出し元へ制御を移す
return false;
}

//?SQL文を編集する
$u_array[] = "update ";
$u_array[] = $tbName;
$u_array[] = " set ";
//カラム配列終了まで以下の処理を実行する
for ( $i = 0; $i < count( $u_Clum ); $i++ ) {
//カラムを編集する
$u_array[] = $u_Clum[$i];
$u_array[] = " = ?";

//最終処理かどうか判定する
if ( count( $u_Clum ) == $i + 1 ) {
//最終処理の場合
//forを終了する

break;
} else {
//最終処理でない場合
$u_array[] = ",";
}
}
//?検索条件の判定を行う
if ( $u_where != "99" ) {
//データの編集を開始する
$u_array[] = " where ";
$u_array[] = $u_where;
}
//SQL文を編集する
$strSql = implode( "",$u_array );

//?プリシアードステートメントを設定する
$this->stmt = $this->getDbConnect->prepare($strSql);

//?バインド変数終了まで以下の処理を実行する
for ( $i = 0; $i < count($u_Data); $i++ ) {
//バインド変数へデータを設定する
$this->stmt->bindParam($i+1,$u_Data[$i]);
}

//SQL文実行処理
try {
//?トランザクション開始する
$this->setTran();

//?レコード更新メソッドを実行する
$this->stmt->execute();

} catch (PDOException $e) {
//?ロールバックする
$this->setRollback();

//?検索が失敗した場合
//異常処理結果のメッセージを設定する

$this->processMessage = $e->getMessage();

//?返却値を設定して呼び出し元へ制御を移す
return false;
}

//?プロセス確定メソッドを実行する
$this->setCommit();

//?返却値を設定し呼び出し元へ制御を移す
return true;
}



 ?本メソッド内で使用している、変数を全て(?)定義しています。
 ?〜?の間で行われいる処理は、メソッド呼び出し時に取得した、引数の入力データチェックを行っています。「レコード追加メソッド(2023年3月6日)」の時は、全ての引数をチェックするかどうか悩んでいましたが、結局すべてのメソッドで 引数のチェックをする ことにしました。
 ?と?では、Update文を編集しています。SQL文を編集するという点では、「レコード追加メソッド」と同じなのですが、?では、引数が"99"か判定しています。Update文の場合、全ての処理でwhere文が必要ではないので、必要ではない場合、呼び出し元で、where文の代わりに、"99"を設定することになります。
 ?では、プリシアードステートメントの設定をしています。
 ?設定したプリシアードステートメントのバインド変数へデータを設定しています。この処理、「レコード追加メソッド」では、tryの中で実行していましたが、tryの外に出しました。特に理由はなく、なんとなくなのですが、どのようなエラーをtry〜catchで取得したいのかというと、「レコード追加メソッド」なら追加処理、「レコード更新メソッド」なら、更新処理にあります。目的にそった使い方をしたほうがいいと思い、このような仕様としています。なお、「レコード追加メソッド」でも横並びで修正しています。
 ?トランザクションを開始します。ここも昨日のトランザクション開始メソッドの仕様に併せて、フラグ等の判定はすべて削除し、実行のみとしています(2023年3月6日 プログラムソース?参照)。
 ?レコード更新メソッドを実行しています。
 ???はcatchは、「レコード追加メソッド(2023年3月6日)」と変更はありません。
 ??は、tryで正常に実行された後に実行される処理です。なお、この処理も、「レコード追加メソッド(2023年3月6日)」と変更はありません。

[あとがき]
 このプロジェクトの決め事として、プログラムソースを修正した場合、ヘッダに更新日と、更新内容を記述することにしています。ただ、プログラムを解説、じっくり見て、修正してみると、プログラムソースよりヘッダの方が長くなってしまいそうな気がしてきました。そのため、ヘッダにリリース日という項目を追加し、リリースした段階で更新履歴は削除することにしました。そして、リリース以降は、修正した場合は、ソース自体に、日付と修正内容を残すことにしました。
 やっぱり、修正した所へ 直接コメントを残した方が後で確認しやすい と思います。ただ、以前加わったプロジェクトでは、修正箇所が多すぎて、プログラムソース、コメントを 読むのが大変 だったということがありました。やはりリリース前によく考え製造しリリースしなくてはいけないとその時に感じた出来事でした。

 私も含めて、プログラムはよく考えて作りましょう!

 では、また!
タグ: php Update

2023年03月07日

トランザクション開始メソッド、プロセス確定メソッド、ロールバックメソッド [プロラム研究室]


 こんにちは!
 ナビゲータのEVEです。

 本日は、レコード追加処理の陰に隠れて、プログラムを紹介できなかった、トランザクション開始メソッド、コミットメソッド、ロールバックメソッドについて解説をしていきます。Prototype EVEの反省を受けて、新たなコンセプトを取り入れています。
 昨日のブログでも触れましたが、Prototype EVEでは、呼び出し元で、トランザクションの開始、コミット処理、ロールバックを行っていました。ただ、そのような処理だと、長いソースプログラムで適切にトランザクション関連処理が行われているかどうか 目検確認するのが大変 です。そのため、EVEシステムでは、クラス側で行おうとしています。

[レコード追加メソッドの解説]
 以下が、トランザクション開始メソッド、コミットメソッド、ロールバックメソッド、そして、デストラクタです。


//?クラスパブリック変数定義
public $getDbConnect; //データベース接続オブジェクト
public $stmt; //ステートメント
public $processMessage; //処理メッセージ
public $setTran = "on"; //トランザクション開始プロパティ
//(on:開始前,exe:実行中,実行不可:off)
public $setCommit = ""; //コミットプロパティ(on:確定予約)

/*************************************************
*【メソッド名】トランザクション開始メソッド
*【 引 数 】
*【返 却 値】なし
*【製 造 者】EVE
*【製造年月日】2023年3月3日
*【更新年月日】
*【 概 要 】
* [2023/03/03]
* トランザクションを開始する
* トランザクションを開始したくない場合は、開始前に
*トランザクション開始プロパティにoffを設定
*************************************************/

//トランザクションを開始する
public function setTran() {
?//トランザクション開始プロパティがオンになっているかどうか判定する
if ( $this->setTran == "on" ) {
//?トランザクション開始プロパティがオンになっている場合
$this->getDbConnect->setAttribute(PDO::ATTR_ERRMODE,
PDO::ERRMODE_EXCEPTION);
//トランザクションを開始する
$this->getDbConnect->beginTransaction();

//?トランザクション開始プロパティを実行中に変更する
$this->setTran = "exe";
}
}
/*************************************************
*【メソッド名】コミットメソッド
*【 引 数 】
*【返 却 値】なし
*【製 造 者】EVE
*【製造年月日】2023年3月3日
*【更新年月日】
*【 概 要 】
* [2023/03/03]
* 処理を確定する
*************************************************/

//データベースを確定する
public function setCommit() {
//?コミットプロパティを判定する
if (( $this->setran == "exe" ) &&
( $this->setCommit == "on" )) {
//?確定フラグが設定されている場合
$this->getDbConnect->commit();

//?確定処理後確定処理前の状態に戻す
//トランザクション開始プロパティ(on:開始前,exe実行中)
$this->setTran = "on";

//コミットプロパティ(on:確定予約、"":未実施)
$this->setCommit = "";
}
}
/*************************************************
*【メソッド名】ロールバックメソッド
*【 引 数 】
*【返 却 値】なし
*【製 造 者】EVE
*【製造年月日】2023年3月6日
*【更新年月日】
*【 概 要 】
* [2023/03/06]
*トランザクションを発生した処理をロールバックする
*************************************************/

//データベースを確定する
public function setRollback() {
//?コミットプロパティを判定する
if ( $this->setTran == "exe" ) {
//?確定フラグが設定されている場合
$this->getDbConnect->rollBack();

//?処理をトランザクション開始前の状態に戻す
//トランザクション開始プロパティ(on:開始前,exe実行中)

$this->setTran = "on";
//コミットプロパティ(on:確定予約)
$this->setCommit = "";
}
}
/*************************************************
*【メソッド名】デストラクタ
*【 引 数 】なし
*【返 却 値】なし
*【製 造 者】EVE
*【製造年月日】2023年3月2日
*【更新年月日】
*【 概 要 】
* オブジェクトが消滅する場合の処理を定義する
*************************************************/

//データベースを検索する
public function __destruct() {
//?処理が実行されている場合
if ( $this->setTran == "exe" ) {
//処理を確定する
//確定フラグが設定されている場合

$this->getDbConnect->commit();
}

//?データベースをクローズする
$this->getDbConnect = null;
}




独習PHP 第4版 [ 山田 祥寛 ]

価格: 3,740円
(2023/3/7 19:38時点)
感想(1件)



?には、DB関連クラス(getDB)のプロパティを記載しています。ここがこのクラスをコントロールする心臓部になります。なお、「独習PHP」に確か、 クラスと分かるようにしたほうがいい とか、書いてあったような気がします。プログラム製造しているうちに、クラスなんだか、メソッドなのか、プロパティなのか分からなくなるような気がします。忠告には従った方がいいかもしれません。後日、「独習PHP」の助言に従って修正する予定です。
?からは、トランザクション開始メソッドです。まず最初に、トランザクション開始プロパティを判定しています。DB関連クラス(getDB)のプロパティのトランザクション開始プロパティを見ていただければ分かりますが、デフォルトは"on"になっています。それは、Insert、Update、DeleteなどのDML(Data Manipulation Language)実行時には必ず、各処理の頭で実行するためデフォルトを"on"(開始)の状態にしています。但し、もしトランザクション処理を実行したくない場合は、"off"を設定することにより実行させない予定です。ただ、今までに、トランザクションを開始させないで、DMLを実行したことはなかったと思います。

 トランザクションを開始させないで、DMLを実行したことがないと書いていて思い出しましたが、2004年の開発当初は、 トランザクションっていう機能が、MySQLにはありませんでした 。トランザクション機能が追加されたのは、PHP4になってからだったよな・・・。その時、MySQLのバージョンいくつだっけな???機能追加するの大変だった記憶が思い出されます。
?では、トランザクションを開始しています。
?では、トランザクション開始プロパティを"exe"(実行中)にしています。このフラグにより、各メソッドはトランザクションの状態を判断します。
?からは、コミットメソッドに入ります。?では、トランザクション開始プロパティとコミットプロパティを判定しています。トランザクション開始プロパティは、"exe"(実行中)、コミットプロパティは"on"(確定予約)という状態になっているかどうか判定しています。"exe"(実行中)はトランザクション開始の時設定しており、それ以外では、設定していません。

 ここで書いていて気づきましたが、トランザクション開始プロパティの属性はpublicである必要はないですね・・・。使用目的から考えると、 private の方がいいような???このブログアップロード後修正します。
?では、確定処理を実行しています。
?では、トランザクション開始前の初期状態に、トランザクション開始プロパティ及びコミットプロパティを戻しています。確定が処理の最後ですから、初期状態に戻すでいいと思います。これ以降また、作成したプロパティを使用するかもしれませんし・・・?
?からは、ロールバックメソッドとなります。ここでもコミットメソッド同様に、トランザクション開始プロパティを判定しています。
?で、処理をロールバックしています。
?では、コミットメソッドと同様に、トランザクション開始プロパティとコミットプロパティを初期化しています。
?からは、 デストラクタ になります。Javaにはない機能なのですが、PHPでは、インスタンスが消滅するときに、起動するメソッドになります。ここでは、トランザクション開始プロパティを判定し、"exe"実行中かどうか判定しています。プログラマとしてはありえないことなのですが、コミットまたはロールバックすることなくプログラムが終了した場合の、リスクヘッジです。
?では、データベースをクローズしています。

[あとがき]
 どうでしょうか?作ってみてプログラム開発当初に想像していたより、よくできたなって思っているのですが気のせいでしょうか?
 これで、プログラム開発が楽になるような気がしています。

 では、また!!!

2023年03月06日

レコード追加メソッドの解説 [プログラム研究室]


 こんにちは!
 ナビゲータのEVEです。

 本日は、レコード追加メソッドの解説をしていきます。

[レコード追加メソッドの解説]
 ここ数日、ブログに掲載していた、メソッドです。昨日お話ししたとおり、処理で異常が発生した場合の rollback処理 を追加しました。加えて、その話とは別に、 コミット処理 の一部の仕様を変更しましたので、解説でご確認ください。


/*************************************************
*【メソッド名】レコード追加メソッド
*【 引 数 】tbName :テーブル名
* i_Clum   :カラム名(配列)
*       i_Data   :データ(配列)
*【返 却 値】なし
*【製 造 者】EVE
*【製造年月日】2023年3月3日
*【更新年月日】2023年3月6日
*【 概 要 】
* [2023/03/03]
* レコードを追加する
*<注意>
*?@トランザクションを開始したくない場合は、開始前に
*トランザクション開始プロパティにoffを設定
*?Aコミットしたい場合は、本メソッド開始前に、
*処理確定プロパティにonを設定
*************************************************/

//レコードを追加する
public function recInsert(string $tbName, //テーブル名
array $i_Clum, //追加用項目
array $i_Data) { //追加データ

//?変数定義
static $i; //ループインデックス
static $i_array = array(); //追加用配列
static $strSql; //SQL文

//?引数の判定を行う
if ( count( $i_Clum ) != count($i_Data) ) {
//引数の指定に誤りがある場合
$this->processMessage = "引数の指定に誤りがあります";

//呼び出し元へ制御を移す
return false;
}

//?トランザクションを開始フラグを判定する
if ( $this->setTran == "on" ) {
//トランザクション開始する
$this->setTran();

//トランザクション開始プロパティを実行中にステータスを変更する
$this->setTran = "exe";
}

//?SQL文を編集する
$i_array[] = "insert into ";
$i_array[] = $tbName;
$i_array[] = " (";

//カラム配列終了まで以下の処理を実行する
for ( $i = 0; $i < count( $i_Clum ); $i++ ) {
//カラムを編集する
$i_array[] = $i_Clum[$i];

//最終処理かどうか判定する
if ( count( $i_Clum ) == $i + 1 ) {
//最終処理の場合
$i_array[] = ")";

//forを終了する
break;
} else {
//最終処理でない場合
$i_array[] = ",";
}
}

//データの編集を開始する
$i_array[] = " value (";
//データ終了まで以下の処理を実行する
for ( $i = 0; $i < count( $i_Data ); $i++ ) {
//データを編集を開始する
$i_array[] = "?";

//最終処理かどうか判定する
if ( count( $i_Data ) == $i + 1 ) {
/ /最終処理の場合
$i_array[] = ");";

//forを終了する
break;
} else {
//最終処理でない場合
$i_array[] = ",";
}
}
//SQL文を編集する
$strSql = implode( "",$i_array );

//?プリシェアードステートメント設定する
$this->stmt = $this->getDbConnect->prepare($strSql);

//SQL文実行処理
try {
//?バインド変数終了まで以下の処理を実行する
for ( $i = 0; $i < count($i_Data); $i++ ) {
//データをSQL文へ設定する
$this->stmt->bindParam($i+1,$i_Data[$i]);
}
//?レコード追加メソッドを実行する
$this->stmt->execute();

} catch (PDOException $e) {
//?処理をロールバックする

$this->setRollback();

//検索が失敗した場合
//?異常処理結果のメッセージを設定する
$this->processMessage = $e->getMessage();

//返却値を設定して呼び出し元へ制御を移す

return false;
}

//?コミットするかどうか判定する
$this->setCommit();
//返却値を設定し呼び出し元へ制御を移す
return true;
}



?当メソッドだけで使用するプロパティをすべて定義しています。なお、もし、プログラムの途中に変数が使われているのに、ここに定義していないのは、ただ、忘れているだけです。後で、こっそりとプログラムを修正するかもしれません(笑)。

?入力データチェックをしています。なお、ここでは、登録カラム名配列と、その追加データ配列の個数を比較し、違った場合、異常終了させています。今までの経験上、このような箇所で一番間違いやすいのは、カラムとデータとの不整合です。そのため、ここでは配列の個数の確認だけをしていますが、今から考えると、 引数をすべてチェックしてもいいかも しれません。今までシステム関数とか使用していますが、エラーメッセージは返すものがなかなかありません。それに合わせると必要最低限でいいということになるかもしれませんが・・・?

?トランザクションを開始しています。今、このロジックを解説してみると、この位置が適切だったかな?っとは思います。通常トランザクションを開始するのは、Insert、Update、Deleteなどの 処理の直前 です。見直したほうがいいかもしれません。まっ、本日は、悪い見本ということで、放置します。

?ここからSQL文を編集しています。配列の頭からSQL文のパーツを登録していって、その配列を最後で結合してSQL文を編集するというやり方です。このやり方、インターネットで時々見ますが、現在の現場では、ちょっと、違ったやり方をしていました。どのようになっていたかは、話すのを差し控えさせていただきますが、あまりいいやり方とはいえないと考えています。保守性が非常に悪いのです。多分セキュリティ重視で同方法を採用しているのだと考えていますが、このやり方でも十分セキュリティは確保できると思います。まっ、1人で製造しているので、これ以外の方法は考えられませんが・・・。

? プリシアードステートメント として、編集したSQL文を設定しています。先ほど話した、トランザクションの開始ですが、この直後ぐらいがいいかもしれませんね?

?プリシアードステートメントに設定したSQL文に、取得した変数、追加データを設定しています。SQL文の編集時にデータを紛らせるという方法もありますが、以下の観点からこの方法を採用しています。

1)セキュリティ
2)データの正確性

1)プリシアードステートメントって、SQLインジェクション対応用関数って言ってもよいと思います。その関数に、本来のやり方でデータセットすることにより、セキュリティを高めています。
2)多分、stringのデータは、stringとして、integerのデータは、integerとして正しく扱ってくれるかなって期待して使用してます。マニュアルには、そこまで書いてないので、予想が外れている可能性がありますが、セキュリティの副次的な機能として期待です。

?Insert文を実行しています。
?これ以降は異常処理になりますが、catch直後にロールバックしています。
?Exceptionで取得したシステムメッセージを、処理メッセージプロパティへ設定しています。
?try〜catchを抜けて、最終処理になります。ここでコミット処理を定義しています。昨日までのプログラムでは、ここで、トランザクション開始プロパティを判定していましたが、それは、プロセス確定メソッドの中で判定することにしました。

[あとがき]
 このプログラムの特長は、 トランザクションの開始、確定は、このクラスの中ですべて完結 しています。Prototype EVEは、すべて呼び出し元で実施していたのですが、長いプログラムでは、最後の確認作業に時間がかかります。どこでトランザクションを開始して、どこでコミットしてと、呼び出し元のプログラムの頭から最後まで見て正しく行われているのか最終的なチェックをしていました。それでは、プログラミングの効率が落ちるので、このやり方を採用しました。
 トランザクションは、暗黙のうちに開始してくれますが、確定処理は明示しなくてはいけないので、思った程の効果が上がるかどうか微妙ですが・・・?

 では、また!

2023年03月05日

PHPのtry〜catchの動作を検証する [プログラム研究室]


 こんにちは!
 ナビゲータのEVEです。

 catchって、直前のエラーを拾うんでしたっけ?それともtryの中の例外すべて拾うんでしたっけ?っていう疑問を持ったので、本日は、実際に動いているプログラムから検証してみました。

[検証方法]
 検証方法は、どこを通っているのかどうか分かるように、プログラムにechoを入れ、画面から確認するという方法です。プログラムに echo を入れるというのは、下記の紫の部分のロジックになります。


/*************************************************
*【メソッド名】レコード追加メソッド
*【 引 数 】dbName :データベース名
* i_Clum   :カラム名(配列)
*       i_Data   :データ(配列)
*【返 却 値】
* 正常時:true
* 異常時:False
*【製 造 者】EVE
*【製造年月日】2023年3月3日
*【更新年月日】
*【 概 要 】
* [2023/03/03]
* レコードを追加する
*<注意>
*?@トランザクションを開始したくない場合は、開始前に
*トランザクション開始プロパティにoffを設定
*?Aコミットしたい場合は、本メソッド開始前に、
*処理確定プロパティにonを設定
*************************************************/

//レコードを追加する
public function recInsert(string $dbName, //データベース名
array $i_Clum, //追加用項目
array $i_Data) { //追加データ

//?変数定義
static $i; //ループインデックス
static $i_array = array(); //追加用配列
static $strSql; //SQL文

//?引数の判定を行う
if ( count( $i_Clum ) != count($i_Data) ) {
//引数の指定に誤りがある場合
$this->processMessage = "引数の指定に誤りがあります";

//呼び出し元へ制御を移す
return false;
}

//?トランザクションを開始フラグを判定する
if ( $this->setTran == "on" ) {
//トランザクション開始する
$this->setTran();

//トランザクション開始プロパティを実行中にステータスを変更する
$this->setTran = "exe";
}

//?SQL文を編集する
$i_array[] = "insert into ";
$i_array[] = $dbName;
$i_array[] = " (";

//カラム配列終了まで以下の処理を実行する
for ( $i = 0; $i < count( $i_Clum ); $i++ ) {
//カラムを編集する
$i_array[] = $i_Clum[$i];

//最終処理かどうか判定する
if ( count( $i_Clum ) == $i + 1 ) {
//最終処理の場合
$i_array[] = ")";

//forを終了する
break;
} else {
//最終処理でない場合
$i_array[] = ",";
}
}

//データの編集を開始する
$i_array[] = " value (";
//データ終了まで以下の処理を実行する
for ( $i = 0; $i < count( $i_Data ); $i++ ) {
//データを編集を開始する
$i_array[] = "?";

//最終処理かどうか判定する
if ( count( $i_Data ) == $i + 1 ) {
/ /最終処理の場合
$i_array[] = ");";

//forを終了する
break;
} else {
//最終処理でない場合
$i_array[] = ",";
}
}
//SQL文を編集する
$strSql = implode( "",$i_array );

//?プリシェアードステートメント設定する
$this->stmt = $this->getDbConnect->prepare($strSql);

//SQL文実行処理
try {
echo "check01";
//?バインド変数終了まで以下の処理を実行する
for ( $i = 0; $i < count($i_Data); $i++ ) {
//データをSQL文へ設定する
$this->stmt->bindParam($i+1,$i_Data[$i]);
}
//?レコード追加メソッドを実行する
$this->stmt->execute();
echo "check02";

} catch (PDOException $e) {
echo "check03";

//検索が失敗した場合
//?異常処理結果のメッセージを設定する
$this->processMessage = $e->getMessage();

//返却値を設定して呼び出し元へ制御を移す
echo "check04";

return false;
}

//?コミットするかどうか判定する
if( $this->setCommit == "on" ) {
//プロセス確定メソッドを実行する
$this->setCommit();
}
echo "check05";
//返却値を設定し呼び出し元へ制御を移す
return true;
}




[正常系の検証]
 データを設定し、実行しますと、想定してたとおり、

check01
check02
check05

というルートを通ります。

[異常系の確認]
 異常系は、正常系の試験を終えた後、データベースに同データが残った状態で、 キーが重複する データを再登録することにより検証しました。その場合も予想通りの結果となります。

check01
check03
check04

[catchの前にロジックを入れてみる]
 ?の「コミットするかどうか判定する」のif文を?の次にロジックを持ってきて、処理を実行しました。その結果は、

check01
check03
check04

 となります。エラーの時の状況で分かりにくいので、?の「コミットするかどうか判定する」のif文を、echo "check02-1";と、echo "check02-2";ではさんで、以下の形で実行すると、以下のようになります。

check01
check03
check04




//レコード追加メソッドを実行する
$this->stmt->execute();
echo "check02-1";
//コミットするかどうか判定する
if( $this->setCommit == "on" ) {
//プロセス確定メソッドを実行する
$this->setCommit();
}
echo "check02-2";




[結論]
 検証の結果は、catchの直前でなくても、エラーは拾ってくれるということは分かりました。但し、エラーが発生した時、エラー以降に実行したい処理があっても、その処理は実行されずcatchへ飛んでしまいます。加えて、try、catchとも、同ロジック内にreturnなどがなければ、try、catchのロジックを抜け、次の処理にいきます。

 以上の検証で、これから、迷うことなく、try、catchを使用できそうです。
 そうそう、このブログをつけていて思い出しましたが、ロールバックが抜けていました。明日、上記プログラムを解説しますが、ロールバックをつけた上で、解説します。

 では、また!
タグ: php catch Try

2023年03月04日

レコード追加メソッド [プログラム研究室]


 こんちは!
 ナビゲータのEVEです。

 ちょっと、昨日まで製造していた部分に疑問が生じたため、ブログの更新に時間がかかってしまいました。

[データベース追加メソッド]
 以下がデータベースを追加するメソッドです。本日は、こんな感じで作りましたという事の報告です。明日、どうしてこういうロジックになったのか解説します。


/*************************************************
*【メソッド名】レコード追加メソッド
*【 引 数 】dbName :データベース名
*       i_Clum   :カラム名(配列)
*       i_Data   :データ(配列)
*【返 却 値】
* 正常時:true
* 異常時:False
*【製 造 者】EVE
*【製造年月日】2023年3月3日
*【更新年月日】
*【 概 要 】
* [2023/03/03]
* レコードを追加する
*<注意>
*?@トランザクションを開始したくない場合は、開始前に
*トランザクション開始プロパティにoffを設定
*?Aコミットしたい場合は、本メソッド開始前に、
*処理確定プロパティにonを設定
*************************************************/

//レコードを追加する
public function recInsert(string $dbName, //データベース名
array $i_Clum, //追加用項目
array $i_Data) { //追加データ

//変数定義
static $i; //ループインデックス
static $i_array = array(); //追加用配列
static $strSql; //SQL文

//引数の判定を行う
if ( count( $i_Clum ) != count($i_Data) ) {
//引数の指定に誤りがある場合
$processMessage = "引数の指定に誤りがあります";

//呼び出し元へ制御を移す
return false;
}

//トランザクションを開始フラグを判定する
if ( $this->setTran == "on" ) {
//トランザクション開始する
$this->setTran();

//トランザクション開始プロパティを実行中にステータスを変更する
$this->setTran = "exe";
}

//SQL文を編集する
$i_array[] = "insert into ";
$i_array[] = $dbName;
$i_array[] = " (";

//カラム配列終了まで以下の処理を実行する
for ( $i = 0; $i < count( $i_Clum ); $i++ ) {
//カラムを編集する
$i_array[] = $i_Clum[$i];

//最終処理かどうか判定する
if ( count( $i_Clum ) == $i + 1 ) {
//最終処理の場合
$i_array[] = ")";

//forを終了する
break;
} else {
//最終処理でない場合
$i_array[] = ",";
}
}

//データの編集を開始する
$i_array[] = " value (";
//データ終了まで以下の処理を実行する
for ( $i = 0; $i < count( $i_Data ); $i++ ) {
//データを編集を開始する
$i_array[] = "?";

//最終処理かどうか判定する
if ( count( $i_Data ) == $i + 1 ) {
/ /最終処理の場合
$i_array[] = ");";

//forを終了する
break;
} else {
//最終処理でない場合
$i_array[] = ",";
}
}
//SQL文を編集する
$strSql = implode( "",$i_array );

//プリシェアードステートメント設定する
$this->stmt = $this->getDbConnect->prepare($strSql);

//SQL文実行処理
try {
//バインド変数終了まで以下の処理を実行する
for ( $i = 0; $i < count($i_Data); $i++ ) {
//データをSQL文へ設定する
$this->stmt->bindParam($i+1,$i_Data[$i]);
}
//レコード追加メソッドを実行する
$this->stmt->execute();

} catch (PDOException $e) {
//検索が失敗した場合
//異常処理結果のメッセージを設定する
$this->processMessage = $e->getMessage();

//返却値を設定して呼び出し元へ制御を移す
return false;
}

//コミットするかどうか判定する
if( $this->setCommit == "on" ) {
//プロセス確定メソッドを実行する
$this->setCommit();
}

//返却値を設定し呼び出し元へ制御を移す
return true;
}




[今日悩んだこと・・・]
 try〜catchの部分・・・。昨日報告したメソッドですが、$this->stmt->execute()の後にtrueを設定していますよね? catchって、直前のエラーを拾うんでしたっけ ?それともtryの中の例外すべて拾うんでしたっけ?
 Javaの時の記憶ですが、直前のエラーを拾ったような???そのため、$this->stmt->execute()の後にロジックを続けた場合、外に出さなければならないような???ただ、catchのロジックに入った場合、catchの中で、returnしないと、外に出したそのロジックに入ってしまうような???
 なんて、考え始めたら、面倒くさくなってしまい、調べる前に、true及びfalseなどの返却値は、returnに設定し、呼び出し元へ制御を移すことにしました。


try {
//プリシェアードステートメント設定する
$this->stmt = $this->getDbConnect->prepare($strSql);

//バインド変数終了まで以下の処理を実行する
for ( $i = 0; $i < count($Bind); $i++ ) {
//変数をSQL文へ設定する
$this->stmt->bindParam($i+1,$Bind[$i]);
}

//検索を実行する
$this->stmt->execute();

//処理結果を設定する
$this->processResult = true;  ←これこの位置でいい???
try〜catchの外に出した方
が良いのでは???

} catch (PDOException $e) {
//検索が失敗した場合
//処理結果を設定する
$this->processResult = false;
//異常処理結果のメッセージを設定する
$this->processMessage = $e->getMessage();
}
}




[あとがき]
 プログラム修正後ですが、調べて見ましたが、私の考えたとおりのことを言っているサイトもありました。ただ、明確に私の疑問に対して回答を出しているサイトは今のところありません。明日まで、もう少しだけ調べて見ます。明日、レコード追加メソッドの解説をします。なお、今日のような事があるので、一部修正が入っている可能性がありますので、ご了承ください。

 では、また!!!
タグ: catch Try

2023年03月03日

検索するSQL文でバインド変数が利用できるようにする [プログラム研究室]


 こんにちは!
 ナビゲータのEVEです。

 だんだんと、プログラムを作る速度が早くなってきました。慣れてきたんですね?以前のレベルではないのですが、3週間もすれば、以前同様に開発できそうです。って 妄想 を抱いています(笑)。
 本日製造したのは、レコードを追加するプログラムなのですが、デバックが終わっていないので、昨日製造した、検索するSQL文に、 バインド変数 を設定するプログラムを解説していきます。

[SQL文に変数を設定する]
 以下が、2023年3月1日に製造した検索プログラムに、変数を定義、バインド変数を設定できるようにしたプログラムです。紫の部分が前回から追加したロジックです。


/*************************************************
*【メソッド名】データベース検索メソッド
*【 引 数 】strSql   :Sql文
*       Bind    :バインド変数
*【返 却 値】なし
*【製 造 者】EVE
*【製造年月日】2023年3月1日
*【更新年月日】2023年3月2日
*【 備 考 】
* 受け取った文字列でデータベースを検索する
*************************************************/

//データベースを検索する
public function selectDb(string $strSql, //SQL文
array $Bind ) { //バインド変数

//SQL文実行処理
try {
//プリシェアードステートメント設定する
$this->stmt = $this->getDbConnect->prepare($strSql);

//バインド変数終了まで以下の処理を実行する
for ( $i = 0; $i < count($Bind); $i++ ) {
//変数をSQL文へ設定する
$this->stmt->bindParam($i+1,$Bind[$i]);
}

//検索を実行する
$this->stmt->execute();

//処理結果を設定する
$this->processResult = true;
} catch (PDOException $e) {
//検索が失敗した場合
//処理結果を設定する
$this->processResult = false;
//異常処理結果のメッセージを設定する
$this->processMessage = $e->getMessage();
}
}



呼び出し元プログラムでは、以下のような感じでSQL文を記述します。


//SQL文を編集する
$sql = "select * from test_table where id = ? and name = ?";

//バインド変数を設定する
$bind[] = 1;
$bind[] = tarou;

//検索を実行する
$pdo->selectDb($sql,$bind)



バインド変数は、?の部分に先頭から順番に設定していくようです。配列に変数を入れる順番は、?の順番に併せて設定してください。

[実は大変でした]
 できたプログラムを見ると、修正が少ないので簡単なように見えますが、実は、大変でした。
 最初、以上のようなプログラムで実行したいと思い、プログラミングを始めたのですが、なかなか動きません。理由は、 プリシアードステートメント にバインド変数を設定する方法は複数あり、以上のようなプログラミングができない方法を選択していたからです。それは、 bindValueメソッド と、 bindParamメソッド ・・・・。「独習PHP」には、それしかやり方が、載っていなかったので・・・。「独習PHP」片手に、できない、できないと苦闘しながら、最終的には他のやり方を探しました。このような処理は、各プログラムに書くのではなく、クラスのメソッドとして実行するのが私の理想です。そして、インターネットで検索して以上の方法を見つけました。このプログラミングも数時間を要しました。

[あとがき]
 今日、PHPをプログラミングをしていて気づいた点は、メソッド内で、 static を利用し定義するのですが、 型は定義できない ようです。型を定義するとエラーになるので、多分できないのだと思います。よく考えたら、クラス変数にも型は定義していませんね・・・。クラス変数に型を定義できるのでしょうか?試してみたら、エラーにはなりませんでした。Javaなら当然定義するのですが、PHPはどうなのでしょうね???
 つい最近、株探を見ていたら、 ノーコード開発 の記事を見つけました。以前、ブログで、 SHIFT(3697) という会社を紹介し、プログラムを必要としないシステムが出てくるといった話をしましたが、 SHIFT(3697) だけでなく、現在いろいろな企業がしのぎを削っているようです。ただ、このPHPの型を定義すると言った所などは、それとは逆行しているような気がするのですが???あなたは、どう感じますか?

 では、また!!!

■プログラマのすすめ 〜プログラマの環境〜 [システム開発研究室]
https://fanblogs.jp/bahamuteve/archive/194/0

2023年03月02日

データベースへの検索機能について解説する〜データベース関連クラスの解説〜 [プログラム研究室]


 こんにちは!
 ナビゲータのEVEです。

 昨日は、データベース接続メソッド内?のデータベースをクローズまで説明しました。本日は、その続きで?のデータベース検索メソッドから説明しましょう。
 なお、このプログラムは、 オブジェクト指向プログラムを経験したことがない プログラマが、今までの経験や知識、そして本から得た情報から作成したものです。もしかしたら、問題点等あるかもしれません。 オブジェクト指向プログラムの製造に対して経験豊富な方で気付いた点がございましたら、教えていただければ助かります。
 では、説明をしていきましょう!

[プログラムの解説〜データベース検索メソッド〜]
 昨日使ったプログラムを使って解説をしていきます。


<?php
/*************************************************
*【クラス名 】DB関連クラス
*【製 造 者】EVE
*【製造年月日】2023年3月1日
*【更新年月日】
*【 概 要 】
* データベースに関する基本的な機能を提供する
*************************************************/

class getDB {
//?プライベート変数定義
private $setDb; //データベース名
private $setHost; //ホスト名
private $setChar; //文字コード
private $setUser; //ユーザ名
private $setPass; //パスワード
private $setPara; //接続条件を編集する

//?パブリック変数定義
public $getDbConnect; //データベース接続オブジェクト
public $stmt; //ステートメント
public $processResult; //処理結果
public $processMessage; //処理メッセージ

/*************************************************
*【メソッド名】コンストラクタ
*【 引 数 】
*      selectDb  :データベース名
*      selectHost :ホスト名
*      selectChar :文字コード
*      selectUser :ユーザー名
*      selectPass :パスワード
*【製 造 者】EVE
*【製造年月日】2023年3月1日
*【更新年月日】
*【機能概要 】
* データベースを利用する場合の初期設定を行う
*************************************************/

public function __construct(string $selectDb, //データベース名
string $selectHost, //ホスト名
string $selectChar, //文字コード
string $selectUser, //ユーザー名
string $selectPass) { //パスワード
//変数定義
static $rtn = "";

//?取得した変数を再定義する
$this->&setDb = $selectDb; //データベース名
$this->&setHost = $selectHost; //ホスト名
$this->&setChar = $selectChar; //文字コード
$this->&setUser = $selectUser; //ユーザー名
$this->&setPass = $selectPass; //パスワード

//?接続条件を編集する
$this->&setPara = "mysql:dbname=".$this->&setDb."; host=".$this->&setHost."; charset=".$this->&setChar.";";

//?データベースへ接続する
$rtn = $this->&connectDb();
}

/*************************************************
*【メソッド名】データベース接続メソッド
*【 引 数 】なし
*【返 却 値】正常時:データベース接続オブジェクト
*       異常時:false
*【製 造 者】EVE
*【製造年月日】2023年3月1日
*【更新年月日】
*【機能概要 】
* データベースへ接続する
*************************************************/

public function connectDb():PDO {
try {
//?データベースへ接続する
$this->&getDbConnect = new PDO($this->&setPara ,$this->&setUser,$this->&setPass);

//?データベース接続オブジェクト
return $this->&getDbConnect;
} catch (PDOException $e) {
//?実行結果を格納する
$this->&processResult = false;
//?例外メッセージを格納する
$this->&processMessage = $e->&getMessage();

//?呼び出し元へ制御を移す
return $this->&processResult;
} finally {
//?データベースをクローズする
$getDbConnect = null;
}

}

/*************************************************
*【メソッド名】データベース検索メソッド
*【 引 数 】strSql   :Sql文
*【返 却 値】なし
*【製 造 者】EVE
*【製造年月日】2023年3月1日
*【更新年月日】
*【機能概要 】
* 受け取った文字列でデータベースを検索する
*************************************************/

//データベースを検索する
public function selectDb(string $strSql) { //SQL文
//SQL文実行処理
try {
//?プリシェアードステートメント設定する
$this->&stmt = $this->&getDbConnect->&prepare($strSql);

//?検索を実行する
$this->&stmt->&execute();

//?処理結果を設定する
$this->&processResult = true; //返却値(正常)
} catch (PDOException $e) {
//検索が失敗した場合
//?処理結果を設定する
$this->&processResult = false; //返却値を設定する(異常)

//?異常処理結果のメッセージを設定する
$this->&processMessage = $e->&getMessage(); //返却値を設定する(メッセージ)
}
}

}
?>



?では、 プリシアードステートメント に引数として取得したSQL文を設定しています。なお、プリシアードステートメントと表現していますが、情報セキュリティで SQLインジェクション について勉強するのですが、そのときに使用するプリシアードステートメントに似ているため、この呼称を使用させていただいています。
?では、SQL文を実行しています。なお、この前にSQL文に変数を設定することができます。その方法については、明日解説します。現在非常に苦労しています・・・。 できることと、できないことが分からない ので・・・?
?では、処理結果ture(正常終了)を設定しています。昨日も話しましたが、EVEシステムでは、パブリックプロパティに処理結果を設定することにより処理の正常、異常を判断し制御することにしました。
?以降では、エラーが発生した場合の処理を定義しています。?では、?と同様に処理結果を設定しています。ここでは、エラーロジックなので、false(異常)を設定しています。
?では、異常メッセージをパブリックプロパティに設定しています。ここでfinally定義できるのですが、どんな処理を記述していいのか分からなかったので、割愛しています。

独習PHP 第4版 [ 山田 祥寛 ]

価格: 3,740円
(2023/3/2 18:19時点)
感想(1件)



[プログラムを作ってみて]
 今見るとそんなに難しいプログラムではないのですが、できることとできないことが分からないので、「独習PHP」から こんなことできるんじゃないか?と想像 し、コーディングしているのですが、 ことごとく外れています 。コンストラクタに、データベース接続関数を定義できなかったけれど、引数を指定すればできるなど、条件がいろいろあるようです・・・。現在個別に条件を調べて対応中です。

[Prototype EVEでの反省を受けて]
 現在、気を付けている点は、 クラス、メソッドに渡す引数の型に気を付けています 。Prototype EVEの時は、正直言ってあまり気にしていませんでした。理由は、PHP自体が厳格にそれを要求していなかったから・・・。ただ、PHPが用意している関数は、型を厳格に定義しています。それでもエラーにならなかったので、気にしなかったのですが、Prototype EVEを他人に使用してもらおうと考えてから考えが変わりました。ただ、癖って恐ろしいもので、夢中で作っているとおろそかになってしまいます。そのため、最終的に引数は、すべてString型で渡し、渡した先で、使用する型に変換するといったことをしていました。これにより、懸念している問題は、解決しました。これから、PHP8で製造していきますが、PHP8は引数を受け取る側で型を指定できるので、今後はこのようなことをしなくても大丈夫だと思います。

[コメントって大事]
 今まで、いろいろな職場を経験していますが、 ドキュメントとプログラムと整合性 がとれているプロジェクトがほとんどなかったという印象です。っていうか、違っているのが普通です。
 プロジェクトを運営するうえで、ドキュメントとプログラムに不整合が発生していた場合、ドキュメントを正としてプログラムを修正するのが本来正しい姿なのですが、それができません。運用していて、正常に動いているのに、ドキュメントが正として扱っているからという理由で、プログラムを修正するというのは非常に勇気がいります。

 そんな時に大事なのが、プログラムに記述されている コメント です。Prototype EVEでは仕様書自体がないということもありますが、1ステップ1ステップにすべてコメントを入れるようにしています。10年以上前に作ったプログラムが多々ありますが、現在、そのコメントを頼りに修正をしています。
 コメントを入れることにより、プログラム速度が遅くなるという話がありますが、納品するときに、コメント削除ツールを使って、コメントを削除して納品すれば、自分だけのコメントを入れることができます。それと、くだらないところで突っ込みも入りませんしね?一度試してください。

 だから、ドキュメントを正として動いているプロジェクトに入ったら、 優秀なプロジェクト だと思っていただいていいと思います。

[あとがき]
 こんな感じでプログラムを作っています。今後もいろいろ工夫してEVEシステムを製造していきます。

 では、また!!!

2023年03月01日

データベースへの接続機能について解説する〜データベース関連クラスの解説〜 [プログラム研究室]


 こんにちは!
 ナビゲータのEVEです。

独習PHP 第4版 [ 山田 祥寛 ]

価格: 3,740円
(2023/3/1 18:49時点)
感想(1件)



 本日は、昨日製造したクラスの解説をします。「独習PHP」を読んでから(*1)製造したのですが、???っという部分もあるので、そういう部分も紹介していきます。

[プログラム解説]
 以下が苦労して作ったプログラムです。では、プログラムの頭から順をおって説明しましょう。


<&?php
/*************************************************
*【クラス名 】DB関連クラス
*【製 造 者】EVE
*【製造年月日】2023年3月1日
*【更新年月日】
*【 概 要 】
* データベースに関する基本的な機能を提供する
*************************************************/

class getDB {
//?プライベート変数定義
private $setDb; //データベース名
private $setHost; //ホスト名
private $setChar; //文字コード
private $setUser; //ユーザ名
private $setPass; //パスワード
private $setPara; //接続条件を編集する

//?パブリック変数定義
public $getDbConnect; //データベース接続オブジェクト
public $stmt; //ステートメント
public $processResult; //処理結果
public $processMessage; //処理メッセージ

/*************************************************
*【メソッド名】コンストラクタ
*【 引 数 】
*      selectDb  :データベース名
*      selectHost :ホスト名
*      selectChar :文字コード
*      selectUser :ユーザー名
*      selectPass :パスワード
*【製 造 者】EVE
*【製造年月日】2023年3月1日
*【更新年月日】
*【機能概要 】
* データベースを利用する場合の初期設定を行う
*************************************************/

public function __construct(string $selectDb, //データベース名
string $selectHost, //ホスト名
string $selectChar, //文字コード
string $selectUser, //ユーザー名
string $selectPass) { //パスワード
//変数定義
static $rtn = "";

//?取得した変数を再定義する
$this->&setDb = $selectDb; //データベース名
$this->&setHost = $selectHost; //ホスト名
$this->&setChar = $selectChar; //文字コード
$this->&setUser = $selectUser; //ユーザー名
$this->&setPass = $selectPass; //パスワード

//?接続条件を編集する
$this->&setPara = "mysql:dbname=".$this->&setDb."; host=".$this->&setHost."; charset=".$this->&setChar.";";

//?データベースへ接続する
$rtn = $this->&connectDb();
}

/*************************************************
*【メソッド名】データべース接続メソッド
*【 引 数 】なし
*【返 却 値】正常時:データベース接続オブジェクト
*       異常時:false
*【製 造 者】EVE
*【製造年月日】2023年3月1日
*【更新年月日】
*【機能概要 】
* データベースへ接続する
*************************************************/

public function connectDb():PDO {
try {
//?データベースへ接続する
$this->&getDbConnect = new PDO($this->&setPara ,$this->&setUser,$this->&setPass);

//?データベース接続オブジェクト
return $this->&getDbConnect;
} catch (PDOException $e) {
//?実行結果を格納する
$this->&processResult = false;
//?例外メッセージを格納する
$this->&processMessage = $e->&getMessage();

//?呼び出し元へ制御を移す
return $this->&processResult;
} finally {
//?データベースをクローズする
$getDbConnect = null;
}

}

/*************************************************
*【メソッド名】データベース検索メソッド
*【 引 数 】strSql   :Sql文
*【返 却 値】なし
*【製 造 者】EVE
*【製造年月日】2023年3月1日
*【更新年月日】
*【機能概要 】
* 受け取った文字列でデータベースを検索する
*************************************************/

//データベースを検索する
public function selectDb(string $strSql) { //SQL文
//SQL文実行処理
try {
//?プリシェアードステートメント設定する
$this->&stmt = $this->&getDbConnect->&prepare($strSql);

//?検索を実行する
$this->&stmt->&execute();

//?処理結果を設定する
$this->&processResult = true; //返却値(正常)
} catch (PDOException $e) {
//検索が失敗した場合
//?処理結果を設定する
$this->&processResult = false; //返却値を設定する(異常)

//?異常処理結果のメッセージを設定する
$this->&processMessage = $e->&getMessage(); //返却値を設定する(メッセージ)
}
}

}
?>




 ?では、プライべート変数を定義しています。これは、データベースへ接続するための情報を保持しています。データベースへの接続情報は、初回のみ使用するだけで、変更しない情報なので、プライベートで変数を保持しようとしています。もし、呼び出し元プログラムから情報へアクセスしたい場合、 getter setter を使用して接続することになります。
 ?では、パブリック変数を定義しています。ここの変数は、呼び出し元プログラムから参照・使用したいものを定義します。
 このプログラムの特徴となりますが、このクラスの処理結果をprocessResult、processMessageへ格納し、このクラスのすべての処理を制御しようとしています。
 ?からは、コンストラクタの解説になります。?では、呼び出し元でインスタンス作成時に設定した引数を、プライベート変数として再定義しています。 カプセル化 っぽいデータの扱いにしたいという意図があります。
 ?では、?で取得した情報を基に、接続する条件を編集しています。
 ?では、データベースへ接続しています。ここで悩んだ点は、返却値を取得したのだけれど、何もできない点・・・。「独習PHP」では、 返却値は返してはいけません って書いてあったので、返却値を返していないのですが、なんか、間抜けです。なお、返却値を指定してもエラーになりません(笑)。
 ?からは、データベースへ接続するためのメソッドの説明になります。?では、データベースへ接続するためのインスタンスを作成しています。
 ?では、取得したデータベース接続オブジェクトを返却しています。ここで 返却値を指定しないとエラーになります
 ?では、パブリックプロパティへ、処理結果、異常、falseを設定しています。
 ?では、パブリックプロパティへ、メッセージ、異常メッセージを設定しています。
 ?プロパティに設定した処理結果を返却値をセットし、呼び出し元へ制御を移しています。ここでもやはり、 返却値の指定をしないと、エラーになります
 ?このオブジェクトが消滅するときの最後の処理を指定しています。ここでは、データベースをクローズしています。

[あとがき]
 解説が途中ですが、本日の解説はここまでとさせていただきます。明日、続きを解説したうえで、いつもどんなところを気にしながらプログラムを製造しているのか、お話しましょう!

 では、また!!!

*1)まだ、すべて読み終えていません。
×

この広告は30日以上新しい記事の更新がないブログに表示されております。

Mobilize your Site
スマートフォン版を閲覧 | PC版を閲覧
Share by: