CSSでスタイルを整える

Bootstrapで時短しつつスタイルを整える。

Bootstrapのインストール

Composerを使ってBootstrap の Sass と JavaScript をインストール

1
$ composer require twbs/bootstrap:4.5.0

公式Bootstrapダウンロード




これをDockerのコンテナで実行。

1
$ docker-compose exec app composer require twbs/bootstrap:4.5.0

ディレクトリ構成

1
2
3
4
5
6
7
8
bootstrap/
├── dist/
│ ├── css/
│ └── js/
├── docs/
│ └── examples/
├── js/
└── scss/

cssディレクトリ以下にある以下のファイルでフルのBootstrapが使える。

  • bootstrap.css
  • bootstrap.min.css

HTMLで読み込み

1
<link rel="stylesheet" href="../vendor/twbs/bootstrap/dist/css/bootstrap.css">

Bootstrapのカスタマイズ

Sassのインストール

Scssライブラリをインストール

scssphp/scssphp
https://github.com/scssphp/scssphp
インストールのコマンド

1
docker-compose exec app composer require scssphp/scssphp

vendorディレクトリ以下にscssphp/scssphpディレクトリができる

Bootstrapのカスタマイズ

ディレクトリ構成

1
2
3
4
5
stylesheets/
├── css/
| ├─ app.css
└── scss/
└─ app.scss

app.scssを編集し、app.cssにコンパイルしてhtmlファイルから読み込む



app.scss

1
@import 'vendor/twbs/bootstrap/scss/bootstrap'

Dockerのappコンテナ内でbashコマンドを使う

1
docker-compose exec app /bin/bash

scssphpコマンドを実行、コンパイルした結果をcssファイルに書き出す

1
vendor/scssphp/scssphp/bin/pscss < companies/stylesheets/scss/app.scss > companies/stylesheets/css/app.css

カスタマイズ法

  • 変数の変更
    @import の前で行う
  • 要素の変更
    @importの後で行う
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// @importの前で変数の定義
// line-height
$headings-line-height: 1.5;
$line-height-base: 1.65;

// Colors
$gray-dark: #546E7A;

@import 'vendor/twbs/bootstrap/scss/bootstrap';

// @importのあとでスタイルの上書き
body {
letter-spacing: .1em;
text-align: justify;
}

classを付与してスタイルしていく

ページ全体を中央ぞろえしたい

全体をdivタグでくくってcontainerクラスを付ける

body以下をマウスで選択

ctrl + shift + p

wrapで検索、 __EmmetのWrap with Abbreviation__を選択 -> enter -> divを入力すると、選択範囲をくくったdivタグができる

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<div class="container"> // ページ全体を中央ぞろえ
<h1 class="h2 text-dark mt-4 mb-4">会社情報の登録</h1> // 見出しの大きさ h2 / 字の色 text-dark / mt-4 マージントップ / mb-4 マージンボトム
<form action="create.php" method="POST">
<?php if (count($errors)) : ?>
<ul class="text-danger"> // エラー文字を赤
<?php foreach ($errors as $error) : ?>
<li><?php echo $error; ?></li>
<?php endforeach; ?>
</ul>
<?php endif; ?>
<div class="form-group"> // form はグループごとにform-group
<label for="name">会社名</label>
<input class="form-control" type="text" name="name" id="name" value="<?php echo $company['name'] ?>"> // inputにform-control
</div>
<div class="form-group">
<label for="establishment_date">設立年月日</label>
<input class="form-control" type="date" name="establishment_date" id="establishment_date" value="<?php echo $company['establishment_date'] ?>">
</div>
<button type="submit" class="btn btn-primary">登録する</button> // ボタンにスタイルをあてる
</form>
</div>

レイアウトを共通化

同じ部分は共通化しておく(以後の修正が楽・修正漏れがない)

共通部分のスタイルを記述したファイルを作る

個別のところに変数に格納したコンテンツを読み込む

ディレクトリ構成

1
2
3
4
5
companies/
├─views/
| ├─layout.php
| └─new.php
└─new.php
  • views/layout.php 共通部分のスタイルを記述したファイルを作る
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    <!DOCTYPE html>
    <html lang="ja">
    <head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="../stylesheets/css/app.css">
    <title><?php echo $title; ?></title> // タイトルを変数から読み込む
    </head>
    <body>
    <div class="container">
    <?php include $content; ?>  // ページの中身をviews以下のファイルから読み込む
    </div>
    </body>
    </html>
  • new.php アクセスされるファイル
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <?php

    $company = [
    'name' => '',
    'establishment_date' => '',
    'founder' => '',
    ];
    $errors = [];

    $title = '会社情報の登録'; // タイトルに変数を格納
    $content = __DIR__ . '/views/new.php'; // コンテンツ内容をviews以下のファイルから変数に格納
    include __DIR__ . '/views/layout.php'; // レイアウトのファイルを読み込み
    /views/new.php コンテンツファイル
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    <h1 class="h2 text-dark mt-4 mb-4">会社情報の登録</h1>
    <form action="create.php" method="POST">
    <?php if (count($errors)) : ?>
    <ul class="text-danger">
    <?php foreach ($errors as $error) : ?>
    <li><?php echo $error; ?></li>
    <?php endforeach; ?>
    </ul>
    <?php endif; ?>
    <div class="form-group">
    <label for="name">会社名</label>
    <input class="form-control" type="text" name="name" id="name" value="<?php echo $company['name'] ?>">
    </div>
    <div class="form-group">
    <label for="establishment_date">設立年月日</label>
    <input class="form-control" type="date" name="establishment_date" id="establishment_date" value="<?php echo $company['establishment_date'] ?>">
    </div>
    <div class="form-group">
    <label for="founder">代表者</label>
    <input class="form-control" type="text" name="founder" id="founder" value="<?php echo $company['founder']?>">
    </div>
    <button type="submit" class="btn btn-primary">登録する</button>
    </form>

    一覧ページ

    データベースからデータを取得して表示する
  1. データベースからデータを取得 配列で取得
  2. HTMLでデータを表示 ループで一つずつ表示
  3. データがないときの処理

    データがないときなどイレギュラーパターンを想定しての処理をかけることがうろダクションコードへの第一歩

    MySQLで特定テーブルの全データを削除する

    TRUNCATE TABLE

  • 指定したテーブルの全データを削除する

    tbl_name: テーブル名

    TRUNCATE[TABLE]tbl_name

  • compnaiesテーブルの全データ削除

    1
    TRUNCATE TABLE companies;

    XSS対策

    有名なセキュリティの脆弱性XSS(クロスサイトスプリクティング)対策をする

    特殊文字をエスケープさせる

  • <

    &lt;

  • >

    &gt;

    PHPでXSS対策

    htmlspecialchars()を使ってHTML特殊記号をエスケープする

  • HTMLの特殊文字を文字参照に置き換える

    • $string: 変換する文字列
    • $flags: 処理の仕方を指定するフラグ
    • $encoding: 文字を変換するときに使用するエンコーディング
      1
      htmlspecialchars($string, $flags, $encoding)

データを登録する

HTMLのフォームに入力されたデータをPHPで処理してデータベースに登録する

  • 登録
  • リダイレクト
  • バリデーション

    PHPの定義済み変数

    PHPで定義されている変数。外部から情報などが取得できる

    $_ENV

  • 環境変数 連想配列として受け取る

    $_POST

  • POSTされた情報 連想配列として受け取る

    $_GET

  • URLパラメータの情報 連想配列として受け取る

    $_SERVER

  • サーバや実行時の環境情報 連想配列として受け取る

    REQUEST_METHOD: ページにアクセスする際に使用されたメソッド名

    'GET','POST'など

    マジック定数

    使われる場所によって値が変化する定数がマジック定数

    __DIR__

    そのファイルの存在するディレクトリ名

    __FILE__

    そのファイルの古パスとファイル名

    __LINE__

    そのファイル上の現在の行番号

    外部ファイルの読み込み

    共通の処理は別ファイルにまとめて、そのファイルを読み込んで使おう

    require

    指定したファイルを読み込む。読み込みが失敗すると処理がそこで中断される
    1
    require 'somefile.php';'

    require_once

    reuireとほぼ同じ。一度しかファイルを読み込まない

    悩んだらrequire_onceを使うことを推奨
    1
    require_once 'somefile.php';'

    共通の関数などをライブラリのファイルにまとめる

    複数のファイルで共通する関数などをまとめたライブラリを作り、実行するファイルから読み込んで使用する
  1. libフォルダ(ライブラリ置き場)を実行ファイルの階層に作る
  2. libフォルダに関数をまとめるファイルを作る(例mysqli.php)
  3. 実行するファイルから読み込む

    ライブラリのファイル

    libフォルダ以下にmysqli.phpファイルを作る
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    <?php

    require __DIR__ . '/../../vendor/autoload.php';

    function dbConnect()
    {
    $dotenv = Dotenv\Dotenv::createImmutable(__DIR__ . '/../..');
    $dotenv->load();

    $dbHost = $_ENV['DB_HOST'];
    $dbUsername = $_ENV['DB_USERNAME'];
    $dbPassword = $_ENV['DB_PASSWORD'];
    $dbDatabase = $_ENV['DB_DATABASE'];

    $link = mysqli_connect($dbHost, $dbUsername, $dbPassword, $dbDatabase);
    if (!$link) {
    echo 'Error: データベーに接続できません' . PHP_EOL;
    echo 'Debugging error: ' . mysqli_connect_error() . PHP_EOL;
    exit;
    }
    return $link;
    }

    実行ファイルでの読み込み

    実行ファイルでの読み込み
    create.php
    1
    2
    3
    4
    5
    6
    <?php

    require_once __DIR__ . '/lib/mysqli.php'; // ライブラリのファイルを読み込み(関数が使えるようになる)
    ...
    // データベースに接続する
    $link = dbConnect();

    登録する情報をPHPへ送る

    情報の送り先ファイルをaction属性の値に、データの登録なのでメソッドはPOST
    送り先のphpファイルに設定してフォームを送信すると、

    $_POSTの連想配列として情報が渡せる
    1
    2
    3
    4
    5
    <form action="create.php" method="POST">
    ...
    ...
    <button type="submit">登録する</button>
    </form>

    PHPで受け取った情報をデータベースに登録する

  4. HTTPメソッドがPOSTだったら
  5. POSTされた会社情報を変数に格納する
  6. バリデーションする
  7. データベースに接続する
  8. データベースにデータを登録する
  9. データベースとの接続を切断する

HTTPメソッドがPOSTだったら

1
2
3
if ($_SERVER['REQUEST_METHOD'] === 'POST'){
// メソッドがPOSTのときだけPOSTされた会社情報を変数に格納する
}

POSTされた会社情報を変数に格納する

1
2
3
4
5
$company = [
'name' => $_POST['name'],
'establishment_date' => $_POST['establishment_date'],
'founder' => $_POST['founder']
];

