php项目 学生管理 MVC模式

前言

在原来的原生PHP上在用MVC来写项目复习一下。不过大家注意,自己写的MVC肯定是拿来学习的,不要想着拿来做项目。

项目介绍

学生管理(添加、查看、编辑、删除学生信息)

简单路由(通过 Router 类处理)。

基本的输入验证(防止 SQL 注入、XSS)。

使用 PDO 连接 MySQL。

简洁的 Bootstrap 界面。

文件结构

mvc-php-mysql/
├── app/
│   ├── Controllers/
│   │   └── StudentController.php
│   ├── Models/
│   │   └── Student.php
│   ├── Views/
│   │   ├── students/
│   │   │   ├── index.php
│   │   │   ├── create.php
│   │   │   └── edit.php
│   │   └── layout.php
│   └── Router.php
├── public/
│   ├── index.php
│   ├── .htaccess
│   └── assets/
│       └── bootstrap.min.css
├── vendor/
├── composer.json
└── .env

项目搭建

Composer初始化
{
    "name": "yyf/mvc-php-mysql",
    "description": "A simple PHP MVC project with MySQL for student management",
    "autoload": {
        "psr-4": {
            "App\\": "app/"
        }
    },
    "authors": [
        {
            "name": "yyf"
        }
    ],
    "require": {
        "php": ">=7.4",
        "ext-pdo_mysql": "*",
        "vlucas/phpdotenv": "^5.5"
    }
}
创建 .env 文件(根目录):
DB_HOST=localhost
DB_NAME=your_database_name
DB_USER=your_username
DB_PASS=your_password

这里大家换上自己的配置

创建数据库和表:
CREATE TABLE students (
  id int(11) NOT NULL AUTO_INCREMENT,
  name varchar(50) NOT NULL,
  age int(11) NOT NULL,
  gender enum('M','F') NOT NULL,
  class varchar(20) NOT NULL,
  email varchar(100) DEFAULT NULL,
  created_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (id),
  UNIQUE KEY email (email)
) ENGINE=MyISAM AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;

INSERT INTO students (NAME, age, gender, class, email) VALUES
('张伟', 20, 'M', 'Class A', 'zhangwei@example.com'),
('李娜', 19, 'F', 'Class B', 'lina@example.com'),
('王强', 21, 'M', 'Class A', 'wangqiang@example.com'),
('赵丽', 20, 'F', 'Class C', 'zhaoli@example.com');
数据库

创建app/Database.php

<?php
namespace App;

use PDO;
use PDOException;
use Dotenv\Dotenv;

class Database {
    private $pdo;

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

        $dsn = "mysql:host={$_ENV['DB_HOST']};dbname={$_ENV['DB_NAME']};charset=utf8";
        try {
            $this->pdo = new PDO($dsn, $_ENV['DB_USER'], $_ENV['DB_PASS']);
            $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        } catch (PDOException $e) {
            die("Connection failed: " . $e->getMessage());
        }
    }

    public function getPdo() {
        return $this->pdo;
    }
}
路由类

创建app/Router.php

<?php
namespace App;

class Router {
    private $routes = [];

    public function get($path, $callback) {
        $this->routes['GET'][$path] = $callback;
    }

    public function post($path, $callback) {
        $this->routes['POST'][$path] = $callback;
    }

    public function dispatch() {
        $uri = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);
        $method = $_SERVER['REQUEST_METHOD'];

        foreach ($this->routes[$method] ?? [] as $path => $callback) {
            $pattern = preg_replace('#\{[\w]+\}#', '(\d+)', $path);
            $pattern = "#^" . $pattern . "$#";

            if (preg_match($pattern, $uri, $matches)) {
                array_shift($matches);
                [$controller, $method] = $callback;
                $instance = new $controller();
                return call_user_func_array([$instance, $method], $matches);
            }
        }

        http_response_code(404);
        echo "404 Not Found";
    }
}
入口文件

创建public/index,php

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

use App\Router;
use App\Controllers\StudentController;

$router = new Router();

$router->get('/', [StudentController::class, 'index']);
$router->get('/index', [StudentController::class, 'index']);
$router->get('/create', [StudentController::class, 'create']);
$router->post('/create', [StudentController::class, 'create']);
$router->get('/edit/{id}', [StudentController::class, 'edit']);
$router->post('/edit/{id}', [StudentController::class, 'edit']);
$router->get('/delete/{id}', [StudentController::class, 'delete']);

$router->dispatch();

学生管理

学生模型

创建app/Models/student.php

<?php
namespace App\Models;

use App\Database;
use PDO;

class Student {
    private $db;

