Closed41

PHP,MySQL,docker

ImaelImael

PHPバッチ 毎日決まった処理、メルマガなど画面が存在しない大量のデータを扱う
 まずフローチャートから作る

ImaelImael

php 変数宣言
キャメルケース
$userName
$userId
スネークケース
$user_count
$user_id

ImaelImael

PHP 定数 すべて大文字
<?php
define("GOOGLE_URL", "https://www.google.co.jp");
echo GOOGLE_URL;

const CONSTANT_NAME = "Value";

定数は、定義後にその値を変更することはできません。
定数の名前は、通常、全て大文字で書かれます(これは必須ではありませんが、標準的な習慣です)。
定数はグローバルスコープを持っています。つまり、関数の内部や外部のどこからでもアクセスすることができます。
定数の前に$記号は付けません。

constキーワードとdefine()関数の主な違いは、constはコンパイル時に評価されるのに対し、define()は実行時に評価される点です。また、constはクラスの中でも使用することができますが、define()はクラスの中では使用できません。

ImaelImael

php オブジェクト型
クラスのことらしい
<?php
$date = new DateTime();
echo $date->format("Y-m-d");

ImaelImael

PHP文字列
""ダブルクォーテーション 変数を展開する、特殊文字を\nなど展開する
''シングルクォーテーション 変数を展開しない特殊文字を処理\nしない

ImaelImael

文字列の連結
<?php
$text1 = "この野郎";
$text2 = "馬鹿野郎";
echo $text1 . $text2;

ImaelImael

php配列
<?php
$colors = ["red", "blue", "yellow"];
// $colors = array("red", "blue", "yellow");
echo $colors[0];

連想配列
// $userScores = ["tanaka"=>90, "yamada"=>80, "suzuki"=>70,];
$userScores = array(
"tanaka" => 90,
"yamada" => 80,
"suzuki" => 70,
);
echo $userScores["yamada"];

多次元配列
$users = array(
array(
"login_id" => "tanaka1234",
"password" => "111111",
"name" => "tanaka",
"birthday" => "1990-01-01",
),
array(
"login_id" => "yamayama",
"password" => "222222",
"name" => "tanaka",
"birthday" => "1990-01-01",
),
array(
"login_id" => "tanaka1234",
"password" => "111111",
"name" => "tanaka",
"birthday" => "1990-01-01",
),
);

echo "{users[1]["name"]}さんのログインIDは{users[1]["login_id"]}です。";

ImaelImael

三項演算子 
<?php

$age = 19;
echo $age < 20 ? "未成年です" : "成年です";

ImaelImael

=== は値が一緒かと型もチェックする
$value1 = 1;
$value2 = "1";

if ($value1 == $value2) {
echo "同じです";
} else {
echo "違います";
}

if ($value1 === $value2) {
echo "同じです";
} else {
echo "違います";
}

ImaelImael

swich
$day = 3; // 仮に3という数値が設定されているとします。

switch ($day) {
case 1:
echo "Monday";
break;
case 2:
echo "Tuesday";
break;
case 3:
echo "Wednesday";
break;
case 4:
echo "Thursday";
break;
case 5:
echo "Friday";
break;
case 6:
echo "Saturday";
break;
case 7:
echo "Sunday";
break;
default:
echo "Invalid day"; // day変数が1から7の範囲外の場合に表示
}

// 出力: Wednesday

ImaelImael

for文
<?php
for ($i = 1; $i <= 10; $i++) {
echo $i . "\n";
}

for ($i = 1; $i <= 10; $i++) {
if ($i === 6) {
continue;
}
echo $i ."\n";
}

// breakループを抜ける
// continue処理を中断しつぎのループに進む

ImaelImael

foreach文
<?php

$array = ["a", "b", "c"];
foreach ($array as $value) {
// 処理
echo $value . "\n";
}

$assocArray = ["first" => "a", "second" => "b"];
foreach ($assocArray as $key => $value) {
// 処理
echo "{key}は{value}です\n";
}

ImaelImael

php
組み込み関数  PHPであらかじめ決められた関数
 echo 画面に文字を表示
strlen 文字列の長さを取得する関数
 array_search 指定した値が配列の中にあるか検索する
その他たくさん

function 関数名(型 引数1, 型 引数2): 戻り値の型 {
処理
}
テストの点数が80点以上のだったら合格、それ未満だったら不合格と返す関数
<?php
$userScoreA = 80;
$userScoreB = 79;

function judgeScore(int $score): string {
if ($score >= 80) {
result = "{score}点は合格です";
} else {
result = "{score}点は不合格です";
}
return $result;
}

echo judgeScore($userScoreA);
echo judgeScore($userScoreB);

ImaelImael

declare(strict_types=1);
厳密な型チェックモードに変更
余計なバグが減るので特別な理由がない限り書いておく

宣言の位置: declare(strict_types=1); は、ファイルの最初に配置する必要があります。この宣言は、宣言がされたファイルのスコープ内のみで有効となります。つまり、各ファイルごとにこのモードを有効または無効にすることができます。

効果: strict_typesを1に設定すると、関数やメソッドの引数、および返り値の型に対する型チェックが厳格になります。

動作例: 型ヒントがintで指定されている関数に対して、文字列型の数値(例:"123")を渡すと、厳密な型モードが有効な場合はエラーが発生します。
ImaelImael

$this はインスタンス化されたオブジェクト(インスタンス)を指し、インスタンスのプロパティやメソッドにアクセスする際に使用します。

self は、静的プロパティ、静的メソッド、定数にアクセスする際に使用し、インスタンス化しなくてもアクセスできます。

ImaelImael

phpスタティック変数
インスタンス化のほうじゃなくクラスのほうに属すので値を共有できる
DBコネクションをひとつだけにしたい?

ImaelImael

PHPエラー
Parse Error (構文エラー)
ファイルを解析する際に発生するエラー。
例:閉じカッコの不足、セミコロンの欠落など。

Fatal Error
    スクリプトの実行を停止させる非常に重大なエラー。
    例:存在しない関数の呼び出し、存在しないクラスのインスタンス化など。

Warning
    スクリプトの実行を停止させることなく、警告メッセージを出力するエラー。
    例:include関数でファイルが見つからない場合など。

Notice
    コードの不具合を示す軽微なエラー。スクリプトの実行は継続される。
    例:未定義の変数の使用、配列の未定義のインデックスのアクセスなど。

Deprecated Error
    使用が推奨されない関数や方法を使用したときに発生するエラー。
    例:将来のバージョンのPHPで非推奨または削除される関数の使用。

Strict Standards
    スクリプトがPHPのコーディング標準に準拠していない場合に発生するエラー。
    例:非静的メソッドを静的として呼び出す場合など。

Recoverable Fatal Error
    エラーハンドラを使用して捕捉および復旧が可能なFatal Error。

Type Error
    引数の型や返り値の型が正しくない場合に発生するエラー。PHP 7以降でのみ使用可能。
ImaelImael

windows Docker desktop
http://peloproject.com/docker-desktop-wsl-kernel-version-too-lowの解消手順について/

DockerDesktopをインストールして起動した際に下記のエラーが表示される場合があるのでそちらの対処方法になります。

WSL(Windows Subsystem for Linux)のバージョンが古いとのことなので更新します。

コマンドプロンプトを開き下記のコマンドを入力します。

wsl --update
インストール中: Linux 用 Windows サブシステム
Linux 用 Windows サブシステム はインストールされました。

ImaelImael

docker run -d -p 80:80 --name my-apache-php-app -v ${PWD}:/var/www/html php:7.2-apache

docker run -d ドッカーを起動するコマンド

-p 80:80 ポート番号のマッピング ブラウザでphpのファイルを見れるようにしてる

--name my-apache-php-app 作成するドッカーコンテナにmy-apache-php-appという名前をつける

-v ${PWD}:/var/www/html 作成してコマンドを実行したディレクトリをブラウザでみれるようにする

php:7.2-apache 使用するドッカーのイメージ

ImaelImael

docker exec -it web bash
ドッカーコンテナのウェブサーバーにログイン

exit
ログアウト

ログイン省略
docker exec -it web php batch/test.php

ImaelImael

docker-composeを使用してDockerコンテナを停止および起動するための基本的なコマンドは以下の通りです。

Dockerコンテナを停止する:

  1. サービスを停止してコンテナを削除:

    docker-compose down
    

    このコマンドは、docker-compose.ymlで定義されたサービスを停止し、関連するコンテナを削除します。ただし、ボリュームやネットワークは削除されません。

    ボリュームも削除したい場合は以下のように-vオプションを使用します:

    docker-compose down -v
    
  2. サービスを停止するのみ:
    サービスを停止し、コンテナをそのまま保持したい場合は以下のコマンドを使用します:

    docker-compose stop
    

