- 这是一个简单的MVC框架
- 使用composer管理依赖的组件。本次使用了以下组件
类型 | 组件名称 | 简介 | 安装 |
---|---|---|---|
模型组件 | catfan/medoo | 轻量级的PHP数据库框架 | composer require catfan/medoo |
视图模板组件 | twig/twig | 灵活、快速、安全的PHP模板语言 | composer require twig/twig |
路由组件 | noahbuscher/macaw | 非常简单的路由器 | https://github.com/NoahBuscher/Macaw |
noahbuscher/macaw,我直接require下载失败,在composer.json文件中添加
“require”: {
“noahbuscher/macaw”: “dev-master”
}
然后执行composer update命令,还要了github密钥[/尴尬],最终下载成功。
- 使用组件可以快速搭建框架,但还是有很多地方要学习,如路径,组件的依赖,还有每个组件的开发文档,都是新的东西。有的组件框架挺大,依赖很多,下载后都使用失败了
- comoposer的使用、还有服务器的设置,如.htaccess文件配置,需要学习的还很多
1.目录结构
- app下即MVC框架成员,控制器、模型、视图
- config放置配置文件,当前只有一个数据库配置
- core核心类库,外部依赖的组件等都在这里处理
- public外部访问目录
- vender通过composer安装的组件都存放在此
2.mvc框架
2.1控制器
- 在controller目录下创建Index.php控制器文件,处理前端发来的各种请求,并返回
在控制器中会用到视图和模型对象,从模型中获取数据,在视图中展示
<?php
namespace app\controller;
use app\model\Goods;
use core\View;
//控制器
class Index
{
/**
* 展示首页
*/
public function index()
{
$goods = new Goods;
$data = $goods->getData();
$view = new View;
echo $view->templete->render('/index/index.html',['data'=>$data]);
}
/**
* 删除一条记录
* 刷新页面
*/
public function delete($id){
$goods = new Goods;
if(!empty($id)){
$row = $goods->delete($id);
if($row){
echo "<script>alert('删除成功')</script>";
}else{
echo "<script>alert('删除失败')</script>";
}
}else{
echo "<script>alert('格式错误')</script>";
}
return $this->index();
}
public function edit($id){
$goods = new Goods;
$view = new View;
$data = $goods->edit($id);
echo $view->templete->render('index/edit.html',['data'=>$data]);
}
public function update($id){
if(isset($_POST['id'])){
$data = $_POST;
unset($data['id']);//去掉id
$goods = new Goods;
$view = new View;
$row = $goods->update($data,$id);
if($row==1){
echo "<script>alert('更新成功')</script>";
}else{
echo "<script>alert('更新失败')</script>";
}
}
return $this->index();
}
}
2.2模型
- model目录下创建Goods.php,对应数据库表goods。用于处理数据
- Goods模型继承核心类库core下的Model类
goods.php
<?php
namespace app\model;
use core\Model;
//模型
class Goods extends Model
{
private $table = 'goods';//表名
//获取多条记录
public function getData(){
$data = parent::select($this->table,'*',["LIMIT"=>15]);
return $data;
}
//删除一条记录
public function delete($id,$table='')
{
$obj = parent::delete($this->table,['id'=>$id]);
return $obj->rowCount();
}
//编辑商品信息,根据ID获取一条数据
public function edit($id){
$data = parent::get($this->table,'*',["id"=>$id]);
return $data;
}
//更新一条数据
public function update($data, $id, $where = null)
{
$obj = parent::update($this->table,$data,["id"=>$id]);
return $obj->rowCount();
}
}
- Model类继承外部引入的模型组件medoo
- 在Model中重写构造方法,在构造方法中引入配置文件database.php
Model.php
<?php
namespace core;
use Medoo\Medoo;
//公共模型
class Model extends Medoo
{
protected $config = [];
public function __construct()
{
$this->config = require('../config/database.php');
parent::__construct($this->config);
}
}
2.3视图模板
- 在view目录下创建index文件夹,存放index控制器的视图文件
- 在core核心类库中创建View.php作为公共的视图类,该类继承外部引入的twig模板组件。
- 创建构造方法,获取twig的模板对象。
View.php
<?php
namespace core;
use Twig\Environment;
use Twig\Loader\FilesystemLoader;
//公共视图模板
class View extends Environment
{
public static $templete;
public function __construct()
{
$loader = new FilesystemLoader('../app/view');
$this->templete = new Environment($loader);
}
}
- 在view/index目录下创建两个视图文件,首页index.html、编辑页edit.html
- 使用twig模板语言输出数据
index.html
```html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>商品信息管理</title>
<style>
body {
display: flex;
flex-flow: column nowrap;
align-items: center;
}
form {
display: flex;
flex-flow: row wrap;
}
form > section {
margin: 10px;
display: flex;
flex-flow: row nowrap;
}
table {
margin-top: 30px;
width: 1000px;
font-family: verdana, arial, sans-serif;
font-size: 11px;
color: #333333;
border-width: 1px;
border-color: #666666;
border-collapse: collapse;
}
table > thead {
background-color: #00ffff;
}
table th {
border-width: 1px;
padding: 8px;
border-style: solid;
border-color: #666666;
}
table td {
border-width: 1px;
padding: 8px;
border-style: solid;
border-color: #666666;
background-color: #ffffff;
text-align: center;
}
tfoot > tr,
tfoot > tr > td {
width: initial;
}
</style>
</head>
<body>
<hr />
<hr />
<form
action="<?php echo $_SERVER['PHP_SELF'] ?>"
class="queryterms"
method="POST"
>
<section>
<label for="goodsname">商品名称:</label>
<input type="text" name="goodsname" id="goodsname" value="" />
</section>
<section>
<label for="goodsmodel">商品型号:</label>
<input type="text" name="goodsmodel" id="goodsmodel" value="" />
</section>
<section>
<button>查询</button>
</section>
</form>
<div>
<table>
<thead>
<tr>
<th>ID</th>
<th>名称</th>
<th>型号</th>
<th>价格</th>
<th>数量</th>
<th>状态</th>
<th>操作</th>
</tr>
</thead>
<tbody>
{% for goods in data %}
<tr>
<td>{{ goods.id|e }}</td>
<td>{{ goods.name|e }}</td>
<td>{{ goods.model|e }}</td>
<td>{{ goods.price|e }}</td>
<td>{{ goods.number|e }}</td>
<td>{{ goods.status|e }}</td>
<td>
<a href="/index/edit/{{ goods.id|e }}">编辑</a>
<a href="/index/delete/{{ goods.id|e }}">删除</a>
</td>
</tr>
{% endfor %}
</tbody>
<tfoot>
<tr>
<td colspan="7"></td>
</tr>
</tfoot>
</table>
</div>
</body>
</html>
edit.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=xiug, initial-scale=1.0" />
<title>修改商品信息</title>
<style>
body {
margin: 0;
text-align: center;
display: flex;
flex-flow: column nowrap;
align-items: center;
}
form {
background-color: lightcyan;
border: 1px solid #c0c0c0;
width: 600px;
display: flex;
flex-flow: column nowrap;
align-items: center;
padding: 30px;
}
form > section {
width: 80%;
margin: 30px 0;
display: grid;
grid-template-columns: 200px 300px;
font-size: 1.2em;
}
form > section input {
font-size: 1.2em;
}
button {
background-color: #bbd6e4;
width: 200px;
margin-top: 30px;
padding: 10px;
border-radius: 5px;
}
</style>
</head>
<body>
<h1>修改商品信息</h1>
<form action="/index/update/{{data.id}}" method="POST">
<input type="hidden" name="id" value="{{data.id}}" />
<section>
<label for="name">商品名称:</label>
<input type="text" name="name" id="name" value="{{data.name}}" />
</section>
<section>
<label for="model">商品型号:</label>
<input type="text" name="model" id="model" value="{{data.model}}" />
</section>
<section>
<label for="price">价格:</label>
<input type="text" name="price" id="price" value="{{data.price}}" />
</section>
<section>
<label for="number">数量:</label>
<input type="text" name="number" id="number" value="{{data.number}}" />
</section>
<section>
<label for="status">状态:</label>
<input type="text" name="status" id="status" value="{{data.status}}" />
</section>
<div class="button">
<button type="submit">提交</button>
</div>
</form>
</body>
</html>
3.路由
- 在core目录下创建routes.php文件
- 在routes.php文件中创建NoahBuscher\Macaw路由器对象
- 通过get方法设置路由,该方法有两个参数route和callback(或控制器方法路径)
<?php
name core;
use NoahBuscher\Macaw\Macaw;
//默认首页
Macaw::get('/','app\controller\Index@index');
//删除
Macaw::get('index/delete/(:num)','app\controller\Index@delete');
//编辑
Macaw::get('index/edit/(:num)','app\controller\Index@edit');
//更新
Macaw::post('index/update/(:num)','app\controller\Index@update');
// Macaw::get('(:all)',function($fu){
// echo '未匹配到路由'.$fu;
// });
Macaw::dispatch();
4.composer自动加载
在正式访问之前还得把创建的几个类在composer.json文件中做好类库映射,然后在终端执行composer dump命令更新,才能实现自动加载。
把以下内容添加到composer.json文件中
"autoload": {
"psr-4": {
"app\\": "app",
"core\\": "core",
"app\\controller\\": "app/controller",
"app\\model\\": "app/model",
"app\\view\\": "app/view"
}
}
5. 访问
- 通过phpstudy创建一个网站,www.compo.edu,根目录指向comp目录下的public目录
- public目录下创建index.php,即为该网站的入口文件
- 另外还需要public目录下创建.htaccess文件,针对当前网站做访问配置
index.php
<?php
//包含进composer自动加载文件
require'../vendor/autoload.php';
//包含进路由器文件
require '../core/routes.php';
.htaccess
RewriteEngine On
RewriteBase /
# Allow any files or directories that exist to be displayed directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^(.*)$ index.php?$1 [QSA,L]
效果图
访问 www.compo.edu
点击编辑:
点击删除:
直接访问 www.compo.edu/hello