    public function __construct() {
        $this->db = (new Database())->getPdo();
    }

    public function getAll() {
        $stmt = $this->db->query("SELECT * FROM students");
        return $stmt->fetchAll(PDO::FETCH_ASSOC);
    }

    public function create($data) {
        $sql = "INSERT INTO students (name, age, gender, class, email) VALUES (:name, :age, :gender, :class, :email)";
        $stmt = $this->db->prepare($sql);
        return $stmt->execute($data);
    }

    public function find($id) {
        $stmt = $this->db->prepare("SELECT * FROM students WHERE id = :id");
        $stmt->execute(['id' => $id]);
        return $stmt->fetch(PDO::FETCH_ASSOC);
    }

    public function update($id, $data) {
        $sql = "UPDATE students SET name = :name, age = :age, gender = :gender, class = :class, email = :email WHERE id = :id";
        $data['id'] = $id;
        $stmt = $this->db->prepare($sql);
        return $stmt->execute($data);
    }

    public function delete($id) {
        $stmt = $this->db->prepare("DELETE FROM students WHERE id = :id");
        return $stmt->execute(['id' => $id]);
    }
}
学生控制器

创建app/Controllers/StudentController.php

<?php
namespace App\Controllers;

use App\Models\Student;

class StudentController {
    private $student;

    public function __construct() {
        $this->student = new Student();
    }

    public function index() {
        $students = $this->student->getAll();
        require_once __DIR__ . '/../Views/students/index.php';
    }

    public function create() {
        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
            // 简单输入验证
            $data = [
                'name' => filter_input(INPUT_POST, 'name', FILTER_SANITIZE_FULL_SPECIAL_CHARS),
                'age' => (int)$_POST['age'],
                'gender' => $_POST['gender'] ?? '',
                'class' => filter_input(INPUT_POST, 'class', FILTER_SANITIZE_FULL_SPECIAL_CHARS),
                'email' => filter_input(INPUT_POST, 'email', FILTER_SANITIZE_EMAIL) ?: null
            ];

            if (empty($data['name']) || $data['age'] <= 0 || !in_array($data['gender'], ['M', 'F']) || empty($data['class'])) {
                $error = "请填写所有必填字段并确保输入有效";
                require_once __DIR__ . '/../Views/students/create.php';
                return;
            }

            if ($this->student->create($data)) {
                header('Location: /');
                exit;
            } else {
                $error = "创建学生失败";
                require_once __DIR__ . '/../Views/students/create.php';
            }
        } else {
            require_once __DIR__ . '/../Views/students/create.php';
        }
    }

    public function edit($id) {
        $student = $this->student->find($id);
        if (!$student) {
            http_response_code(404);
            echo "Student not found";
            return;
        }

        if ($_SERVER['REQUEST_METHOD'] === 'POST') {
            $data = [
                'name' => filter_input(INPUT_POST, 'name', FILTER_SANITIZE_FULL_SPECIAL_CHARS),
                'age' => (int)$_POST['age'],
                'gender' => $_POST['gender'] ?? '',
                'class' => filter_input(INPUT_POST, 'class', FILTER_SANITIZE_FULL_SPECIAL_CHARS),
                'email' => filter_input(INPUT_POST, 'email', FILTER_SANITIZE_EMAIL) ?: null
            ];

            if (empty($data['name']) || $data['age'] <= 0 || !in_array($data['gender'], ['M', 'F']) || empty($data['class'])) {
                $error = "请填写所有必填字段并确保输入有效";
                require_once __DIR__ . '/../Views/students/edit.php';
                return;
            }

            if ($this->student->update($id, $data)) {
                header('Location: /');
                exit;
            } else {
                $error = "更新学生失败";
                require_once __DIR__ . '/../Views/students/edit.php';
            }
        } else {
            require_once __DIR__ . '/../Views/students/edit.php';
        }
    }

    public function delete($id) {
        if ($this->student->find($id)) {
            $this->student->delete($id);
        }
        header('Location: /');
        exit;
    }
}
布局文件

创建app/Views/layout.php

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <title>学生管理系统</title>
    <link href="/assets/bootstrap.min.css" rel="stylesheet">
</head>
<body>
    <div class="container mt-4">
        <h1 class="mb-4">学生管理系统</h1>
        <a href="/" class="btn btn-primary mb-3">学生列表</a>
        <a href="/create" class="btn btn-success mb-3">添加学生</a>
        <?php if (isset($error)): ?>
            <div class="alert alert-danger"><?= htmlspecialchars($error) ?></div>
        <?php endif; ?>
        <?php include $content; ?>
    </div>
