20210123のPHPに関する記事は13件です。

PHP ログイン認証の作成手順③ 〜新規登録機能作成②とパスワードハッシュ化〜

新規登録フォームからPOSTで送られてきたデータをデータベースにINSERTする

手順

ユーザを登録する処理

register.phpでバリデーションに引っかからずに登録ができる準備が整った時の処理をコーディングしていく。
UserLogicクラスを作成し、その中のcreateUserメソッドを作成し、それを使用する。
createUserメソッドはtrueかfalseを返すような関数だから、新規登録に失敗した時には、
$err配列に格納して、バリデーションと同じようにエラー項目として表示させる。

register.php
<?php

require_once('../classes/UserLogic.php');

// エラーメッセージ
$err = [];

// バリデーション
if(!$username = filter_input(INPUT_POST, 'username')){
    $err[] = 'ユーザ名を記入してください';
}

if(!$email = filter_input(INPUT_POST, 'email')){
    $err[] = 'メールアドレスを記入してください';
}

$password = filter_input(INPUT_POST, 'password');
// 正規表現
if(!preg_match("/\A[a-z\d]{8,100}+\z/i", $password)){
    $err[] = 'パスワードは英数字8文字以上100文字以下にしてください。';
}

$password_conf = filter_input(INPUT_POST, 'password_conf');
if($password !== $password_conf){
    $err[] = '確認用パスワードと異なっています';
}

if(count($err) === 0){
    //ユーザを登録する処理
    $hasCreated = UserLogic::createUser($_POST);

    if(!$hasCreated){
        $err[] = '登録に失敗しました';
    }
}
?>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ユーザ登録完了画面</title>
</head>
<body>
<?php if (count($err) > 0) : ?>
<!-- エラーがある場合にforeachで該当エラーを表示させる -->
    <?php foreach($err as $e) : ?>
    <p><?php echo $e ?></p>
    <?php endforeach; ?>
<!-- $err配列に何もない=エラーがない から完了画面を表示させる -->
<?php else: ?>
    <p>ユーザー登録が完了しました。</p>
<?php endif ; ?>
<a href="signup_form.php">戻る</a>
</body>
</html>

UserLogicクラスを作成する

createUserメソッドでPOSTで送られてきたデータを引数にとる。
そして、送られてきたユーザ名、メールアドレス、パスワードを$arr配列に格納して、
prepareで用意したINSERT文のプレースホルダーに入れる。

UserLogic.php
<?php
require_once('../dbconnect.php');

class UserLogic
{
    /**
     * ユーザを登録する
     * @param array $userData
     * @return bool $result
     */
    public static function createUser($userData)
    {
        $result = false;
        $sql = 'INSERT INTO users (name, email, password) VALUES (?, ?, ?)';

        // ユーザデータを配列に入れる
        $arr = [];
        $arr[] = $userData['username'];
        $arr[] = $userData['email'];
        $arr[] = password_hash($userData['password'], PASSWORD_DEFAULT);
        try{
            $stmt = connect()->prepare($sql);
            $result = $stmt->execute($arr);
            return $result;
        }catch(\Exception $e){
            return $result;
        }
    }
}

?>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

PHP ログイン認証の作成手順② 〜新規登録機能作成とバリデーションの作成〜

手順

新規登録画面の作成

今回は、ユーザ名メールアドレスパスワードパスワード確認の4つのフォームを用意する

signup_form.php
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ユーザ登録画面</title>
</head>
<body>
    <h2>ユーザ登録フォーム</h2>
    <form action="register.php" method="POST">
    <p>
        <label for="username">ユーザ名</label>
        <input type="text" name="username">
    </p>
    <p>
        <label for="email">メールアドレス</label>
        <input type="email" name="email">
    </p>
    <p>
        <label for="password">パスワード</label>
        <input type="password" name="password">
    </p>
    <p>
        <label for="password_conf">パスワード確認</label>
        <input type="password" name="password_conf">
    </p>
    <p>
        <input type="submit" value="新規登録">
    </p>
    </form>
</body>
</html>

新規登録完了画面の作成

register.php
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ユーザ登録完了画面</title>
</head>
<body>
    <p>ユーザー登録が完了しました</p>
    <a href="signup_form.php">戻る</a>
</body>
</html>

バリデーションの作成

入力フォームにて入力し、送信した後はregister.phpへ情報が飛んで、リンクに繋がる。
その時にregister.phpの方で、登録が完了したか、入力エラーがあるかどうかを表示させる仕組みを作成する。
なお、新規登録を完了させることができた場合の処理はのちに行う。

①入力エラーが存在するフォームそれぞれに対して、エラーの文字を配列で集めていく。
②一つでもエラーの配列の要素がある場合は、あるもの全てをforeachで表示させていく。

register.php
<?php
// エラーメッセージ
$err = [];

// バリデーション
if(!$username = filter_input(INPUT_POST, 'username')){
    $err[] = 'ユーザ名を記入してください';
}

if(!$email = filter_input(INPUT_POST, 'email')){
    $err[] = 'メールアドレスを記入してください';
}

$password = filter_input(INPUT_POST, 'password');
// 正規表現
if(!preg_match("/\A[a-z\d]{8,100}+\z/i", $password)){
    $err[] = 'パスワードは英数字8文字以上100文字以下にしてください。';
}

$password_conf = filter_input(INPUT_POST, 'password_conf');
if($password !== $password_conf){
    $err[] = '確認用パスワードと異なっています';
}

if(count($err) === 0){
    //ユーザを登録する処理
}
?>

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>ユーザ登録完了画面</title>
</head>
<body>
<?php if (count($err) > 0) : ?>
<!-- エラーがある場合にforeachで該当エラーを表示させる -->
    <?php foreach($err as $e) : ?>
    <p><?php echo $e ?></p>
    <?php endforeach; ?>
<!-- $err配列に何もない=エラーがない から完了画面を表示させる -->
<?php else: ?>
    <p>ユーザー登録が完了しました。</p>
<?php endif ; ?>
<a href="signup_form.php">戻る</a>
</body>
</html>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

