2023.09.15
【Phalcon】基本のCRUD

Unsplashniko photosが撮影した写真

はじめに

この記事ではPhalconを触り始めたばかりの方に向けて、基本のCRUDのコードをまとめています。

DBとテーブルの作成、PhalconとDBの接続からやっていきますので、初めてPhalconでDBを扱う方にもわかりやすい内容になっているかと思います。

動作確認した環境

OS:Windows11 Home / WSL(Ubuntu20.04)
php:v7.4.33
phalcon:4.0.6
Phalcon DevTools:v4.2.0
DB:mysql v8.0.34

前提

新規プロジェクト作成済みであること。

もしプロジェクトの作成方法がわからない場合には次のリンク先ページを参考に作成してください。
【Phalcon】新規プロジェクト作成~HelloWorld

この記事でやること

ユーザー管理用のUsersテーブルについて、以下のアクションとビューをつくります。

・index:ユーザー一覧
・show:ユーザー情報詳細
・add:新規追加
・edit:編集
・delete:削除  ※deleteはビューを作らず、アクションのみ作成します。

事前準備

CRUD処理を書き始める前に必要なものを整えていきます。

①DBとUsersテーブルを作成する

まず、データベースとUsersテーブルを作成します。

コマンドプロンプトでMySQLにログインします。
下のコマンドを打ち、パスを入力するとログインできます。

mysql -u [ユーザ名] -p
例)mysql -u root -p

以下のコマンドでデータベースを作成します。

CREATE DATABASE [DB名] DEFAULT CHARACTER SET utf8mb4;
例)CREATE DATABASE testdb DEFAULT CHARACTER SET utf8mb4;

作成したDBに移動します。

USE [DB名]
例)USE testdb

次に、Usersテーブルを作成します。

CREATE TABLE users(
id serial primary key,
name varchar(20) not null,
password varchar(100) not null
);

テーブルが作成できか確認してみます。

show tables;

と打ち込み以下のように表示されたらテーブルが作成されています。

mysql> show tables;
+---------------------+
| Tables_in_testdb    |
+---------------------+
| users               |
+---------------------+
1 row in set (0.00 sec)

②DB接続

次にDBとPhalconをつなぎます。

Phalconの設定ファイル「/app/config/config.php」を以下のように書き換えます。

[対象ファイル:/app/config/config.php]
~~省略~~
'database' => [
        'adapter'     => 'Mysql',
        'host'        => '127.0.0.1',  //環境によってはlocalhostではエラーになる
        'username'    => '[MySQLのユーザー名]',
        'password'    => '[MySQLのログインパスワード]',
        'dbname'      => 'testdb',  //←DB名
        'charset'     => 'utf8',
    ],
~~省略~~

③モデルを作成する

以下のコマンドでモデルを作成します。

phalcon model [テーブル名]
例)phalcon model users

※正常にモデルが作成されれば「/app/models」にモデルが作成される

※ここでエラーが出たら概ね「②DB接続」で失敗しています。
 「ERROR:SQLSTATE[HY000] [1045]Access denied for user ~~」
  ⇒usernameかpasswordが間違っています。

 「ERROR:SQLSTATE[HY000] [1049]Unknown database ~~」
  ⇒dbnameが間違っています。

④コントローラを作成する

以下のコマンドでコントローラを作成します。

phalcon create-controller --name [コントローラ名] --base-class=ControllerBase
例)phalcon create-controller --name users --base-class=ControllerBase

コマンドを実行すると「/app/controllers/UsersController.php」が作成されます。

⑤Viewを作成する

Viewはコマンドではなく「マウス右クリック > 新規作成」で地道に作ります。

1つのディレクトリ「users」と4つのファイル「index.phtml、show.phtml、add.phtml、edit.phtml」を以下の場所に作成してください。

【ディレクトリ作成場所】

/app/views/users

【ファイル作成場所】

/app/views/users/index.phtml
/app/views/users/show.phtml
/app/views/users/add.phtml
/app/views/users/edit.phtml

⑥ルーティング

これから以下の5つのアクションを作成するので、ルーティングはまとめて記述しておきます。

・indexAction
・showAction
・addAction
・editAction
・deleteAction

ルーティングを書き込むファイルは「/app/config/router.php」です。

<?php
$router = $di->getRouter();

// Define your routes here
$router->add("/users/index", "Users::index");   //追記
$router->add("/users/show", "Users::show");   //追記
$router->add("/users/add", "Users::add");    //追記
$router->add("/users/edit", "Users::edit");   //追記
$router->add("/users/delete", "Users::delete"); //追記

$router->handle($_SERVER['REQUEST_URI']);

以上でCRUDの事前準備は終わりです!

続いてCRUD画面と処理を作成していきます。

index:ユーザー一覧画面の作成

さっそくユーザー一覧画面から作成していきます。

以下の赤字部分を追記してください。

[対象ファイル:/app/controllers/UsersController.php]

<?php
declare(strict_types=1);

class UsersController extends ControllerBase
{
    public function indexAction(){
        //Usersテーブルから全レコード取得
        $users = Users::find();

        //Viewに値を渡す
        $this->view->users = $users;
    }
}

Viewは以下のように記述してください。

[対象ファイル:/app/views/users/index.phtml]

<h2>users/index</h2>

<div>
    <a href="/users/add">ユーザーの新規登録</a>
</div>

