Arale

アパレル、バリスタを経て未経験からのプログラマーになった男の勉強ログ

プログラムの大まかな流れを書いておく

画像のようにプログラムの大まかな流れをコメントアウトでメモ。

次に再開するときや他の人に見てもらうときにわかりやすく、

アドバイスも貰いやすい。備忘録として残します。

変に記述せずにどういった意図やゴールを持っているのか、

形として残すのが大事です。

laravel9でmigrate時のエラー対処

あくまで私がアプリを制作しているときにでた時の備忘録に。

今回は以下のようなエラーが出ました。

// ターミナルで表示されたエラー
Illuminate\Database\QueryException
  SQLSTATE[HY000] [1045] Access denied for user 'root'@'localhost' (using password: YES) 
  (SQL: select * from information_schema.tables where table_schema =
  first_app and table_name = migrations and table_type = 'BASE TABLE')
// envファイル
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=***** // phpMyAdminで作成したDB名
DB_USERNAME=root
DB_PASSWORD=

色々調べてみたら、いくつかの原因が - envファイルとdatabase.phpの差異 - php artisan cache:clear - php artisan config:cache - DB_SOCKETの記述漏れ

以上の4点が私が毎回直面するエラーでした。

備忘録をつけているつもりでしたが、忘れてました。

エラーが解決した時の記述です。

// 1.DB_SOCKETの記述も忘れない
// 2.php artisan cache:clear->php artisan config:cache
// 3.php artisan migrateでマイグレーション
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=*****
DB_USERNAME=root
DB_PASSWORD=root
DB_SOCKET=/Applications/MAMP/tmp/mysql/mysql.sock

phpのlayout機能

rubyでいう部分テンプレートと一緒

bladeと呼ばれるviewファイルを呼び起こすファイルがlaravelにはあります

これはRailsでいうerbファイルですかね。

早速下記にlayout.blade.phpファイルを用意します。

<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">

  <title>@yield('title')</title>

  <!-- Fonts -->
  <link href="https://fonts.googleapis.com/css2?family=Nunito:wght@400;600;700&display=swap" rel="stylesheet">

  <!-- Styles -->

  <style>
       中略
  </style>
</head>

<body class="antialiased">
  <div class="relative p-4">
    <nav>
      <a href="/">Home</a>
      <a href="/about">About</a>
      <a href="/contact">Contact</a>
      // 各コンテンツのリンク
    </nav>
  </div>
  <div class="relative flex items-top justify-center min-h-screen bg-gray-100 dark:bg-gray-900 sm:items-center py-4 sm:pt-0">
    @yield('content') //ここに呼び出したいビュー
  </div>
  @yield('scripts'); // JavaScriptを呼び出す
</body>

</html>

@yield('content')は呼び出したいビューです。

逆に各リンクのコンテンツ以外は全て共通部分なので、上記のコードで一纏めにしてます。

それではContactのbladeファイルはどうなっているか見てみます

@extends('layout') // layoutに反映させる記述
@section('title', 'Contact Us') // <head>内の<title>も反映
@section('content') // 以下が読み込みたいコンテンツ
<div class="max-w-6xl mx-auto sm:px-6 lg:px-8">
    <div class="flex justify-center pt-8 sm:justify-start sm:pt-0">
        <h1>Contact Us</h1>
    </div>

    <div class="mt-8 bg-white dark:bg-gray-800 overflow-hidden">
        <p>This is the contact page.</p>
    </div>
</div>
@endsection

@section('scripts') // 反映させたいJavaScript
<script>
    alert('contact us');
</script>
@endsection

まだまだ細かい記述などはこれからですが、

とりあえずこれだけ覚えてたら大丈夫そうです。

共通部分のbladeファイルを作り、各コンテンツに反映させる。

まだRubyでもオリジナルアプリを作ってませんが、

とりあえずPHPでそろそろ作る時期が近いづいてるかもしれません。

参考にしたサイト

zenn.dev

phpとdbのやりとりのこと

<form action="xxx.php" method="post">
name
<div><input type="text" name="n"></div>
message
<div><textarea  name="m"></textarea></div>
<input type="submit" value="SUBMIT">
</form>

送信先はxxx.php、POST送信

テキストフォーム、テキストエリアには名前をそれぞれ付けており、

$POST["n"], $POST["m"]でフォームに入力された情報を取得できる。