PHP ログイン認証の作成手順① 〜データベースと接続する〜

使用環境(ローカル環境)

・MAMP
・phpMyAdmin

データベース定義(使用するカラム)

・id
・name
・email
・password

手順

データベースとの接続

env.php
<?php
define('DB_HOST', 'localhost');
define('DB_NAME', 'user');
define('DB_USER', 'root');
define('DB_PASS', 'root');
?>
dbconnect.php
<?php

require_once('env.php');

function connect()
{
    $host = DB_HOST;
    $db = DB_NAME;
    $user = DB_USER;
    $pass = DB_PASS;

    $options = [
        PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
        PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
        PDO::ATTR_EMULATE_PREPARES   => false,
    ];

    $dsn = "mysql:host=$host;dbname=$db;charset=utf8mb4";

    try{
        $pdo = new PDO($dsn, $user, $pass, $options);
    }catch(PDOException $e){
        echo 'error'. $e->getMessage();
    }
}

?>
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【PHP 初級】配列を使いこなす➁ ~取得・検索・その他~

【PHP 初級】配列を使いこなす➀ ~宣言・初期化・追加・結合・削除~の続きです。
今回は配列から値を取得、検索する方法など、もう少し実務的な内容をまとめます。

値の取得

配列から値を取り出す色んな方法を見てみます。

キーを指定して値を取り出す

どの言語も同じように、数値やキーを指定して値を取り出します。

php > $fruits = ['apple', 'grape', 'banana'];

php > var_export($fruits[0]);
'apple'
php > $colors = ['C1' => 'red', 'C2' => 'purple', 'C3' => 'green'];

php > var_export($colors['C1']);
'red'

すべての値を取り出す

array_values

https://www.php.net/manual/ja/function.array-values.php

array_values (配列)
戻り値:配列

array_valuesは配列のすべての値を取り出し、数値のインデックス番号を付けた配列を返します。
【PHP】配列を使いこなす➀ ~宣言・初期化・追加・結合・削除~で紹介したように、配列の値の削除を行った後、インデックス番号を詰め直すのに利用したりします。
またarray_valuesに連想配列を渡せば、配列に変換することが出来ます。

php > $colors = ['C1' => 'red', 'C2' => 'purple', 'C3' => 'green'];

php > var_export(array_values($colors));
array (
  0 => 'red',
  1 => 'purple',
  2 => 'green',
)

多次元配列からキーを指定して値を取り出す

array_column

https://www.php.net/manual/ja/function.array-column.php

array_column (配列, 指定するキー)
戻り値:配列

array_columnは個人的にかなり良く使うメソッドなので、ぜひ使い方を身に付けてみてください。
array_columnは多次元配列のキーを指定し、全ての値を配列で返します。

php > $students = [
php >     ['class' => 1, 'name' => 'tanaka', 'age' => 15],
php >     ['class' => 2, 'name' => 'yamamoto', 'age' => 16],
php >     ['class' => 1, 'name' => 'honda', 'age' => 16],
php >     ['class' => 3, 'name' => 'inoue', 'age' => 17],
php > ];

// 学生の名前を取得
php > $students_name = array_column($students, 'name');
php > var_export($students_name);
array (
  0 => 'tanaka',
  1 => 'yamamoto',
  2 => 'honda',
  3 => 'inoue',
)

また第3引数を指定して、特定の値をキーにした多次元配列を生成することもできます。

array_column (配列, 指定するキー、新しい配列のキーとして指定するキー)
戻り値:配列

言葉が分かりづらいですが、例を見ればすぐに理解できると思います。

php > $students = [
php >     ['class' => 1, 'name' => 'tanaka', 'age' => 15],
php >     ['class' => 2, 'name' => 'yamamoto', 'age' => 16],
php >     ['class' => 1, 'name' => 'honda', 'age' => 16],
php >     ['class' => 3, 'name' => 'inoue', 'age' => 17],
php > ];

// クラス毎に名前を取得する
php > $name_by_class = array_column($students, 'name', 'class');
php > var_export($name_by_class);
array (
  1 => 'honda',
  2 => 'yamamoto',
  3 => 'inoue',
)

注意点はキーが重複する場合、後ろの値で上書きされます。
そのため、クラス1はhondaくんが取得されます。

名前だけでなく、学生の情報が全て取得したい場合は第2引数にnullを指定します。

php > $students = [
php >     ['class' => 1, 'name' => 'tanaka', 'age' => 15],
php >     ['class' => 2, 'name' => 'yamamoto', 'age' => 16],
php >     ['class' => 1, 'name' => 'honda', 'age' => 16],
php >     ['class' => 3, 'name' => 'inoue', 'age' => 17],
php > ];

// クラス毎に学生の情報を取得する
php > $student_by_class = array_column($students, null, 'class');
php > var_export($student_by_class);
array (
  1 =>
  array (
    'class' => 1,
    'name' => 'honda',
    'age' => 16,
  ),
  2 =>
  array (
    'class' => 2,
    'name' => 'yamamoto',
    'age' => 16,
  ),
  3 =>
  array (
    'class' => 3,
    'name' => 'inoue',
    'age' => 17,
  ),
)

こちらもクラス1は重複するため、hondaくんの情報のみ取得されています。

多次元配列のキーでグルーピングする

上書きしないでクラス毎の全員の情報が取得したい場合は、次のような自作メソッドが必要になります。

public function groupBy($list, $key) {
    $ret = array();
    if (is_array($list)) {
        foreach ($list as $val) {
            $ret[$val[$key]][] = $val;
        }
    }

    return $ret;
}

Utilメソッドとして定義し、どこからでも使えるようにしたら良いです。
グルーピングした結果は以下のようになります。

php > $students = [
php >     ['class' => 1, 'name' => 'tanaka', 'age' => 15],
php >     ['class' => 2, 'name' => 'yamamoto', 'age' => 16],
php >     ['class' => 1, 'name' => 'honda', 'age' => 16],
php >     ['class' => 3, 'name' => 'inoue', 'age' => 17],
php > ];

// クラス毎に学生をグループ化する
php > $group_by_class = groupBy($students, 'class');
php > var_export($group_by_class);
array (
  1 =>
  array (
    0 =>
    array (
      'class' => 1,
      'name' => 'tanaka',
      'age' => 15,
    ),
    1 =>
    array (
      'class' => 1,
      'name' => 'honda',
      'age' => 16,
    ),
  ),
  2 =>
  array (
    0 =>
    array (
      'class' => 2,
      'name' => 'yamamoto',
      'age' => 16,
    ),
  ),
  3 =>
  array (
    0 =>
    array (
      'class' => 3,
      'name' => 'inoue',
      'age' => 17,
    ),
  ),
)

キーの取得

次はキーを取得する方法を見てみましょう。

配列の全てのキーを取得する

array_keys

https://www.php.net/manual/ja/function.array-keys.php

array_keys (配列)
戻り値:配列

引数に渡した配列の全てのキーを配列にて返します。

php > $fruits_color = [
php >     'apple' => 'red',
php >     'banana' => 'yellow',
php >     'orange' => 'orange',
php >     'cherry' => 'red',
php > ];

php > var_export(array_keys($fruits_color));
array (
  0 => 'apple',
  1 => 'banana',
  2 => 'orange',
  3 => 'cherry',
)

値を指定してキーを取得する

array_keys

https://www.php.net/manual/ja/function.array-keys.php

array_keys (配列, 指定する値, 型比較を行うか)
戻り値:配列

指定した値に該当するキーを取得するにはarray_keysに第2引数を渡して使用します。
第3引数には値を検索する際に厳密な比較===を行うかどうかをtrue,falseで指定します。
常にtrueを指定することをお勧めします。

php > $fruits_color = [
php >     'apple' => 'red',
php >     'banana' => 'yellow',
php >     'orange' => 'orange',
php >     'cherry' => 'red',
php > ];

php > $red_fruits = array_keys($fruits_color, 'red', true);
php > var_export($red_fruits);
array (
  0 => 'apple',
  1 => 'cherry',
)

もし第3引数にtrueを指定しない場合、以下のような想定外の動作をする可能性があります。

php > $numbers = [
php >     'zero' => 0,
php >     'one' => 1,
php >     'two' => 2,
php > ];

// 何も取得されないと思いきや、'zero'が取得される
php > $number = array_keys($numbers, 'a');
php > var_export($number);
array (
  0 => 'zero',
)

第3引数を指定しないと値の検索に緩やかな比較==を行います。
PHPは型が異なる値同士を比較する際に、暗黙的な型変換を行います。
そのため数値と文字列を比較しようとすると、文字列は0に変換されてしまいます。

php > var_export((int) 'a');
0

なので上記のように第2引数に'a'を指定しても、実際には0に変換されてしまうので、'zero'が取得されてしまうのです。
このような想定外の動作はバグを引き起こす可能性があるため、避けるべきでしょう。

値の検索

値を指定して存在するか検索する

array_search

https://www.php.net/manual/ja/function.array-search.php

array_search(検索する値, 配列, 型比較を行うか)
戻り値:キーもしくはfalse

値が見つかった場合、該当のキーを返します。
見つからなかった場合はfalseを返します。

array_keysは値を指定した場合、該当するキーを全て配列で返しますが、array_searchは1つのキーを数値か文字列にて返します。
そのため1つ以上の値が見つかる場合は先に見つかった方のキーを返します。

php > $foods = ['ramen', 'sushi', 'curry', 'udon', 'karaage', 'sushi'];

// 寿司を検索。寿司は2つあるため、前方のキーが取得される。
php > $sushi_key = array_search('sushi', $foods, true);
php > var_export($sushi_key);
1

// ピザを検索。値が見つからないためfalseを返す。
php > $pizza_key = array_search('pizza', $foods, true);
php > var_export($pizza_key);
false

array_searchも第3引数にtrueを指定して厳密な比較を行うようにしましょう。

in_array

https://www.php.net/manual/ja/function.in-array.php

in_array(検索する値, 配列, 型比較を行うか)
戻り値:trueもしくはfalse

使い方はarray_searchと同じですが、値が見つかった場合にキーではなくtrueを返します。
第3引数にはもちろんtrueを指定します。

php > $foods = ['ramen', 'sushi', 'curry', 'udon', 'karaage', 'sushi'];

php > $sushi_key = in_array('sushi', $foods, true);
php > var_export($sushi_key);
true

php > $pizza_key = in_array('pizza', $foods, true);
php > var_export($pizza_key);
false

array_searchin_arrayの使い分けは、
値を検索して存在する場合、その値を用いて何らかの処理をしたい時はarray_search

$key = array_search('val', $list, true);
if ($key !== false) {
    $value = $list[$key];
    ... // 値を使って処理を行う
}

値を検索して存在するかしないかで何らかの処理をしたい場合はin_arrayを使うイメージです。

if (in_array('val', $list, true)) {
    ... // 存在する場合の処理
} else {
    ... // 存在しない場合の処理
}

キーの検索

キーを指定して存在するか検索する

array_key_exists

https://www.php.net/manual/ja/function.array-key-exists.php

array_key_exists (検索するキー, 配列)
戻り値:trueもしくはfalse

第1引数に渡したキーが存在すればtrueを返します。

php > $fruits = [
php >     'name' => 'apple', 'color' => 'red',
php >     'name' => 'banana', 'color' => 'yellow',
php >     'name' => 'melon', 'color' => 'green',
php > ];

php > var_export(array_key_exists('name', $fruits));
true
php > var_export(array_key_exists('price', $fruits));
false

issetemptyを使ってもarray_key_existsと同じようなことができます。

isset

https://www.php.net/manual/ja/function.isset.php

isset (変数)
戻り値:trueもしくはfalse

変数が宣言されていて、かつnullでなければtrueを返します。

php > $fruits = [
php >     'name' => 'apple', 'color' => 'red',
php >     'name' => 'banana', 'color' => 'yellow',
php >     'name' => 'melon', 'color' => 'green',
php > ];

php > var_export(isset($fruits['name']));
true
php > var_export(isset($fruits['price']));
false

empty

https://www.php.net/manual/ja/function.empty.php

empty (変数)
戻り値:trueもしくはfalse

変数が宣言されていないか、空であればtrueを返します。
array_key_existissetとは逆にキーが存在しなければtrueを返します。
同じ使い方をしたい場合は必ず!を付けるようにしましょう。

php > $fruits = [
php >     'name' => 'apple', 'color' => 'red',
php >     'name' => 'banana', 'color' => 'yellow',
php >     'name' => 'melon', 'color' => 'green',
php > ];

php > var_export(!empty($fruits['name']));
true
php > var_export(!empty($fruits['price']));
false

array_key_exists、isset、emptyの違い

array_key_existsはキーが定義されているかどうかのみを判断します。
issetはキーが定義されているか、また値がnullではないかを判断します。
emptyはキーが提起されているか、また値が空ではないかを判断します。

いくつかの違いをまとめると以下のようになります。

key/value array_key_exists isset !empty
'a' => undefined false false false
0 => NULL true false false
1 => '' true true false
2 => 0 true true false
3 => 'val' true true true
// array_key_exists
php > var_export(array_key_exists('a', $list));
false
php > var_export(array_key_exists(0, $list));
true
php > var_export(array_key_exists(1, $list));
true
php > var_export(array_key_exists(2, $list));
true
php > var_export(array_key_exists(3, $list));
true

// isset
php > var_export(isset($list['a']));
false
php > var_export(isset($list[0]));
false
php > var_export(isset($list[1]));
true
php > var_export(isset($list[2]));
true
php > var_export(isset($list[3]));
true

// empty
php > var_export(!empty($list['a']));
false
php > var_export(!empty($list[0]));
false
php > var_export(!empty($list[1]));
false
php > var_export(!empty($list[2]));
false
php > var_export(!empty($list[3]));
true

キーが存在するかチェックしたい場合はarray_key_existsを、
キーが存在して意味のある値が入っていることを確認したい場合はissetemptyを使いましょう。

その他、配列に関する色々

JAVAのstreamぽい書き方もできる

詳細は割愛しますが、JAVAのstreamのように配列の全要素を回しながら処理する色んな関数があります。
array_walk
array_filter
array_map
など

最後の要素の後にはカンマを付ける

これは賛否両論があるようですが
1行で記述する場合は最後にカンマを付けない
複数行で技術する場合は最後にカンマを付ける
が一般的のようです。

PHP公式サイト

配列を一行で定義する場合は、ふつうは最後のカンマを省略します。
つまり、 array(1, 2) のほうが array(1, 2, ) よりおすすめだということです。
しかし複数行で定義する場合は、最後のカンマをつけることが一般的です。
そうしておけば、配列の最後に要素を追加するのが容易になるからです。

Zend framework

we encourage using a trailing comma for the last item in the array; this minimizes the impact of adding new items on successive lines, and helps to ensure no parse errors occur due to a missing comma.

$sampleArray = array(1, 2, 3, 'Zend', 'Studio'); // 最後にカンマを付けない
$sampleArray = array(
    1, 2, 3, 'Zend', 'Studio',
    $a, $b, $c,
    56.44, $d, 500, // 最後にカンマを付ける
);
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【PHP 初級】配列おさらい➁ ~取得・検索・その他~

【PHP 初級】配列おさらい➀ ~宣言・初期化・追加・結合・削除~の続きです。
今回は配列から値を取得、検索する方法など、もう少し実務的な内容をまとめます。

値の取得

配列から値を取り出す色んな方法を見てみます。

キーを指定して値を取り出す

どの言語も同じように、数値やキーを指定して値を取り出します。

php > $fruits = ['apple', 'grape', 'banana'];

php > var_export($fruits[0]);
'apple'
php > $colors = ['C1' => 'red', 'C2' => 'purple', 'C3' => 'green'];

php > var_export($colors['C1']);
'red'

すべての値を取り出す

array_values

https://www.php.net/manual/ja/function.array-values.php

array_values (配列)
戻り値:配列

array_valuesは配列のすべての値を取り出し、数値のインデックス番号を付けた配列を返します。
【PHP 初級】配列おさらい➀ ~宣言・初期化・追加・結合・削除~で紹介したように、配列の値の削除を行った後、インデックス番号を詰め直すのに利用したりします。
またarray_valuesに連想配列を渡せば、配列に変換することが出来ます。

php > $colors = ['C1' => 'red', 'C2' => 'purple', 'C3' => 'green'];

php > var_export(array_values($colors));
array (
  0 => 'red',
  1 => 'purple',
  2 => 'green',
)

多次元配列からキーを指定して値を取り出す

array_column

https://www.php.net/manual/ja/function.array-column.php

array_column (配列, 指定するキー)
戻り値:配列

array_columnは個人的にかなり良く使うメソッドなので、ぜひ使い方を身に付けてみてください。
array_columnは多次元配列のキーを指定し、全ての値を配列で返します。

php > $students = [
php >     ['class' => 1, 'name' => 'tanaka', 'age' => 15],
php >     ['class' => 2, 'name' => 'yamamoto', 'age' => 16],
php >     ['class' => 1, 'name' => 'honda', 'age' => 16],
php >     ['class' => 3, 'name' => 'inoue', 'age' => 17],
php > ];

// 学生の名前を取得
php > $students_name = array_column($students, 'name');
php > var_export($students_name);
array (
  0 => 'tanaka',
  1 => 'yamamoto',
  2 => 'honda',
  3 => 'inoue',
)

また第3引数を指定して、特定の値をキーにした多次元配列を生成することもできます。

array_column (配列, 指定するキー、新しい配列のキーとして指定するキー)
戻り値:配列

言葉が分かりづらいですが、例を見ればすぐに理解できると思います。

php > $students = [
php >     ['class' => 1, 'name' => 'tanaka', 'age' => 15],
php >     ['class' => 2, 'name' => 'yamamoto', 'age' => 16],
php >     ['class' => 1, 'name' => 'honda', 'age' => 16],
php >     ['class' => 3, 'name' => 'inoue', 'age' => 17],
php > ];

// クラス毎に名前を取得する
php > $name_by_class = array_column($students, 'name', 'class');
php > var_export($name_by_class);
array (
  1 => 'honda',
  2 => 'yamamoto',
  3 => 'inoue',
)

注意点はキーが重複する場合、後ろの値で上書きされます。
そのため、クラス1はhondaくんが取得されます。

名前だけでなく、学生の情報が全て取得したい場合は第2引数にnullを指定します。

php > $students = [
php >     ['class' => 1, 'name' => 'tanaka', 'age' => 15],
php >     ['class' => 2, 'name' => 'yamamoto', 'age' => 16],
php >     ['class' => 1, 'name' => 'honda', 'age' => 16],
php >     ['class' => 3, 'name' => 'inoue', 'age' => 17],
php > ];

// クラス毎に学生の情報を取得する
php > $student_by_class = array_column($students, null, 'class');
php > var_export($student_by_class);
array (
  1 =>
  array (
    'class' => 1,
    'name' => 'honda',
    'age' => 16,
  ),
  2 =>
  array (
    'class' => 2,
    'name' => 'yamamoto',
    'age' => 16,
  ),
  3 =>
  array (
    'class' => 3,
    'name' => 'inoue',
    'age' => 17,
  ),
)

こちらもクラス1は重複するため、hondaくんの情報のみ取得されています。

多次元配列のキーでグルーピングする

上書きしないでクラス毎の全員の情報が取得したい場合は、次のような自作メソッドが必要になります。

public function groupBy($list, $key) {
    $ret = array();
    if (is_array($list)) {
        foreach ($list as $val) {
            $ret[$val[$key]][] = $val;
        }
    }

    return $ret;
}

Utilメソッドとして定義し、どこからでも使えるようにしたら良いです。
グルーピングした結果は以下のようになります。

php > $students = [
php >     ['class' => 1, 'name' => 'tanaka', 'age' => 15],
php >     ['class' => 2, 'name' => 'yamamoto', 'age' => 16],
php >     ['class' => 1, 'name' => 'honda', 'age' => 16],
php >     ['class' => 3, 'name' => 'inoue', 'age' => 17],
php > ];

// クラス毎に学生をグループ化する
php > $group_by_class = groupBy($students, 'class');
php > var_export($group_by_class);
array (
  1 =>
  array (
    0 =>
    array (
      'class' => 1,
      'name' => 'tanaka',
      'age' => 15,
    ),
    1 =>
    array (
      'class' => 1,
      'name' => 'honda',
      'age' => 16,
    ),
  ),
  2 =>
  array (
    0 =>
    array (
      'class' => 2,
      'name' => 'yamamoto',
      'age' => 16,
    ),
  ),
  3 =>
  array (
    0 =>
    array (
      'class' => 3,
      'name' => 'inoue',
      'age' => 17,
    ),
  ),
)

キーの取得

次はキーを取得する方法を見てみましょう。

配列の全てのキーを取得する

array_keys

https://www.php.net/manual/ja/function.array-keys.php

array_keys (配列)
戻り値:配列

引数に渡した配列の全てのキーを配列にて返します。

php > $fruits_color = [
php >     'apple' => 'red',
php >     'banana' => 'yellow',
php >     'orange' => 'orange',
php >     'cherry' => 'red',
php > ];

php > var_export(array_keys($fruits_color));
array (
  0 => 'apple',
  1 => 'banana',
  2 => 'orange',
  3 => 'cherry',
)

値を指定してキーを取得する

array_keys

https://www.php.net/manual/ja/function.array-keys.php

array_keys (配列, 指定する値, 型比較を行うか)
戻り値:配列

指定した値に該当するキーを取得するにはarray_keysに第2引数を渡して使用します。
第3引数には値を検索する際に厳密な比較===を行うかどうかをtrue,falseで指定します。
常にtrueを指定することをお勧めします。

php > $fruits_color = [
php >     'apple' => 'red',
php >     'banana' => 'yellow',
php >     'orange' => 'orange',
php >     'cherry' => 'red',
php > ];

php > $red_fruits = array_keys($fruits_color, 'red', true);
php > var_export($red_fruits);
array (
  0 => 'apple',
  1 => 'cherry',
)

もし第3引数にtrueを指定しない場合、以下のような想定外の動作をする可能性があります。

php > $numbers = [
php >     'zero' => 0,
php >     'one' => 1,
php >     'two' => 2,
php > ];

// 何も取得されないと思いきや、'zero'が取得される
php > $number = array_keys($numbers, 'a');
php > var_export($number);
array (
  0 => 'zero',
)

第3引数を指定しないと値の検索に緩やかな比較==を行います。
PHPは型が異なる値同士を比較する際に、暗黙的な型変換を行います。
そのため数値と文字列を比較しようとすると、文字列は0に変換されてしまいます。

php > var_export((int) 'a');
0

なので上記のように第2引数に'a'を指定しても、実際には0に変換されてしまうので、'zero'が取得されてしまうのです。
このような想定外の動作はバグを引き起こす可能性があるため、避けるべきでしょう。

値の検索

値を指定して存在するか検索する

array_search

https://www.php.net/manual/ja/function.array-search.php

array_search(検索する値, 配列, 型比較を行うか)
戻り値:キーもしくはfalse

値が見つかった場合、該当のキーを返します。
見つからなかった場合はfalseを返します。

array_keysは値を指定した場合、該当するキーを全て配列で返しますが、array_searchは1つのキーを数値か文字列にて返します。
そのため1つ以上の値が見つかる場合は先に見つかった方のキーを返します。

php > $foods = ['ramen', 'sushi', 'curry', 'udon', 'karaage', 'sushi'];

// 寿司を検索。寿司は2つあるため、前方のキーが取得される。
php > $sushi_key = array_search('sushi', $foods, true);
php > var_export($sushi_key);
1

// ピザを検索。値が見つからないためfalseを返す。
php > $pizza_key = array_search('pizza', $foods, true);
php > var_export($pizza_key);
false

array_searchも第3引数にtrueを指定して厳密な比較を行うようにしましょう。

in_array

https://www.php.net/manual/ja/function.in-array.php

in_array(検索する値, 配列, 型比較を行うか)
戻り値:trueもしくはfalse

使い方はarray_searchと同じですが、値が見つかった場合にキーではなくtrueを返します。
第3引数にはもちろんtrueを指定します。

php > $foods = ['ramen', 'sushi', 'curry', 'udon', 'karaage', 'sushi'];

php > $sushi_key = in_array('sushi', $foods, true);
php > var_export($sushi_key);
true

php > $pizza_key = in_array('pizza', $foods, true);
php > var_export($pizza_key);
false

array_searchin_arrayの使い分けは、
値を検索して存在する場合、その値を用いて何らかの処理をしたい時はarray_search

$key = array_search('val', $list, true);
if ($key !== false) {
    $value = $list[$key];
    ... // 値を使って処理を行う
}

値を検索して存在するかしないかで何らかの処理をしたい場合はin_arrayを使うイメージです。

if (in_array('val', $list, true)) {
    ... // 存在する場合の処理
} else {
    ... // 存在しない場合の処理
}

キーの検索

キーを指定して存在するか検索する

array_key_exists

https://www.php.net/manual/ja/function.array-key-exists.php

array_key_exists (検索するキー, 配列)
戻り値:trueもしくはfalse

第1引数に渡したキーが存在すればtrueを返します。

php > $fruits = [
php >     'name' => 'apple', 'color' => 'red',
php >     'name' => 'banana', 'color' => 'yellow',
php >     'name' => 'melon', 'color' => 'green',
php > ];

php > var_export(array_key_exists('name', $fruits));
true
php > var_export(array_key_exists('price', $fruits));
false

issetemptyを使ってもarray_key_existsと同じようなことができます。

isset

https://www.php.net/manual/ja/function.isset.php

isset (変数)
戻り値:trueもしくはfalse

変数が宣言されていて、かつnullでなければtrueを返します。

php > $fruits = [
php >     'name' => 'apple', 'color' => 'red',
php >     'name' => 'banana', 'color' => 'yellow',
php >     'name' => 'melon', 'color' => 'green',
php > ];

php > var_export(isset($fruits['name']));
true
php > var_export(isset($fruits['price']));
false

empty

https://www.php.net/manual/ja/function.empty.php

empty (変数)
戻り値:trueもしくはfalse

変数が宣言されていないか、空であればtrueを返します。
array_key_existissetとは逆にキーが存在しなければtrueを返します。
同じ使い方をしたい場合は必ず!を付けるようにしましょう。

php > $fruits = [
php >     'name' => 'apple', 'color' => 'red',
php >     'name' => 'banana', 'color' => 'yellow',
php >     'name' => 'melon', 'color' => 'green',
php > ];

php > var_export(!empty($fruits['name']));
true
php > var_export(!empty($fruits['price']));
false

array_key_exists、isset、emptyの違い

array_key_existsはキーが定義されているかどうかのみを判断します。
issetはキーが定義されているか、また値がnullではないかを判断します。
emptyはキーが提起されているか、また値が空ではないかを判断します。

いくつかの違いをまとめると以下のようになります。

key/value array_key_exists isset !empty
'a' => undefined false false false
0 => NULL true false false
1 => '' true true false
2 => 0 true true false
3 => 'val' true true true
// array_key_exists
php > var_export(array_key_exists('a', $list));
false
php > var_export(array_key_exists(0, $list));
true
php > var_export(array_key_exists(1, $list));
true
php > var_export(array_key_exists(2, $list));
true
php > var_export(array_key_exists(3, $list));
true

// isset
php > var_export(isset($list['a']));
false
php > var_export(isset($list[0]));
false
php > var_export(isset($list[1]));
true
php > var_export(isset($list[2]));
true
php > var_export(isset($list[3]));
true

// empty
php > var_export(!empty($list['a']));
false
php > var_export(!empty($list[0]));
false
php > var_export(!empty($list[1]));
false
php > var_export(!empty($list[2]));
false
php > var_export(!empty($list[3]));
true

キーが存在するかチェックしたい場合はarray_key_existsを、
キーが存在して意味のある値が入っていることを確認したい場合はissetemptyを使いましょう。

その他、配列に関する色々

JAVAのstreamぽい書き方もできる

詳細は割愛しますが、JAVAのstreamのように配列の全要素を回しながら処理する色んな関数があります。
array_walk

array_walk (配列, コールバック関数, コールバック関数の引数)
戻り値:true

配列を回してコールバック関数の処理を行います。
コールバック関数に渡す第1引数は配列の値、第2引数は配列のキーになります。
コールバック関数で第3引数を使用したい場合はarray_walkに第3引数を指定します。
JAVAのstream.forEachみたいなイメージです。

array_filter

array_filter (配列, コールバック関数, モード)
戻り値:配列

配列を回してコールバック関数でフィルタリングした結果を配列で返します。
第3引数ではコールバック関数に何を引数として渡すかを指定します。
デフォルトだと配列の値を引数として渡します。
JAVAのstream.filterに値します。

array_map

array_map (コールバック関数, 配列...)
戻り値:配列

配列を回してコールバック関数の処理を行います。
コールバック関数の処理を通った結果を配列で返します。
コールバック関数に引数で渡す配列は複数指定することが出来ます。
JAVAのstream.mapに似ています。

最後の要素の後にはカンマを付ける

これは賛否両論があるようですが
1行で記述する場合は最後にカンマを付けない
複数行で技術する場合は最後にカンマを付ける
が一般的のようです。

PHP公式サイト

配列を一行で定義する場合は、ふつうは最後のカンマを省略します。
つまり、 array(1, 2) のほうが array(1, 2, ) よりおすすめだということです。
しかし複数行で定義する場合は、最後のカンマをつけることが一般的です。
そうしておけば、配列の最後に要素を追加するのが容易になるからです。

Zend framework

we encourage using a trailing comma for the last item in the array; this minimizes the impact of adding new items on successive lines, and helps to ensure no parse errors occur due to a missing comma.

$sampleArray = array(1, 2, 3, 'Zend', 'Studio'); // 最後にカンマを付けない
$sampleArray = array(
    1, 2, 3, 'Zend', 'Studio',
    $a, $b, $c,
    56.44, $d, 500, // 最後にカンマを付ける
);
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【PHP】初中級者が解くべき過去問精選 100 問を解いてみた【3問目/100】

アルゴリズムのアウトプット

ということで、
レッドコーダーが教える、競プロ・AtCoder上達のガイドライン【中級編:目指せ水色コーダー!】@e869120さん

AtCoder で水色コーダー、つまりレーティング 1200 を少ない問題数で達成するために、茶色コーダー・緑コーダーにとって適切な教育的良問を 100 問集めました。

こちらの記事の初中級者が解くべき過去問精選 100 問
をPHPで解いていきます。

<?php

while (true) {
<?php

$wordArr = str_split(trim(fgets(STDIN)));
$num = count($wordArr);
$max = 0;
$count = 0;
$acgt = ['A', 'C', 'G', 'T'];
for ($i = 0; $i < $num; $i++) {
    if (in_array($wordArr[$i], $acgt)) {
        $count++;
        $max = max($count, $max);
    } else {
        $count = 0;
    }
}

echo $max;
}

文字列を配列化し順番に該当する文字かどうか判定。
連続している間は足し上げていき、対象出ない場合はcountをリセットする問題。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【PHP】初中級者が解くべき過去問精選 100 問を解いてみた【2問目/100】

アルゴリズムのアウトプット

ということで、
レッドコーダーが教える、競プロ・AtCoder上達のガイドライン【中級編:目指せ水色コーダー!】@e869120さん

AtCoder で水色コーダー、つまりレーティング 1200 を少ない問題数で達成するために、茶色コーダー・緑コーダーにとって適切な教育的良問を 100 問集めました。

こちらの記事の初中級者が解くべき過去問精選 100 問
をPHPで解いていきます。

<?php

$num = trim(fgets(STDIN));
$answer = 0;
for ($i = 1; $i <= $num; $i++) {
    if ($i % 2 == 0) {
        continue;
    }
    $count = 0;
    for ($j = 1; $j <= $num; $j++) {
        if ($i % $j == 0) {
            $count++;
        }
    }
    if ($count == 8) {
        $answer++;
    }
}

echo $answer;

}

偶数のときはガード節使って計算量を減らすようにした。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【PHP】初中級者が解くべき過去問精選 100 問を解いてみた【1問目/100】

アルゴリズムのアウトプット

ということで、
レッドコーダーが教える、競プロ・AtCoder上達のガイドライン【中級編:目指せ水色コーダー!】@e869120さん

AtCoder で水色コーダー、つまりレーティング 1200 を少ない問題数で達成するために、茶色コーダー・緑コーダーにとって適切な教育的良問を 100 問集めました。

こちらの記事の初中級者が解くべき過去問精選 100 問
をPHPで解いていきます。

<?php

while (true) {
    $s = trim(fgets(STDIN));
    $s = str_replace(array("\r\n","\r","\n"), '', $s);
    $s = explode(" ", $s);
    $n = $s[0];
    $x = $s[1];
    if ($n == 0 && $x == 0) {
        break;
    }
    $ans = 0;
    for ($i = 1; $i <= $n; $i++) {
        for ($j = 1; $j <= $n; $j++) {
            for ($k = 1; $k <= $n; $k++) {
                if ($i < $j && $j < $k && $i + $j +$k == $x) {
                    $ans++;
                }
            }
        }
    }
    echo $ans . "\n";
}

典型的な全列挙の問題。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【超初心者編】PHP7×MySQL、PDOを使用してDB(データーベース)に接続する方法

データベースとの接続は、初心者にとって「最初の壁」

こんにちは、自分はPHPを勉強して2ヶ月目の初心者です。
今回は自分用のメモと記憶整理としてデーターベース(以降:DB)との接続方法を超簡単に説明します。

環境は以下の通り
・MAMP6.2
・PHP7.4.9
・MySQL 5.7.30

【注意】初心者の解説なので、専門的に学習したい人は他の学習用のサイト・ページなどを参考にしてください!

MySQLとPDOについて

MySQLはオープンソースのDB(データベース)管理システムです。

(オープンソースとは商用、非商用を問わず配布されてるもの)
・無償で利用できる
・大容量のデーターを高速で動作させられる
・幅広いOSに対応している(Windows,mac,Linuxなど)

上記は特徴の一部に過ぎません。
優秀なシステムで実際に世界中の企業でも使用されています。

PDOとは?

PDO(PHP Data Objects)とは、
PHPからDBへアクセスする機能を持った拡張モジュールです。

なにやら難しそうですが、とりあえずDBへアクセする為の便利な機能だと思ってもらえれば、今回は大丈夫です!

接続する方法

それでは、接続方法を解説していきます。
先づはDBに接続するSQL文を用意します。

~phpMyAdmin上の表記以下と仮定~
Sever:localhost8889
ユーザー名:root
パスワード:root

DB接続用のSQL文を作成

PHP7
$sql = 'mysql:dbname=test;host=localhost;port=8889;charset=utf8';
$user = 'root';
$pass = 'root';

変数sqlにDB接続用のsql文を代入して、
dbname、host、portの各所にDBの情報を入力します。

最後のcharasetの所は、文字コードをUTF-8に指定しています。

変数userとpassにはユーザー名とパスワードを入力してください。

PDOを使いSQL文を$dbhに代入する

$dbh = new PDO($sql,$user, $id);

$dbhにPDOを使い、先程の変数を組み合わせる。

例外処理を追加

もしDBとの接続が出来なかった場合、エラー文を表示する様に
try(例外処理)を追加します。