</body>
</html>
学生列表

创建app/views/students/index.php

<?php $content = __FILE__; ?>
<?php include __DIR__ . '/../layout.php'; ?>
<h2>学生列表</h2>
<table class="table table-bordered">
    <thead>
        <tr>
            <th>ID</th>
            <th>姓名</th>
            <th>年龄</th>
            <th>性别</th>
            <th>班级</th>
            <th>邮箱</th>
            <th>操作</th>
        </tr>
    </thead>
    <tbody>
        <?php if (empty($students)): ?>
            <tr><td colspan="7" class="text-center">无数据</td></tr>
        <?php else: ?>
            <?php foreach ($students as $student): ?>
            <tr>
                <td><?= htmlspecialchars($student['id']) ?></td>
                <td><?= htmlspecialchars($student['name']) ?></td>
                <td><?= htmlspecialchars($student['age']) ?></td>
                <td><?= htmlspecialchars($student['gender'] === 'M' ? '男' : '女') ?></td>
                <td><?= htmlspecialchars($student['class']) ?></td>
                <td><?= htmlspecialchars($student['email'] ?? '') ?></td>
                <td>
                    <a href="/edit/<?= $student['id'] ?>" class="btn btn-sm btn-warning">编辑</a>
                    <a href="/delete/<?= $student['id'] ?>" class="btn btn-sm btn-danger" onclick="return confirm('确定删除?')">删除</a>
                </td>
            </tr>
            <?php endforeach; ?>
        <?php endif; ?>
    </tbody>
</table>
学生添加

创建app/views/students/create.php

<?php $content = __FILE__; ?>
<?php include __DIR__ . '/../layout.php'; ?>
<h2>添加学生</h2>
<form method="POST" action="/create">
    <div class="mb-3">
        <label class="form-label">姓名</label>
        <input type="text" name="name" class="form-control" value="<?= htmlspecialchars($_POST['name'] ?? '') ?>" required>
    </div>
    <div class="mb-3">
        <label class="form-label">年龄</label>
        <input type="number" name="age" class="form-control" value="<?= htmlspecialchars($_POST['age'] ?? '') ?>" required>
    </div>
    <div class="mb-3">
        <label class="form-label">性别</label>
        <select name="gender" class="form-select" required>
            <option value="M" <?= ($_POST['gender'] ?? '') === 'M' ? 'selected' : '' ?>></option>
            <option value="F" <?= ($_POST['gender'] ?? '') === 'F' ? 'selected' : '' ?>></option>
        </select>
    </div>
    <div class="mb-3">
        <label class="form-label">班级</label>
        <input type="text" name="class" class="form-control" value="<?= htmlspecialchars($_POST['class'] ?? '') ?>" required>
    </div>
    <div class="mb-3">
        <label class="form-label">邮箱</label>
        <input type="email" name="email" class="form-control" value="<?= htmlspecialchars($_POST['email'] ?? '') ?>">
    </div>
    <button type="submit" class="btn btn-primary">提交</button>
</form>
编辑学生

创建app/views/students/edit.php

<?php $content = __FILE__; ?>
<?php include __DIR__ . '/../layout.php'; ?>
<h2>添加学生</h2>
<form method="POST" action="/create">
    <div class="mb-3">
        <label class="form-label">姓名</label>
        <input type="text" name="name" class="form-control" value="<?= htmlspecialchars($_POST['name'] ?? '') ?>" required>
    </div>
    <div class="mb-3">
        <label class="form-label">年龄</label>
        <input type="number" name="age" class="form-control" value="<?= htmlspecialchars($_POST['age'] ?? '') ?>" required>
    </div>
    <div class="mb-3">
        <label class="form-label">性别</label>
        <select name="gender" class="form-select" required>
            <option value="M" <?= ($_POST['gender'] ?? '') === 'M' ? 'selected' : '' ?>></option>
            <option value="F" <?= ($_POST['gender'] ?? '') === 'F' ? 'selected' : '' ?>></option>
        </select>
    </div>
    <div class="mb-3">
        <label class="form-label">班级</label>
        <input type="text" name="class" class="form-control" value="<?= htmlspecialchars($_POST['class'] ?? '') ?>" required>
    </div>
    <div class="mb-3">
        <label class="form-label">邮箱</label>
        <input type="email" name="email" class="form-control" value="<?= htmlspecialchars($_POST['email'] ?? '') ?>">
    </div>
    <button type="submit" class="btn btn-primary">提交</button>
</form>

完结,先发出来。我在瞅瞅有没有要完善的。有的话再来改,没有就准备下一个项目了。laravel!!!
`

`

`

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值