<table border="1" cellpadding="10px">
    <?php foreach($users as $user): ?>
        <tr>
            <td><?= $user->name ?></td>
            <td><a href="/users/show?user_id=<?=$user->id?>">show</a></td>
            <td><a href="/users/edit?user_id=<?=$user->id?>">edit</a></td>
            <td><a href="/users/delete?user_id=<?=$user->id?>">delete</a></td>
        </tr>
    <?php endforeach; ?>
</table>

書き終わったら以下コマンドでphalconを起動してください。

phalcon serve

次にブラウザで「http://localhost:8000/users/index」にアクセスしてみてください。

まだデータを作成していないので、このような表示になっているはずです。

indexページが正常に動作しているかはデータが無いと確認できないので、次に進みます。

show:ユーザー詳細画面

index同様にControllerとViewのコードを書いていきます。

以下の赤字部分を追記してください。

[対象ファイル:/app/controllers/UsersController.php]

<?php
declare(strict_types=1);

class UsersController extends ControllerBase
{

    public function indexAction()
{
        ~~省略~~
    }

    public function showAction()
{
        //user_idで特定のレコードを取得
        $user = Users::findFirst("id = {$_GET['user_id']}");
        $this->view->user = $user;
    }
}

Viewは以下のように記述してください。

[対象ファイル:/app/views/users/show.phtml]

<h2>users/show</h2>

<p>user_id:<?=$user->id?></p>
<p>name:<?=$user->name?></p>
<p>password:<?=$user->password?></p>

showもデータが無いと動作確認できないので、動作確認せず次に進みます。

add:ユーザーの新規登録

addも同様にControllerとViewのコードを書いていきます。

赤字が追記部分です。

[対象ファイル:/app/controllers/UsersController.php]

<?php
declare(strict_types=1);

class UsersController extends ControllerBase
{
    public function indexAction(){
        ~~省略~~
    }

    public function showAction(){
        ~~省略~~
    }

    public function addAction(){

        //POSTされた時の処理
        if($_POST['operation'] == 'send'){
            $user = new Users(); 

            //nameカラムに値をセット                   
            $user->name = $_POST['name'];

            //passwordカラムに値をセット           
            $user->password = $_POST['password'];   

            if($user->save()){
                //成功時の処理
                return $this->response->redirect("users/index");
            }else{
                //失敗時の処理:エラーメッセージをViewに渡す
                $this->view->errorMessages = $user->getMessages();
            }
        }
    }
}

Viewは以下のように記述してください。

[対象ファイル:/app/views/users/add.phtml]

<h2>users/add</h2>

<?php
    if(!empty($errorMessages)){
        foreach($errorMessages as $message){
            echo "<p style='color:red;'>{$message}</p>";
        }
    }
?>

<form action="#" method="post">
    <p><label for="name">氏名</label></p>
    <p><input type="text" name="name"></p>

    <p><label for="password">パスワード</label></p>
    <p><input type="text" name="password"></p>

    <button type="submit" name="operation" value="send">登録</button>
</form>

コードを書いたら、addでユーザーを登録し、index、showの画面が正常に動作しているか確認してみてください。

edit:ユーザー情報の編集

editも同様にControllerとViewのコードを書いていきます。

赤字が追記部分です。

[対象ファイル:/app/controllers/UsersController.php]

<?php
declare(strict_types=1);

class UsersController extends ControllerBase
{

    public function indexAction(){
        ~~省略~~
    }

    public function showAction(){
        ~~省略~~
    }

    public function addAction(){
        ~~省略~~
    }

    public function editAction(){
        $user = Users::findFirst("id = {$_GET['user_id']}");
        $this->view->user = $user;

        //POSTされた時の処理
        if($_POST['operation'] == "send"){
            $user = new Users();
            $user->id = $_POST['id'];
            $user->name = $_POST['name'];
            $user->password = $_POST['password'];

            if($user->save()){
                //成功時の処理
                return $this->response->redirect("users/index");
            }else{
                //失敗時の処理:エラーメッセージをViewに渡す
                $this->view->errorMessages = $user->getMessages();
            }
        }
    }
}

Viewは以下のように記述してください。

[対象ファイル:/app/views/users/edit.phtml]

<h2>users/edit</h2>

<?php
    if(!empty($errorMessages)){
        foreach($errorMessages as $message){
            echo "<p style='color: red;'>{$message}</p>";
        }
    }
?>

<form action="#" method="post">
    <input type="hidden" name="id" value="<?=$user->id?>">

    <p><label for="name">氏名</label></p>
    <p><input type="text" name="name" value="<?=$user->name?>"></p>

    <p><label for="password">パスワード</label></p>
    <p><input type="text" name="password" value="<?=$user->password?>"></p>

    <button type="submit" name="operation" value="send">登録</button>
</form>

delete:ユーザーの削除

今回はdelete用のViewを作成せず、Controllerにアクションを追加するだけです。

以下の赤字部分を追記してください。

<?php
declare(strict_types=1);

class UsersController extends ControllerBase
{
    public function indexAction(){
        ~~省略~~
    }

    public function showAction(){
        ~~省略~~
    }
    public function addAction(){
        ~~省略~~
    }
    public function editAction(){
        ~~省略~~
    }
    public function deleteAction(){
        $user = Users::findFirst("id = {$_GET['user_id']}");
        $result = $user->delete();

        return $this->response->redirect('/users/index');
    }
}

画面の完成形

これでCRUDができるようになったので、ブラウザで動作を確認してみてください。

画面はそれぞれこんな感じになります。