try {
 $dbh = new PDO($sql,$user,$id);
} catch(PDOException $e) {
  echo('DB接続エラー:' . $e->getMessage());
}

これによりDBと接続出来なかった時、cath内の'DB接続エラー'とエラー文が表示されるようになります。

まとめ

MySQLなどDBの世界は本当に奥が深く、覚える事が多く難しいです。
そんな中、少しでも分かりやすく記録できたらと思い投稿させていただきました。

今回はDBの接続方法のみですが、今後SELECTやINSERT、内部結合についても取り上げられたらと思います。
少しでもお役に立てたら幸いです!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【PHP】Docker環境にphpMyadminを導入する

手順

docker-compose.ymlにphpMyadominのコンテナを追記します。

docker-compose.yml
#docker-compose.ymlのバージョン
version: "3.8"
#docker volumeの設定
volumes:
  docker-volume:

#services以下に各コンテナの設定を書く
services:
  #Webサーバーのコンテナ
  web:
    image: nginx:1.18
    ports:
      - "8000:80"
    depends_on:
      - app
    volumes:
      - ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
      - .:/var/www/html
  #アプリケーションのコンテナ
  app:
    build: ./docker/php
    volumes:
      - .:/var/www/html
  #データベースのコンテナ
  db:
    image: mysql:5.7
    ports:
      - "3306:3306"
    environment:
      MYSQL_DATABASE: db_name
      MYSQL_USER: db_user
      MYSQL_PASSWORD: db_password
      MYSQL_ROOT_PASSWORD: root
      TZ: "Asia/Tokyo"
    volumes:
      - docker-volume:/var/lib/mysql
  # phpMyadominのコンテナ作成
  phpmyadmin:
    image: phpmyadmin/phpmyadmin
    depends_on:
      - db
    environment:
      - PMA_ARBITRARY=1
      - PMA_HOSTS=db
      - PMA_USER=db_user
      - PMA_PASSWORD=db_password
    ports:
      - "8080:80"
    volumes:
      - ./docker/phpmyadmin/sessions:/sessions

コードの下部にある# phpMyadominのコンテナ作成からが追記する箇所です。
portsを8080に設定しているので、localhost:8080でphpmyadminの管理画面にアクセスできるように設定しています。
また、volumesにある./docker/phpmyadmin/sessions:/sessionsではセッション情報をボリュームに設定して永続化するようにします。

補足

参考までに作ってみた環境

https://github.com/yuyaamano23/Laravel_Docker_practice/tree/github-open




ちなみに僕は以下の記事を参考にphp+mysql+nginxの環境を構築しました。神記事です。:relaxed:
絶対に失敗しないDockerでLaravel+Vueの実行環境(LEMP環境)を構築する方法〜前編〜
絶対に失敗しないDockerでLaravel6.8+Vueの実行環境(LEMP環境)を構築する方法〜後編〜
Docker Composeでphpmyadminを導入する

各々構築したDocker環境のプロジェクトにあるdocker-compose.ymlnに追記していただければ良いと思います。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

PHPで突如現れた「? : 」に、なんそれ!となった頃の話

めちゃめちゃ初心者だった頃、PHP Laravelでの業務中に、
先輩が書いたコードで突如現れた「? : 」に、なんそれ!となりました。

開発言語がPHPなので、
「PHP ? : 」とかでググってみても、いまいちHITしなくて困った記憶があり、
同じ様な人がいるかもしれないので、記事にしてみました。

早速「? : 」の正体ですが、条件演算子の中の『三項演算子』です。

AAA ? BBB : CCC

この形、

AAA が「true」なら BBB 、「false」なら CCC

ということになります。

初心者だった頃の私は、この条件分岐なら全部if文で書いてました。

example.php
if ( AAA ) {
    BBB
} else {
    CCC
}

どっちが見やすいか、一目で分かりやすいか、と言われると、
定義する値によるため、場合によって書き分ける必要があります。

条件や分岐後に定義したい内容が変数だけとかの短いものは、
「AAA ? BBB : CCC」の形がスマートだなと思います。

条件演算子『三項演算子』については、PHPマニュアルにて確認しました。
https://www.php.net/manual/ja/language.operators.comparison.php

最後に

この記事が「PHP ? : 」とかでググった時に出ると良いなぁと思いながら書きました。
どうなんでしょうね…届けこの想い…!

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Laravel5.5】キャッシュクリアコマンドと、まとめて実行する方法

Laravel5.5使用時の例です。
ファイルの変更を反映した後、実行しておきたいキャッシュクリアコマンド。

php artisan cache:clear

→「storage/framework/cache/data」内のキャッシュデータを削除する。

php artisan view:clear

→「storage/framework/views」内に全ビューのキャッシュデータを削除する。

php artisan config:clear

→「config」ディレクトリのファイルの更新内容が反映されるようになる。

php artisan route:clear

→「bootstrap/cache/routes.php」のRouteのキャッシュデータを削除する。

※ 各コマンドで何しているかは、
https://blog.capilano-fw.com/?p=768 より引用しました。
こちらのサイトにはとてもお世話になっております。感謝永遠に。。

まとめて実行するには…

systemディレクトリ直下にシェルスクリプトを作成する。

clear_cache.sh
php artisan cache:clear
php artisan view:clear
php artisan config:clear
php artisan route:clear

//最後に改行を入れる

上記では「clear_cache.sh」というファイル名にしているので、
systemディレクトリにいる状態で、
下記のコマンドでまとめて実行することができる。

sh clear_cache.sh

楽。よき。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

PHPの最低限必要スキルのメモ

・条件分岐やループ処理ができる(itやfor)

・共通処理は関数化できる

・オブジェクト指向プログラミングが簡単にできる

クラスとインスタンス、継承、カプセル、ポリモーフィズムを理解し、使いこなせる

・データベースに対して、CRUD操作ができる

create, read, update, delete

・セッションやクッキーを扱い、ステートフルなプログラムを実装できる

・ログインとログアウト機能を実装できる

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む