バリデーションする

あとで

データベースに接続する

1
$link = dbConnect();

データベースにデータを登録する

1
createCompany($link, $company);

データベースとの接続を切断する

1
mysqli_close($link);

リダイレクト

データを保存した後、登録情報が表示されるページに遷移させる

遷移先のページを作る
index.php

表示する内容をHTMLで記述しておく

データ登録後にページを遷移させる

1
header("Location: index.php");

アクセスログとエラーログを出力

ログとはプログラムの実行状況・データ送受信などを記録しておくもの

PHP・Apacheのログ

ログには主にアクセスログとエラーログがある。

PHPはエラーログ、Apacheはアクセスログとエラーログを主に出力

ログを確認

Dockerコンテナ内のログを確認するコマンドdocker logs

  • docker ps コンテナ名を確認
  • docker logs -f <コンテナ名> - ログを確認するとき(-f: follow ログの出力を表示し続ける)
  • docker logs <コンテナ名> -f 2>/dev/null - アクセスログを確認(エラーログ捨てる)
  • docker logs <コンテナ名> -f 1>/dev/null - エラーログを確認(アクセスログを捨てる)

    ログにエラーを記録

    mysqli関数にエラーがあったときにログを出力
    1
    2
    3
    4
    5
    $result = mysqli_query($link, $sql);
    if (!$result) {
    error_log('Error: Fail to create company');
    error_log('Debugging Error: ' . mysqli_error($link));
    }

    バリデーション処理

    バリデーション処理に使う関数
  • strlen()

    文字のあるなしを判定。
  • explode(区切り文字列, 入力文字列)

    文字列を区切って配列に格納
  • count()

    配列の要素を数えて数を返す
  • checkdate(月, 日, 年)

    暦が正しいかを判定
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    function validate($company) {

    // エラーを`$errors`という配列を準備して配列に格納する
    $errors = [];

    // 会社名
    if (!strlen($company['name'])) { // 入力がない場合
    $errors['name'] = '会社名を入力してください';
    } elseif (strlen($company['name']) > 255) { // 文字数が多い場合
    $errors['name'] = '会社名は255文字以内で入力してください';
    }
    // 設立日
    $dates = explode('-', $company['establishment_date']); // 日付の形式 yyyy-mm-dd を"-"で分割している。
    if (!strlen($company['establishment_date'])) { // 入力がない場合
    $errors['establishment_date'] = '設立日を入力してください';
    } elseif (count($dates) !== 3) { // datesの配列が3つかどうかで形式を判定
    $errors['establishment_date'] = '設立日を正しい形式で入力してください';
    } elseif (!checkdate($dates['1'], $dates['2'], $dates['0'])) { // 存在する日付かどうかの判定
    $errors['establishment_date'] = '設立日を正しい日付で入力して下さい';
    }

    HTMLとPHPファイルを分割

    HTMLファイルを分割したらincludeで読み込もう
  • include

    指定したファイルを読み込
    1. 読み込みが失敗しても処理が中断されない
    2. HTMLやテキストなどを読み込むときに使う
      1
      include 'somefile.php';
  • require_once

    指定したファイルを読み込む
    1. 読み込みが失敗したら処理が中断される
    2. 関数など重要な処理を読み込むときに使う
      1
      require_once 'somefile.php';

      HTMLに未定義の変数があるとき

      空の変数を用意しておき、エラーを回避する。
  • 例 : $errorsという変数がHTMLコード内にある時

    HTMLの読み込みより前に空の変数を宣言しておけばOK
1
2
3
4
5
<?php

$errors = [];

include 'views/new.php';

フォームの入力値を残す

フォームの入力でバリデーションエラーが出たら入力済みの値が消えてしまうが、値を保持させたい

inputタグのvalue属性を使う

input要素の値を指定する属性

  • テキスト入力欄などにおいては初期入力値を表す
    1
    <input type="text" id="name" name="name" value="<?php echo $company['name']?>">

    ラジオボタンの初期値checked属性

    checked属性をつけると初期値で選択された状態になる
    1
    2
    3
    <input type="radio" name="sex" id="sex1" value="男性"
    <?php echo (#user['sex'] === '男性')? 'checked' : '' ; ?>>
    <label for ="sex1">男性</label>
  • 3項演算子とif文
    1
    2
    3
    4
    5
    6
    7
    8
    9
    eco ($user['sec'] === '男性') ? 'checked' : '' ;

    // 以下の文と等価

    if ($user['sex'] === '男性') {
    echo 'checked';
    } else {
    echo '';
    }

    フォーム初回読み込み時にエラーが出る

    初回読み込み時には、変数が未定義のため、エラーとなる。

    回避のため、HTML読み込み前に変数を空で宣言しておく
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <?php

    $review = [
    'title' =>'',
    'author' =>'',
    'status' =>'',
    'score' =>'',
    'summary' =>'',
    ];

    $errors = [];

    include 'views/new.php';

HTMLで表示

Dockerのsrc以下のフォルダがApacheの/var/www/htmlのフォルダに同期されている

docker-compose.ymlの設定volumes:以下)

1
2
3
4
5
6
7
8
9
10
app:
build:
context: .
dockerfile: docker/app/Dockerfile
ports:
- "50080:80"
volumes:
- ./src:/var/www/html
depends_on:
- db`

src以下のフォルダに置いたファイルには、ブラウザから

localhost:50080/ファイルのパスで表示できる

ページの表示

src直下にnew.phpを配置

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>PHPファイルでHTMLを表示</title>
</head>
<body>
<h1>HELLO WORLD!</h1>
</body>
</html>

ブラウザのアドレスにhttp://localhost:50080/new.phpを指定するとHTMLが表示される

HTMLのフォーム

フォームとは「お問い合わせ」「会員登録」など、ユーザーが入力処理を行うために使用されるもの

1
2
3
4
<form action="create.php" method="post">
<label for="name">名前</label>
<input type="text" name="name" id="name">
<button type="submit">登録する</button>
  • formタグ: フォームを作成する
  • actionタグ: 送信ボタンを押した後に移動するページ
  • method: データの送信方法GETかPOSTを指定。登録系のときはPOSTを指定
  • labelタグ: フォームのラベルを作成する
  • for パーツのid属性と同じ値にすることでパーツをラベルを関連づけられる
  • input type=”text”: 1行のテキストエリアを設置する
  • name: パーツの名前。PHPにデータを送信する際の項目名になる

    ラジオボタン

    ラジオボタンにすることで複数から一つを選ばせることができる。

    nameの名前を同じにするとグループ化できる
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    <form action="create.php" method="post">
    <div>
    <input type="radio" name="sex" id="male" value="male">
    <label for="male">男性</label>
    </div>
    <div>
    <input type="radio" name="sex" id="female" value="female">
    <label for="female">女性</label>
    </div>
    <button type="submit">登録する</button>

PHPでライブラリを使う

環境変数の管理にライブラリPHPDOTENVを使うので、ライブラリの管理ツールを導入

PHPでライブラリを導入したいときはComposerを使うと便利。

ComposerはPHPの依存管理ツール

Composerの仕組み

composer.jsoncomposer.lockファイルで依存するライブラリを定義する。

  • composer.json
    • プロジェクトで使用するライブラリを一覧にしたもの
  • composer.lock
    • 実際にどのライブラリのどのバージョンをダウンロードしたかをひとまとめにしたもの
  1. composer install を実行すると、インストールしたライブラリとバージョン情報が書き出される
  2. composer.lockがある状態でcomposer installすると、composer.lockに記されたバージョンのライブラリがインストールされる

    Composerのコマンド

  • init 対話形式でcomposer.json を作成する
    • composer init
  • require新しいライブラリを追加する

    composer.jsonにライブラリが、composer.lockに実際にインストールしたものが記載される
    • composer require <ライブラリ名>
  • install composer.jsonもしくはcomposer.lockにしたがってライブラリをインストールする-共通のバージョンのライブラリを使うことができる
    • composer install
  • removeライブラリを取り除く
    • composer remove <ライブラリ名>

      環境変数を管理

  • 通常の変数 - PHPのコードの中で定義し、実行したプロセス内でのみ使用できる
  • 環境変数 - PHPが動いているOSに保存し
    PHPアプリケーションに渡す仕組み(OSに格納される変数)

    PHPで環境変数をつかう

    .envファイルを使って環境変数を管理(phpdotenv)
  • .envファイル: 重要な設定データを定義 = 環境変数
    1
    DB_HOST=db
  • プログラムのファイル: .envファイルに定義された値を取得して使える
    1
    2
    $dbHost = $_ENV['DB_HOST']
    $link = mysqki_connect($dbHost, ..., ..., ...);

    Composerのインストール

    docker-compose exec app composer init

    設定はそのままエンター連打。文字を入力するのは以下の2か所

    Author [, n to skip]: nを入力

    Do you confirm generation [yes]? yesを入力

    src以下にcomposer.jsonファイルができている

    phpdotenvのインストール

    GitHubより、インストール法をコピペ
    docker-compose exec app composer require vlucas/phpdotenv

    .envファイルに環境変数を定義

    .env
    1
    2
    3
    4
    DB_HOST="db"
    DB_USERNAME="book_log"
    DB_PASSWORD="pass"
    DB_DATABASE="book_log"

    PHPファイルで読み込み

    phpファイルの最初にライブラリを読み込む
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    <?php

    require __DIR__ . '/../vendor/autoload.php'; // オートロードファイルを読み込む

    function dbConnect()
    {
    $dotenv = Dotenv\Dotenv::createImmutable(__DIR__ . '/..'); // .envファイルを読み込む
    $dotenv->load();

    $dbHost = $_ENV['DB_HOST']; // 環境変数を変数に代入
    $dbUsername = $_ENV['DB_USERNAME'];
    $dbPassword = $_ENV['DB_PASSWORD'];
    $dbDatabase = $_ENV['DB_DATABASE'];

    $link = mysqli_connect($dbHost, $dbUsername, $dbPassword, $dbDatabase); // 環境変数を代入した変数を使ってデータベースに接続
    if (!$link) {
    echo 'Error: データベーに接続できません' . PHP_EOL;
    echo 'Debugging error: ' . mysqli_connect_error() . PHP_EOL;
    exit;
    }
    return $link;
    }

PHPからデータベースのテーブルを作成

PHPファイルからテーブルを作成できるように準備

mysqli()関数をつかう

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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
<?php

function dbConnect()
{
$link = mysqli_connect('db', 'book_log', 'pass', 'book_log');
if (!$link) {
echo 'Error: データベーに接続できません' . PHP_EOL;
echo 'Debugging error: ' . mysqli_connect_error() . PHP_EOL;
exit;
}
return $link;
}

function dropTable($link)
{
$dropTableSql = 'DROP TABLE IF EXISTS companies;';
$result = mysqli_query($link, $dropTableSql);
if ($result) {
echo 'テーブルを削除しました' . PHP_EOL;
} else {
echo 'Error: テーブルの削除に失敗しました' . PHP_EOL;
echo 'Debugging Error: ' . mysqli_error($link) . PHP_EOL;
}
}

function createTable($link)
{
$createTableSql = <<<EOT
CREATE TABLE companies (
id INTEGER AUTO_INCREMENT NOT NULL PRIMARY KEY,
name VARCHAR(255),
establishment_date DATE,
founder VARCHAR(255),
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
) DEFAULT CHARACTER SET=utf8mb4;
EOT;
$result = mysqli_query($link, $createTableSql);
if ($result) {
echo 'テーブルを作成しました' . PHP_EOL;
} else {
echo 'Error: テーブルの作成に失敗しました' . PHP_EOL;
echo 'Debugging Error: ' . mysqli_error($link) . PHP_EOL;
}
}

$link = dbConnect();
dropTable($link);
createTable($link);
mysqli_close($link);

lesson5 データベース(MySQL)

MySQLを使う流れ

  1. MySQLに接続する
  2. MySQLに命令する
    • テーブルにデータを登録する
    • テーブルからデータを取得する
  3. MySQLとの接続を切断する

MySQLに接続しよう

mysql クライアントからmysqlサーバへの接続

  • -h:host ホスト名
    
  • -u:user ユーザー名
    
  • -D database データベース名(大文字)
    
  • -p password 値を指定しないとターミナルで入力、非表示なのでセキュア
    

appコンテナからdbコンテナのmysqlに接続する

$ docker-compose exec app mysql -h db -u book_log -D book_log -p

パスワードは「pass」を入力

mysqlとの接続を切断する

>quit

(exitでも可能)

接続と切断

  • MySQLへ接続
    1
    2
    3
    4
    5
    6
    7
    8
    9
    $ docker-compose exec app mysql -h db -u book_log -D book_log -p
    Enter password:
    Welcome to the MariaDB monitor. Commands end with ; or \g.
    Your MySQL connection id is 2
    Server version: 5.5.62 MySQL Community Server (GPL)

    Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

    Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.
  • MySQLから切断
    1
    2
    MySQL [book_log]> quit
    Bye

    SQL文でデータベースを操作する

    テーブルの作成

    CREATE TABLE 文で作成
    1
    2
    3
    4
    5
    CREATE TABLE[IF NOT EXISTS]<テーブル名>(
    <列名1><データ型><制約>,
    <列名2><データ型><制約>,
    ・・・
    )<テーブルオプション>;
  • 命名ルール
    • 半角英数
    • アンダーバー
    • 最初の文字はアルファベット
    • 名前の重複はだめ(1つのデータベースに同名のテーブルダメ,1つのテーブルに同名の列はダメ)

データ型 列ごとにデータ型を宣言

  • INTEGER 整数
  • VARCHAR 文字列(可変長文字列)
  • DATE 日付
  • TIMESTAMP 日付と時間の両方を含む値

制約 鉄に入れるデータに制限や条件をかけること

  • NOT NULL データを必ず入れる
  • PRIMARY KEY プライマリーキー(主キー)制約
  • AUTO _INCREMENT データを追加した際に最大値より1づつ増えていく
  • DEFAULT CURRENT_TIMESTAMP 対象の列に値を指定しなかった場合にデフォルト値が現在のタイムスタンプに設定される。

テーブルを作成してみる

mysqlにつないで以下のコマンドをメモ帳などからコピペで実行。

typoでミスらないように。

1
2
3
4
5
6
7
8
9
CREATE TABLE book_log (
id INTEGER AUTO_INCREMENT NOT NULL PRIMARY KEY,
book_name VARCHAR(255),
author VARCHAR(100),
status VARCHAR(50),
score INTEGER,
review VARCHAR(500),
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
) DEFAULT CHARACTER SET= utf8mb4;

テーブルの確認

SHOW COLUMNS FROM book_log;

1
2
3
4
5
6
7
8
9
10
11
+------------+--------------+------+-----+-------------------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+-------------------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| book_name | varchar(255) | YES | | NULL | |
| author | varchar(100) | YES | | NULL | |
| status | varchar(50) | YES | | NULL | |
| score | int(11) | YES | | NULL | |
| review | varchar(500) | YES | | NULL | |
| created_at | timestamp | NO | | CURRENT_TIMESTAMP | |
+------------+--------------+------+-----+-------------------+----------------+

テーブルの削除

DROP TABLE <テーブル名>;

ファイルからSQL文を実行

テキストファイルにSQL文を保存、下記のコマンドを実行

mysql < text_file

Docker上のMySQLに対して実行するなら

docker-compose exec app /bin/bash (appコンテナ内でコマンドを実行)

mysql -h db -u book_log -D book_log -p < text_file

PHPからMySQLに接続

MySQLiの使い方

  • mysqli_connext関数
    1
    `mysqli_connect('my_host','my_user','my_password','my_db')`

読書ログでMySQLに接続するなら

1
mysqli_connect('db','book_log','pass','book_log');

MySQLに接続できないケースの対策

mysqli_connect()は接続に失敗した場合にFALSEを返す。

FALSEが帰ってきたらアプリケーションを終了させよう

1
2
3
4
5
6
7
$link = mysqli_connect('db','book_log','pass','book_log');
if(!$link) {
echo 'Error: データベースに接続できません' . PHP_EOL;
echo 'Debugging error: '. mysqli_connect_error() . PHP_EOL;
exit;
}
// $linkがFALSEのときにif文が実行-> エラーが表示される

MySQLとの接続を切断する

  • mysqli_close関数

     $link: mysqli_connect()が返すリンクIDが格納されている
    mysqli_close($link);

テーブルにデータを登録する

MySQL にコマンドで登録する方法

1
2
3
4
5
6
7
8
9
INSERT INTO companies (
name,
establishment_date,
founder
) VALUES (
'mercari inc',
'2012-02-01',
'Shintaro Yamada'
);

結果の確認

1
2
3
4
5
6
SELECT * FROM companies\G
id: 1
name: mercari inc
establishment_date: 2012-02-01
founder: Shintaro Yamada
created_at: 2021-04-17 19:34:05

PHPからMySQLに対してSQL文を実行する方法

INSERT文を使うと、テーブルに1行のデータを挿入する
$link:mysqli_connect() が返すリンクIDが格納されている

$query:SQL文の文字列

1
mysqli_query($link, $query)

複数行にまたがる文字列を表記しよう(ヒアドキュメント)

  • 構文
    1
    2
    3
    <<<EOT // ID
    内容
    EOT; // 終わりのID
    $sqlにSQL文を格納し、mysqli()関数の第2引数に渡すと、PHPからSQL文を実行できる
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    $sql = <<<EOT
    INSERT INTO companies (
    name,
    establishment_date,
    founder
    ) VALUES (
    'SmartHR Ink',
    '2013-01-23',
    'Shoji Miyata'
    )
    EOT;
    1
    mysqli_query($link, $sql);

    SQL文実行時にエラーがあった場合、エラーメッセージを表示する

queryの戻り値を$resultに格納、$result がTRUEならデータを追加と表示、$resultがFALSEならエラーメッセージを表示する。

1
2
3
4
5
6
7
$result = mysqli_query($link, $sql);
if ($result) {
echo 'データを追加しました' . PHP_EOL;
} else {
echo 'Error: データの追加に失敗しました' . PHP_EOL;
echo 'Debugging error: ' . mysqli_error($link) . PHP_EOL;
}

バリデーション処理

論理演算子

  • ! 否定の演算子 // TRUEでないときTRUEを返す

  • && 論理積の演算子 // 左から判定し、TRUEなら右の判定へとすすむ。すべてTRUEならTRUEを返す

  • || 論理積の演算子 // 左から判定し、TRUEになった時点でTRUEを返す

書籍名のバリデーション ・空文字でないか? ・255文字以下か?

// バリデーション処理する関数

1
2
3
4
5
6
7
8
9
10
11
12
13
function validate($reviews)
{
$errors = []; // エラーを格納する配列

// 書籍名のバリデーション 書籍名が空のときと、255文字以上のとにきにエラーを配列に格納し、処理を中断する
if (!mb_strlen($reviews['title'])) {
$errors['title'] = '書籍名を入力してください';
} elseif (mb_strlen($reviews['title']) > 255) {
$errors['title'] = '書籍名は255文字以内で入力してください';
}

return $errors;
}

評価のバリデーション 5以下の整数であるか?(1~5)

型キャスト(型の変換)

  • (int) 整数への変換
  • (bool) 論理値への変換
  • (string) 文字列への変換

例文

1
2
$a = '2'; // string(1) "2"
$ var_dump((int)$a); // int(2) 文字列から整数へキャストされた

比較演算子

  • $a == $b 等しい場合にTRUE 比較時に型キャストされる
  • $a === $b 型キャストは行われない(厳密な比較)
  • $a != $b 等しくない場合にTRUE 比較時に型キャストされる
  • $a !== $b 型キャストは行われない(厳密な比較)
  • $a < $b $aが$bより小さい場合にTRUE
  • $a > $b $aが$bより大きい場合にTRUE
  • $a <= $b $aが$bより小さいか等しい場合(以下)にTRUE
  • $a >= $b $aが$bより大きいか等しい場合(以上)にTRUE

入力時に整数にキャストしておく
$review['score'] = (int)trim(fgets(STDIN));

1から5の整数かのバリデート処理

1
2
3
4
5
if (!$review['score']) {
$errors['score'] = '評価を整数で入力してください';
} elseif ($review['score'] > 5 || $review['score'] <1) {
$errors['score'] = '評価は1から5の整数で入力してください';
}

入力してほしい文字列と一致しているかのバリデーション

in_array()

  • 使い方
    in_array(探す値, 配列, <型のチェック>) : TRUE か FALSE を返す。
    1
    2
    3
    4
    5
    $status = ['未読', '読了', '読んでる'];    // この配列の値に一致しているもの以外をFALSEにする

    if (!in_array($review['status'], $status)) {
    $errors['status'] = '(読了,読んでる,未読)のうちいずれかを入力してください';
    }

    SQLのテーブルからデータを取得する

SELECT文を使う

1
SELECT <列名>,<列名> FROM テーブル名; // 指定した列のデータを取得する。
1
SELECT * FROM テーブル名;  // すべての列のデータを取得する。

PHPからSQLのSELECT文を実行してテーブルからデータを取得する。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// データベースに接続する
$link = mysqli_connect('db', 'book_log', 'pass', 'book_log');

// SQL文を実行、結果(mysqli_resultオブジェクト)が返ってくる。結果を$rsultsに格納。
$sql = 'SELECT name, founder FROM companies';
$results = mysqli_query($link, $sql);

// mysqli_resultオブジェクトを連想配列で取得(変換する、ここでは$companyに連想配列を格納し,
while文でループ処理している)
while($company = mysqli_fetch_assoc($results)) {
echo '会社名: ' . $company['name'] . PHP_EOL;
echo '代表者: ' . $company['founder'] . PHP_EOL;
}
// データの使用後にメモリを解放している。
mysqli_free_result($results);

mysqli関数 まとめ

PHPからMySQLに接続

mysqli_connect関数

mysqli_connect('my_host','my_user','my_password','my_db')

$link = mysqli_connect('my_host','my_user','my_password','my_db') // リンクIDを$linkに格納

PHPからMySQLとの接続を切断する

mysqli_close関数
mysqli_close($link)
$link: mysqli_connect()が返すリンクID

PHPからMySQLに対してSQL文を実行する

mysqli_query($link, $query)

$link:mysqli_connect() が返すリンクID

$query:SQL文の文字列

SQL文を(ヒアドキュメントなどで)$queryに格納し、$link(リンクID)と一緒にmysqli_query()に渡す。

INSERT INTO文 (登録)

1
2
3
4
5
6
7
8
9
10
11
$sql = <<<EOT
INSERT INTO companies (
name,
establishment_date,
founder
) VALUES (
'SmartHR Ink',
'2013-01-23',
'Shoji Miyata'
)
EOT;

SELECT文 (データの取得)

1
$sql = 'SELECT name, founder FROM companies';

SQLの結果であるmysqli_resultオブジェクト を連想配列で取得する

1
mysqli_fetch_assoc($results)

SQLの結果をメモリから解放する。

1
mysqli_free_result($results);

lesson4 PHPでテキストアプリ開発

ファイル置き場

part2 src/ディレクトリの下にPHPファイルを作成。

docker-compose execコマンドで実行

PHPの基本的の書き方

1
2
3
4
5
6
7
8
9
10
11
</php // 開始タグ

/*
複数行の
コメント
*/
echo 'Hi!PHP' .PHP_EOL; // 文

//単一行のコメント

?> //閉じタグ 省略推奨

echo 文字の出力

1
2
3
4
<?php

echo 'Hi! . PHP_EOL;
echo 'How's it going? . PHP.EOL;

最初のPHPファイル

ディレクトリ

tmp/echo.php

1
2
3
<?php

echo 'Hi'.PHP_EOL; // Hi

テキストアプリのメニュー内容

  • 読書ログの表示

    • 表示内容
    • 書籍名:銀河鉄道の夜
    • 著者名:宮沢賢治
    • 読書状況:読了
    • 評価:5
    • 乾燥:本当の幸せとは何だろうか?と考えさせられた

book_log.phpに記述していく

1
2
3
4
5
6
7
<?php

echo '書籍名:銀河鉄道の夜'.PHP_EOL;
echo '著者名:宮沢賢治'.PHP_EOL;
echo '読書状況:読了'.PHP_EOL;
echo '評価:5'.PHP_EOL;
echo '乾燥:本当の幸せとは何だろうか?と考えさせられた'.PHP_EOL;

標準入力の値を取得しよう

STDIN 標準入力(standard input)を意味する定数

fgets ()で指定したものから1行データを取得する

標準入力の値を取得する

fgets(STDIN)

1
2
3
4
5
6
7
8
9
<?php

echo '読書ログを登録します'.PHP_EOL;
echo '書籍名:';
echo fgets(STDIN);

//
読書ログを登録します
書籍名:ドラえもん

変数

変数に値を格納する

変数に値を格納することを「代入」という

$変数名=値(式)

$tile='ドラえもん'; // $titleという変数に「ドラえもん」という値を代入している

文字列とは?

文字を並べたものが文字列「’」「”」で囲む

1
'str'
1
"str"

「’」 「”」に比べてやや高速、変数やエスケープ文字は展開できない。

「”」変数やエスケープ文字を展開できる

1
2
3
$name = 'たけし'
echo '{$name}、ありがと!\n'; // 「{$name}、ありがと!\n」
echo "{$name}、ありがと!\n"; // 「たけし、ありがと!<改行>」

文字列の結合 「.」

1
2
$name = 'たけし';
echo $name.'グッジョブ! . PHP_EOL'; // たけしグッジョブ<改行>

登録時に余計なスペースを削除して登録

trim 文字列の先頭および末尾にあるホワイトスペースを取り除ける

trim($str)

1
trim('   ドラえもん') // 「ドラえもん」

PHP 条件分岐

構文

1
2
3
4
if
if(条件式) {
  文
}
1
2
3
if ($carts > 10) {
echo '買いすぎです';
}

真偽値を見てみる

var_dump();  // 型と値を確認できる (echo は文字列しか出力しない)

1
2
3
4
5
<?php

var_dump(1 <2 ); // bool(true)

var_dump(1 > 2); //bool(false)

繰り返し処理(無限ループ) while文

構文

1
2
3
while(条件式) {
文;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?php

$i = 0;

while (true) {
if($i <= 5) {
echo $i . PHP_EOL;
$i++;
} else {
break;
}
}
//
0
1
2
3
4
5

配列

  • 初期化

    $配列名 = [値1, 値2, 値3];

  • 配列に要素を追加

    $配列名[] = 値;

  • 配列の要素にアクセス (キーは0から始まる)

    $配列名[キー番号(文字列)]

連想配列

  • 初期化

    1
    2
    3
    4
    $配列名 = [
    'キー名' => 値,
    'キー名' => 値,
    ];
  • 配列に要素を追加

    1
    $配列名['キー名'] = 値;
  • 配列の要素にアクセス (キーは0から始まる)

    1
    $配列名['キー名']

    ※ PHP内部では配列と連想配列は区別されない(連想配列はキーが’0’,’1’,’2’…0から始まる文字列が添え字の配列として扱われている)

配列に配列を格納することもできる。

1
2
3
4
5
6
$arrys = [
[1,2,3,4,5]
,
[2,4,6,8,10]
,
];

繰り返し処理 foreach文

構文

  • 配列
    1
    2
    3
    foreach($配列名 as $要素名) {
    // 繰り返したい処理
    }
  • 連想配列
    1
    2
    3
    foreach($配列名 as $キー名 => 要素名) {
    // 繰り返したい処理
    }

    例文

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    <?php

    // 配列
    $numbers = [1, 2, 3, 4, 5];
    foreach ($numbers as $number) {
    echo $number * 2 .PHP_EOL;
    }

    // 連想配列
    $currencies = [
    'japan' => 'yen',
    'us' => 'dollar',
    'england' => 'pound',
    ];
    foreach ($currencies as $country => $currency) {
    echo $country . ':' . $currency . PHP_EOL;
    }

    関数 一連の処理を行うもの

関数定義

1
2
3
4
5
function 関数名(引数1, 引数2, ...,引数n)
{
# 処理
return 戻り値;
}

※ 引数と戻り値は省略できる, 関数名はキャメルケース

関数の呼び出し

  • 戻り値あり // 戻り値を変数に格納している。

    $変数 = 関数名(引数1, 引数2, …,引数n)

  • 戻り値なし // 関数から値は返ってこない

    関数名(引数1, 引数2, …,引数n)

例文

1
2
3
4
5
6
function multiply($a, $b)
{
return $a * $b;
}

echo multiply(3, 5) . PHP_EOL;

Windows10での開発環境構築 備忘録

WSL2 とはWindows上で動くLinux

VirtualBoxなどより軽量、高速、何よりMicrosoft謹製。
インストールも簡単。Windows10 PRO ならコマンド一発で導入できる。

WSL2 導入 Windows10PROの場合

簡略化されたインストール “ (pro版でのみ可能らしい) “

wsl --install

簡略化されたインストール コマンド wsl --install を使用するには、Windows Insider Program に参加し、Windows 10 のプレビュー ビルド(OS ビルド 20262 以降) をインストールする必要がありますが、

手動インストールの手順に従う必要がなくなります。
必要な操作は、管理者特権でコマンド ウィンドウ(Power Shell)を開いてwsl --install を実行するだけです。再起動後、WSL を使用する準備が整います。

windows terminalのインストール

windows storeよりインストール

VScode

Visual Studio Code公式サイト

よりインストール

拡張機能

  • 日本語化

    • Japanese Language Pack for Visual Studio Code
      Vusial Studio Code 内の表記を日本語化します 
  • 整形

    • Bracket Pair Colorizer 2
      括弧の色付けをします。
    • indent-rainbow
      インデントの色付けをします。
    • Code Spell Checker
      コードのスペルチェックをします。
  • 言語特有

    • HTML CSS Support
      HTMLドキュメントに対するCSSのサポートを行います。
    • PHP Intelephense
      PHPのコード補完をします。
    • Docker
      Dockerの操作をサポートします。
  • 表示

    • Material Icon Theme
      アイコンをマテリアルアイコンに変更します。
    • GitHub Theme
      GitHub公式のテーマです。講義では GitHub Dark テーマを使用します。こちらはお好きなものを入れてください。

      基本設定

  • フォント 14 16 など

  • 見た目の折り返し Editor Word Wrap on

  • 最終行に空白行をプラス Insert Final Newline ☑

  • 行末スペース削除 Trim Final Newlines ☑ / Trim Trailing - Whitespace ☑

  • タブサイズ 

  • Tab Size 2

    Gitのインストールと設定

    インストール時のウィザードで設定

  • Use Visual Studio Code as Git's default editor

    標準エディタをVScode1にしておく

  • Ajasuting your PATH environment

    パスを設定

  • Git from the command line and also from 3rd-party software

    サードパーティのソフトからも開けるように

  • Choose the default behavior of 'git pull'

  • Rebase

    コマンドラインで設定

  • ユーザー名を設定

    $ git config --global user.name "github user name"

  • メールアドレスを設定

    $ git config --global user.email github@example.com

  • Git で使用するエディタに Visual Studio Code を指定

    $ git config --global core.editor 'code --wait'

  • マージする時にファストフォワードされないようにする

    $ git config --global merge.ff false

  • プルの挙動をリベース型にする

    $ git config --global pull.rebase merges

  • 設定を確認する

    $ git config --list

    Docker

Windows10PROダウンロード

独学エンジニアのDockerイメージからコンテナを起動する

  • GitHubよりclone

    $ git clone https://github.com/dokugaku-engineer/server-side.git

  • part2をコピー
    $ cp -r part2 -t ~/code

    part2 ディレクトリにて作業する

    docker-compose.ymlのあるディレクトリでdockerコマンドを実行。

  • イメージをビルド

    docker-compose build //Successfully built

  • コンテナの作成と起動

    docker-compose up -d 実行 (-d はデタッチバックグラウンドで実行)

  • 起動しているコンテナの確認

    docker-compose ps

  • コンテナ内でPHPを実行

    docker-compose exec app php -v  // phpのバージョンが表示される

  • コンテナの削除

    docker-compose down // コンテナの終了と削除