Dockerコンテナを起動する:

  1. サービスを起動:

    docker-compose up
    

    -dオプションを追加すると、コンテナをバックグラウンドで実行することができます:

    docker-compose up -d
    
  2. サービスを起動し、関連するイメージを再構築:

    docker-compose up --build
    

これらのコマンドを実行するときは、コマンドを実行しているディレクトリにdocker-compose.ymlファイルが存在していることを確認してください。

ImaelImael

あなたが実行した wsl --install コマンドは、Windows Subsystem for Linux (WSL) に新しい Linux ディストリビューションをインストールするためのものです。しかし、あなたが提示したメッセージは、コマンドの使用方法を示すヘルプメッセージのようです。

このメッセージは、wsl --install コマンドが正しく実行されなかったことを示しています。これは、コマンドが正しく入力されなかったか、あるいはあなたのシステムが WSL のインストールをサポートしていない可能性があります。

WSL をインストールするには、以下の手順を試してみてください:

PowerShell を管理者として実行します。
次のコマンドを実行して、WSL を有効にします:dism.exe /online /enable-feature /featurename:Microsoft-Windows-Subsystem-Linux /all /norestart
次のコマンドを実行して、仮想マシンプラットフォームを有効にします(これは WSL 2 を使用するために必要です):dism.exe /online /enable-feature /featurename:VirtualMachinePlatform /all /norestart
PC を再起動します。
再起動後、次のコマンドを実行して、WSL のデフォルトバージョンを 2 に設定します:wsl --set-default-version 2
最後に、wsl --install コマンドを実行して、Linux ディストリビューションをインストールします。

ImaelImael

docker run -d -p 80:80 --name my-apache-php-app -v ${PWD}:/var/www/html php:7.2-apache

ImaelImael

2023年11月12日 Windows10のPCにdocker desktopをインストールしようとして

画像のようなエラーになった
いろいろ試したがWindows11にアップデートしたら成功した

ImaelImael

docker-compose.ymlを使った起動
docker-compose up -d --build
停止
docker-compose down

ImaelImael


MySQL
MySQL WorkbenchがVisual C++ 2019 Redistributable Packageを必要としている
Visual C++ 2019 Redistributableをダウンロードして解決

ImaelImael

getサーバから受け取る
POSTサーバーに登録する

POST通信をするにはフォームが必要
<form aciton="sample_post.php" method="post">
ユーザーID:<input type="text" name="user_id" />

パスワード:<input type="password" name="password" />

<input type="submit" value="送信"/>
</form>
actionはフォームのポストするURLを指定する
formを送信することをsubmitという

ImaelImael

SQLのWHERE 1 = 1について
You
sql = "SELECT COUNT(*) AS count FROM users WHERE 1 = 1 {whereSql}";
ここでWHERE 1 = 1 とする理由はなんでしょうか?
ChatGPT
ChatGPT
WHERE 1 = 1 という構文は、SQLクエリの書き方の一つで、主に動的なクエリを構築する際に便利です。このパターンは特に、検索条件が可変で、条件が追加されるかもしれない場合によく使われます。

WHERE 1 = 1 は常に真となる式です。この部分自体がクエリの結果に直接影響を与えることはありませんが、以下のような利点があります:

条件の追加が容易:既に WHERE 句が存在するため、追加の条件を AND キーワードで簡単に追加できます。クエリがプログラムによって動的に生成される場合、条件があるかないかをチェックせずに、追加の条件を簡単に連結できます。

可読性の向上:WHERE 1 = 1 を書くことで、SQLの構造が明確になり、後続の条件が WHERE 句の一部であることがはっきりします。

あなたのコードの例では、$whereSql に動的に追加される条件(社員番号、社員名カナ、性別)があるため、WHERE 1 = 1 の使用は意味があります。これにより、どの条件が指定されても、それらをシームレスに追加できます。

例えば、もし $whereSql が空の場合、クエリは WHERE 1 = 1 のみとなり、すべてのユーザを対象とします。一方で、条件が指定されている場合は、それらの条件が AND で適切に追加されます。

User
You
whereが常に真となり追加条件がANDで簡単に追加できるという理解でいいですか?
ChatGPT
ChatGPT
はい、その理解で正しいです。WHERE 1 = 1 は常に真となるため、これをクエリに含めることで、追加の条件を AND を使って容易に連結することができます。これは特に動的なSQLクエリを構築する際に有効です。条件がない場合でもクエリが正しく動作し、条件がある場合はそれらを簡単に追加することができます。

例えば、あなたのコードでは、以下のように動的に条件を追加しています:

if ($id !== '') { ... } で社員番号に基づく条件を追加
if ($nameKana !== '') { ... } で社員名カナに基づく条件を追加
if ($gender !== '') { ... } で性別に基づく条件を追加
これらの条件は $whereSql に追加され、最終的なSQLクエリでは WHERE 1 = 1 に続いて連結されます。これにより、どの条件が存在するかにかかわらず、SQLクエリがスムーズに機能します。

ImaelImael

HTMLのdisabled属性は、フォーム要素(通常は<input>、<button>、<select>、<textarea>など)に使用され、その要素を使用不可にします。disabled属性が設定されたフォーム要素は、ユーザーによる操作ができなくなります(入力や選択ができなくなる)し、その要素の値はフォーム送信時にサーバーに送られません。

disabled属性の特徴:

ユーザーインタラクションの禁止:disabled属性が設定された要素は、ユーザーがクリックしたり、値を変更したりすることができません。

視覚的な変化:多くのブラウザでは、disabled属性が設定された要素は視覚的にも無効化されていることが分かるように表示されます(通常は薄く表示される)。

フォーム送信の除外:disabled属性が設定された要素の値は、フォームがサーバーに送信される際に含まれません。

CSSとJavaScriptの影響:CSSやJavaScriptを使用してスタイルや動作をカスタマイズすることができますが、disabled属性自体を動的に追加または削除することも可能です。

例:

html

<input type="text" name="username" disabled>

この例では、ユーザー名を入力するテキストボックスがdisabled属性を持っているため、ユーザーはこのフィールドに入力できず、フォームが送信された際にこのフィールドの値は送信されません。

disabled属性と似ているが異なる属性にreadonlyがあります。readonly属性は要素に対してユーザーの入力を禁止しますが、フォーム送信時にはその値が含まれます。また、readonlyは<input>や<textarea>要素にのみ適用されます。

ImaelImael

リファクタリング

リファクタリング手法
外部環境への接続情報は別のファイルに定数定義する
不変なものは別のファイルに定数定義する
外部起因で変更の可能性が予見さてるものはべつのファイルに定数定義する
複数個所に同じ処理がある場合はクラスや関数で定義して、それを呼び出すようにする
再利用できそうな処理はクラスや関数で定義して、それを呼び出すようにする
1関数(1メソッド)は1関心毎
関数(メソッド)にドキュメンテーションコメントを残す
ネストは浅くする
変数名や関数名をわかりやすい名称にする
ビジネスロジック部分とテンプレート部分を分ける
コメントアウトしたソースは削除する

注意点
複数個所に同じ処理があっても、将来的にそれらはべつの修正を受け、別進化していく可能性があるものはリファクタリング対象外
何でもかんでもリファクタリングしてしまうとプログラムの可読性が低くなり逆に生産性が下がる可能性がある
リファクタリングする時間は限られているので、一気にやらずに少しずつ実施していく

ImaelImael

require_once(dirname(DIR) . "/config/config.php");
/config/config.phpの親のディレクトリを返す

ImaelImael

<?php declare(strict_types=1); ?>
<div id="menu">
<h3>メニュー</h3>
<?php if (mb_strpos($_SERVER["REQUEST_URI"], "search.php") !== false) { ?>
<div class="sub_menu">社員検索</div>
<div class="sub_menu"><a href="input.php">社員登録</a></div>
<?php } else { ?>
<div class="sub_menu"><a href="search.php">社員詮索</a></div>
<div class="sub_menu">社員登録</div>
<?php } ?>
</div>
mb_strposはURLにsearch.phpが含まれているかを見ている
mb_strpos — 文字列の中に指定した文字列が最初に現れる位置を見つける

ImaelImael

SQLも実行、DBへの接続はシングルトンパターンがよくつかわれる。
<?php
declare(strict_types=1);

class DataBase
{
private static PDO $pdo;

/**
 * コンストラクタ
 */
private function __construct()
{
}

private static function getInstance(): PDO
{
    if (!isset(self::$pdo)) {
        self::$pdo = new PDO(
            "mysql:host=" . DB_HOST . ";dbname=" . DB_NAME . ";charset=utf8", 
            DB_USER, 
            DB_PASS
        );
    }
    return self::$pdo;
}

}
?>

ImaelImael

if (isset($_SESSION["id"])) {
header("Location: login.php");
exit;
}

ImaelImael

ログアウトはセッションの削除
ロケーションで強制てきに遷移

このスクラップは2023/10/08にクローズされました