$my_num = htmlspecialchars($_POST["n"], ENT_QUOTES);
$my_mes = htmlspecialchars($_POST["m"], ENT_QUOTES);

phpの記述ではフォームで入力された情報に

タグなどがあった場合に無効化する記述を施し、

変数に格納してます。

$db = new PDO("mysql:host=localhost;dbname=db_book", "root", "root")
$変数 = new オブジェクト("mysql:host=ホスト名,dbname=DB名", "ユーザー名", "パスワード名")

$db->query("INSERT INTO tb_book(ban, nam, mes, dat) 
           VALUES(NULL, '$my_nam', '$my_mes', NOW())")

データベースを操作するためのコマンド

PDOオブジェクトを使用し、$db変数に代入している。

newはオブジェクトを作成するときに使用するコマンド

ホスト名やユーザー名はどこから探すのー?!ていう時は

MAMP>WebStart>MySQLから確認可能

$db->queryでSQL文を用いて、INTOの後にデータベースにあるテーブル名、

カラム名に該当するデータを入れてます。

VALUESの後に続くのは入れたい値を指定してます。

DBを操作する場合はページ毎にPDOオブジェクトが必要

表示プログラムの実行

$db = new PDO("mysql:host=localhost;dbname=db_book", "root", "root");
// tb_bookテーブルから全てのデータを取得
// queryメソッドの結果を$ps変数に代入
// 文字列や数値ではなく、PDOStatement(オブジェクト)が入っている
// $psはPDOStatementのPSからとってる?!
$ps = $db->query("SELECT * FROM tb_book");
// $psの中身はオブジェクトなので、printで出力できない
// fetchというメソッドを実行 SQLの実行結果から1レコード分を配列として返す
// 実行すると一番古いレコードが配列に変換され、$rに代入される
$r = $ps->fetch();
// fetchメソッドが返す配列はカラム名がそのままデータの名前になっている
// {}は展開式、各変数を囲むことで中身を表示する
print "{$r['ban']} {$r['nam']} {$['dat']} {$['mes']}";

長くなりましたが、以上がphpでdbのデータとのやりとり諸々です。 foreachやwhileを用いて、残りのデータを表示します。

メッセージを書き込むプログラム

<form>
  <input type="text" name="a">
  <input type="submit" value="SUBMIT">
</form>

<?php
  $f = fopen("chat.txt", "at");
  fwrite($f, $_GET["a"], "\n");
  fclose($f);
?>
  • fopen ファイルを開く

    • 第一引数にはオープンするファイル名を指定
    • 第二引数にはファイルを開く設定 aはファイルの末尾に追記、ファイルがない場合は新たに作る
    • 第二引数のtはテキストファイルを読み込む意
  • fwrite ファイルに記述

    • 第一引数には$f(ファイルハンドル)
    • 第二引数には書き込む内容 今回の場合はフォームで入力された値
    • 第三引数は改行したいので、改行コマンドを入れている
  • fclose ファイルを閉じる

    • 引数は閉じるファイルなので$fを入れる

参考URL

www.php.net

yu-nix.com

フォームで考えられるバグを防ぐ

一つ前の記事ではフォームで入力された値を

$_GET["a"]を用いて、表示する記述を書きました。

ただ、このままではタグなども入力が出来、

悪意のある情報を埋め込まれる可能性があります。

それを防ぐためにhtmlspecialcharsを用います。

$input = htmlspecialchars($_GET["a"], ENT_QUOTES);
print isset($_GET["a"]) ? $input . "だしん" : "何かしゃべって!";

$inputという変数に代入してます。

送信文字列のタグを無効化するhtmlspecialchars関数

第一引数には変換したい入力文字列を入れてます。

第二引数には変換パターンを入れてます。詳しい説明は下記にある参考URLをご覧ください。

空白のまま送信を押しても「だしん」が表示される

上記のコードの記述でタグを入力されても、

有効化されずに文字列として表示される処理を完了しました。

しかし、空入力のまま送信ボタンを押すと「だしん」と表示されてしまいます。

何か文字列が入力されたら「だしん」と語尾に表示したいように設定します。

$input = htmlspecialchars($_GET["a"], ENT_QUOTES);
print isset($_GET["a"]) && $_GET["a"] != "" ? $input . "だしん" : "何かしゃべって!";

&&はrubyでも出てきた用法かと思います。AかつBの時と条件を加えます。

!= は否定の時の用法ですね。この場合だと空ではない時という条件です。

参考URL

techplay.jp