首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

Agavi MVC 框架實戰 (三-1):管理後台、CRUD 操作、認證授權與安全控制

     編輯:PHP 綜合知識

本章目標

  • 建立管理後台模組 (Admin)
  • 實現 Listing 的 **Create/Edit/Delete** 完整 CRUD
  • 引入 **認證 (Authentication)** 與 **授權 (Authorization)**:區分銷售商與管理員
  • 自訂母版頁區分前後台風格

建立 Admin 模組與認證基礎

./bin/agavi module-create
# Module name: Admin

# 建立登入 Action
./bin/agavi action-wizard
# Module: Admin
# Action: Login
# Views: Input Error Success

用戶 Entity 與角色

<?php
// app/lib/Entity/User.php
use Doctrine\ORM\Mapping as ORM;

/**
 * @ORM\Entity
 * @ORM\Table(name="admin_user")
 */
class User
{
    /** @ORM\Id @ORM\GeneratedValue @ORM\Column(type="integer") */
    private $id;

    /** @ORM\Column(type="string", length=50, unique=true) */
    private $username;

    /** @ORM\Column(type="string", length=255) */
    private $passwordHash;

    /** @ORM\Column(type="string", length=20) */
    private $role; // 'dealer' | 'admin'

    public function getId(): int { return $this->id; }
    public function getUsername(): string { return $this->username; }
    public function getRole(): string { return $this->role; }
    public function checkPassword(string $plain): bool {
        return password_verify($plain, $this->passwordHash);
    }
    public function setPassword(string $plain): void {
        $this->passwordHash = password_hash($plain, PASSWORD_DEFAULT);
    }
}

登入 Action

<?php
// app/modules/Admin/actions/LoginAction.class.php
class Admin_LoginAction extends AgaviAction
{
    public function execute(AgaviRequestDataHolder $rd)
    {
        if ($rd->getParameter('login')) {
            $username = $rd->getParameter('username');
            $password = $rd->getParameter('password');

            $em = DoctrineHelper::getEntityManager();
            $user = $em->getRepository('User')->findOneBy(['username' => $username]);

            if ($user && $user->checkPassword($password)) {
                // 寫入 Session
                $this->getContext()->getSession()->setAttribute('admin_user', [
                    'id'       => $user->getId(),
                    'username' => $user->getUsername(),
                    'role'     => $user->getRole(),
                ]);
                return 'Success';
            }
            $this->setAttribute('error', '帳號或密碼錯誤');
            return 'Error';
        }
        return 'Input';
    }

    public function validate(AgaviValidator $validator)
    {
        $validator->addRule('username', new AgaviRequiredValidator());
        $validator->addRule('password', new AgaviRequiredValidator());
    }
}

認證過濾器 (Filter) - 保護所有 Admin Action

<?php
// app/modules/Admin/filters/AuthFilter.class.php
class Admin_AuthFilter extends AgaviFilter
{
    public function execute(AgaviFilterChain $chain)
    {
        $session = $this->getContext()->getSession();
        $user = $session->getAttribute('admin_user');

        // 登入頁、靜態資源放行
        $actionName = $this->getContext()->getController()->getActionName();
        if (in_array($actionName, ['Login', 'Logout'])) {
            return $chain->execute();
        }

        if (!$user) {
            // 未登入 → 導向登入頁
            $this->getContext()->getController()->redirect('admin.login');
            return;
        }

        // 可選:角色授權檢查
        $requiredRole = $this->getParameter('required_role');
        if ($requiredRole && $user['role'] !== $requiredRole) {
            throw new AgaviSecurityException('權限不足');
        }

        return $chain->execute();
    }
}

註冊過濾器 (app/modules/Admin/config/filters.xml)

<?xml version="1.0" encoding="UTF-8"?>
<ae:configurations xmlns:ae="https://agavi.org/agavi/config/global/envelope/1.0"
                   xmlns="https://agavi.org/agavi/config/parts/filter/1.0">
  <ae:configuration>
    <filters>
      <filter name="auth" class="Admin_AuthFilter">
        <parameters>
          <parameter name="required_role">admin</parameter>
        </parameters>
      </filter>
    </filters>
    <filter-mappings>
      <filter-mapping filter="auth" pattern="^admin\." />
    </filter-mappings>
  </ae:configuration>
</ae:configurations>

自訂 Admin 母版頁 (app/templates/AdminMaster.php)

<?php // app/templates/AdminMaster.php ?>
<!DOCTYPE html>
<html><head>
  <meta charset="utf-8">
  <title><?= $t->getAttribute('_title', 'Admin') ?> - WASP Admin</title>
  <link rel="stylesheet" href="<?= $ro->getBaseHref() ?>/css/admin.css">
</head><body>
  <header>
    <h1><img src="<?= $ro->getBaseHref() ?>/images/logo-admin.png" alt="WASP Admin"></h1>
    <nav><a href="<?= $ro->gen('admin.dashboard') ?>">儀表板</a> | <a href="<?= $ro->gen('admin.logout') ?>">登出</a></nav>
  </header>
  <main><?= $inner ?></main>
  <footer>Powered by Agavi</footer>
</body></html>

View 指定母版頁

<?php
// app/modules/Admin/views/DashboardSuccessView.class.php
class Admin_DashboardSuccessView extends AgaviHtmlView
{
    public function setupHtml()
    {
        $this->setLayout('AdminMaster'); // 關鍵:指定後台母版
    }
}

Create/Edit/Delete Action 概略

ActionHTTP MethodView關鍵邏輯
CreateActionGET/POSTInput/SuccessPOST 時驗證 → 建立 Entity → persist → flush → 導向列表
EditActionGET/POSTInput/SuccessGET 讀取 Entity 填充表單;POST 更新欄位 → flush
DeleteActionPOSTSuccessCSRF 驗證 → find Entity → remove → flush → JSON 回應 (AJAX)

下一步

下一篇將實作 **Create/Edit 表單的詳細驗證、檔案上傳 (車輛圖片)、列表分頁排序、搜尋功能**,並示範如何輸出 **JSON/XML/RSS** 多格式 API。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved