Composer笔记和利用Composer来建立自己的框架

一 认识Composer

Composer是 PHP 用来管理依赖(dependency)关系的工具。你可以在自己的项目中声明所依赖的外部工具库(libraries),Composer 会帮你安装这些依赖的库文件。

  • Composer 是必须掌握的工具
  • 是 PHP 依赖管理的利器

PHP中常用扩展库模式PK

  • PECL: 是 PHP 扩展的存储库, 提供了所有已知的扩展和托管设施的目录, 用于下载和开发 PHP 扩展.
  • PEAR: PEAR是一个可重用 PHP 组件的框架和分发系统.
  • phpize: 用 phpize 编译共享 PECL 扩展库.
  • Composer: 是 PHP 用来管理依赖(dependency) 关系的工具.

Composer的代码库在哪里?
Composer笔记和利用Composer来建立自己的框架_第1张图片

  • https://pkg.phpcomposer.com
  • https://php.cnpkg.org/
  • https://mirrors.aliyun.com/composer/

项目中常用的Composer代码包

包名 说明 地址
guzzlehttp/guzzle 功能强大的 HTTP 请求库 https://packagist.org/packages/guzzlehttp/guzzle
hashids/hashids 数字 ID 转字符串,支持多语言 https://packagist.org/packages/hashids/hashids
intervention/image 图片处理,获取图片信息,上传,格式转换,缩放,裁剪等 https://packagist.org/packages/intervention/image
phpmailer/phpmailer 邮件发送 https://packagist.org/packages/phpmailer/phpmailer
phpoffice/phpexcel excel操作类 https://packagist.org/packages/phpoffice/phpexcel
monolog/monolog 日志操作,composer官方就是用它做例子 https://packagist.org/packages/monolog/monolog
catfan/medoo 简单易用的数据库操作类,支持各种常见数据库 https://packagist.org/packages/catfan/medoo
league/route 路由调度 https://packagist.org/packages/league/route
nesbot/carbon 时间操作 https://packagist.org/packages/nesbot/carbon

二 Composer 的安装

  • 下载地址 https://getcomposer.org/download/

Windows安装

  1. 先确定自己电脑的php环境, 进入命令行 php -v 看看. 如果是继承环境, 还没有加入 php环境变量的话, 需要加入php环境变量.
  2. 确定好自己的PHP环境变量有了之后,进入下载页面, https://getcomposer.org/download/ , 下载 Composer-Setup.exe, 点击下一步, 一直到完成.
  3. 进入项目目录, 然后 输入 composer, 看到命令介绍, 说明已经成功了.

linux安装

  1. 进入下载页 https://getcomposer.org/download/ , 右键保存最近的 版本链接.

Composer笔记和利用Composer来建立自己的框架_第2张图片

  1. 进入命令行, wget https://getcomposer.org/download/2.0.2/composer.phar
  2. 完成之后, 输入 composer 看到如下表示成功 (PS: 有版本需要输入 php componser.phar , 如果是这样可以, mv composer /usr/bin/composer 这样就只用输入 composer 了, 如果没有权限的话, chmod +x /usr/bin/composer),

Composer笔记和利用Composer来建立自己的框架_第3张图片


三 Composer 的应用

  1. 在 https://packagist.org/explore/ 上,随便输入 monolog, 测试一下.s.630web.com
  2. 进入项目目录, 然后在命令行中输入 composer require monolog/monolog (这样是默认的,但是默认的是使用国外的服务器)
  3. 用上面所说的国内的镜像, 例如 https://php.cnpkg.org ,进入之后, 按照说明, 先要设置 镜像
  1. 设置成功之后, 如何查看呢? 命令行中输入 composer config -g -l

Composer笔记和利用Composer来建立自己的框架_第4张图片

  1. 进入项目目录, 然后在 命令行中输入 composer require monolog/monolog ,如果指定详细的版本可以用 composer require monolog/monolog:1.0 这里可以用通配符 *(泛匹配) ^(大于) ~(约等于) 等
  2. 取消 镜像 composer config -g --unset repos.packagist
  3. 使用的时候,一定要 导入这个文件 例如 require “verdor/autoload.php”;


require("vendor/autoload.php");

use Monolog\Logger;
use Monolog\Handler\StreamHandler;

// create a log channel
$log = new Logger('name');
$log->pushHandler(new StreamHandler(__DIR__.'/your.log', Logger::WARNING));

// add records to the log
$log->warning('this is a test');
$log->error('ok'); 
  1. 具体怎么用,去具体的 插件文档中去找.

四 Composer 常用文件

  • vendor 目录 : 所有的插件下载后,都放在这个目录中
  • composer.json 文件
键名 描述
name 表示包的名称,如果你经常使用 Github, 那对这个值的表达式一定非常熟悉. 通常扩展包名包含两部分,并且以"/"分割.斜杠前的部分,代表包的所有者,斜杠后的部分代表包的名称.尽量保持简单和有意义,便于记忆和传播. 如 “name”:“Lmonkey/demo”, "Lmonkey"表示公司, “demo” 表示公司下面的一个项目名
description 表示项目的应用简介,这部分应尽量简洁的介绍项目.如果确实有很多内容,建议写在 README.md 文件里(在扩展库的源码目录中)
license 如果决定将包公开发布,那么记得选择一个合适的许可证.这样别的程序员在引用包的时候,通过查看许可证,确保没有法律上的问题.
authors 作者字段可以包含一个对象数组,也就是说,可以提供多个作者信息.
require 这个字段的值是一个对象,同样以键值对的形式构成.上例提到的两个依赖关系,最重要的就是版本信息的指定.如我们需要使用monolog的版本是1.0.,意思是只要版本是1.0分支即可,如1.0.0, 1.0.2或1.0.99. 版本定义的几种方式如下: ①标准的版本: 定义标准的版本包文件,如1.0.2 ②一定范围的版本: 使用比较符号来定义有效的版本的范围,有效的符号有>,>=,<,<=,!= ③通配符:特别的匹配符号, 如1.0.* 相当于>=1.0且<1.1版本即可 ④下一个重要的版本: ~符号最好的解释就是, ~1.2就相当于>1.2 且<2.0, 但~1.2.3相当于 >=1.2.3且<1.3版本
minimum-stability 通过设置minimum-stablility的值,告诉Composer当前开发的项目依赖要求的包的全局稳定性级别,它的值包括dev,alpha,beta,RC,stable, 其中,stable是默认值
  • composer.lock 文件

文件composer.lock 会根据 composer.json 的内容自动生成, 和 composer.json 在同一位置, 即在安装完所有需要的包之后, Composer 会在 composer.lock文件中生成一张标准的包版本的文件,这将锁定所有包的版本. 可以使用 composer.lock (当然是和 composer.json 一起) 来控制项目的版本.
composer.lock 与 composer.json 的关系为: composer.json 文件为包的元信息, composer.lock 文件同样为包的元信息, 但在 composer.json文件中可以指定不明确的依赖包版本, 如 “>=1.0” , 在 componser.lock 文件中的会是当前安装的版本.那么当使用 Componser安装包时,它会优先从composer.lock 文件读取依赖版本,再根据 composer.json 文件去获取依赖.这确保了该库的每个使用者都能得到相同的依赖版本.这对于团队开发来讲非常重要.


五 Composer 常用命令

命令 描述
composer list 获取帮助信息
composer init 以交互方式填写 composer.json 文件信息
composer install 从当前目录读取 composer.json 文件,处理依赖关系,并安装到 vendor 目录下
composer update 获取依赖的最新版本,升级 composer.lock 文件
composer require 添加新的依赖包到 composer.json 文件中并执行更新
composer search 在当前项目中搜索依赖包
composer show 列举所有可用的资源包
composer validate 检测 composer.json 文件是否有效
composer self-update 将 composer 工具更新到最新版本
composer create-project 基于 composer 创建一个新的项目

更新一个插件的版本号

  1. 先在 composer.json 中查看当前插件的版本号. 如下
{
    "require": {
        "monolog/monolog": "1.25.0"
    }
}

  1. 我们将 1.25.0 修改为 2.1.1, 进入项目目录 然后执行

composer update monolog/monolog

Composer笔记和利用Composer来建立自己的框架_第5张图片

  1. 查看 composer.lock ,已经更改完成.

六 库类的规范

  • Composer 利用 PSR-0 和 PSR-4, 以及PHP5.3的命名空间构造了一个繁荣的PHP生态系统.
  • PSR即PHP推荐标准. 目前通过审核的有PSR-1至PSR-4,还有最近的PSR-6和PSR-7.重点是成熟的前四个标准,对于初学者来说,可以起到一个很好的代码规范作用.早些时候还有PSR-0规范,但已经废弃并被 PSR-4 取代. 例如 PSR规范描述了从文件路径自动加载类,可以与PSR-0规范相互操作,可一起使用.PSR规范也描述了自动加载的文件应当放在哪里.PSR-4规范能够满足面向package的自动加载,它规范了如何从文件路径自动加载类,同时规范了自动加载文件的位置.PSR描述的规范内容很多,具体细节请参考PSR规范文档.

Composer笔记和利用Composer来建立自己的框架_第6张图片


七 使用 Composer 构建自己的 PHP 开发框架

  • 路由 noahbuscher/macaw
  • 控制器
  • 视图 twig/twig
  • 模型 catfan/medoo
  • 应用库 jasongrimes/paginator
  • 单个文件自动加载 helpers.php
  • 文件上传 slince/upload
  • 图片处理(大小,尺寸,水印等) intervention/image
  • 分页类 jasongrimes/paginator

1 框架介绍

Composer笔记和利用Composer来建立自己的框架_第7张图片

2 构建框架的路由

  • 路由 noahbuscher/macaw
  1. 安装 noahbuscher/macaw
    注意,这个插件只有一个版本(dev-master), 所以命令行安装的时候,如果用 composer require noahbuscher/macaw 是不成功的. 需要用如下

composer require noahbuscher/macaw:dev-master

  1. 使用, 看使用文档 https://packagist.org/packages/noahbuscher/macaw

在index.php 加入如下代码


require('vendor/autoload.php');

use NoahBuscher\Macaw\Macaw;

// 打开首页测试
Macaw::get('/', function () {
    echo "this is index";
});

// 访问 http://xx.com/hello
Macaw::get("/hello", function () {
    echo "hello,world!";
});

// 访问 http://bd.del.com/demo/22 
Macaw::get("/demo/(:num)", function ($id) {
    echo "#######{$id}";
});

Macaw::dispatch();

打开网址,即可显示.

  1. 这里注意, 在文档 https://packagist.org/packages/noahbuscher/macaw 最下面,有一个提示,在 Apache 下面需要加一个 文件. 这里要加一下.

3 构建控制器

  1. 在 app/controllers 下,新建一个 Test.php 文件

namespace controllers;

class Test
{
    function index()
    {
        echo "this is index()";
    }

    function hello(){
        echo "this is hello()";
    }
}
  1. 在 入口文件 index.php 中修改路由, 如下

require('vendor/autoload.php');

use NoahBuscher\Macaw\Macaw;

Macaw::get('/index', "controllers\Test@index");


Macaw::dispatch();
  1. 这样访问的话, 还是会出错. 因为我们的类没有自动加载, 需要在 composer.json 中,写一个自动加载 autoload
{
  "require": {
    "monolog/monolog": "2.1.1",
    "noahbuscher/macaw": "dev-master"
  },
  "autoload": {
    "classmap": [
        "app/controllers"
    ]
  }
}
  1. 上面写完了 autoload, 我们需要进入项目目录下, 然后执行 composer dump-autoload

在这里插入图片描述
如上成功了, 我们在 vendor / composer 下面的 autoload_classmap.php 下,就可以看到,我们自己写的 Hello,Test就已经加载了



// autoload_classmap.php @generated by Composer

$vendorDir = dirname(dirname(__FILE__));
$baseDir = dirname($vendorDir);

return array(
    'Composer\\InstalledVersions' => $vendorDir . '/composer/InstalledVersions.php',
    'controllers\\Hello' => $baseDir . '/app/controllers/Hello.php',
    'controllers\\Test' => $baseDir . '/app/controllers/Test.php',
);

如上, 我们手动的 composer dump-autoload 的方式来加载我们的控制器,这样是可以的,但是如果项目太大,这样是不够的. 应该想办法实现自动加载.

  1. 实现自动加载类控制器. 在composer.json 中修改如下
{
  "require": {
    "monolog/monolog": "2.1.1",
    "noahbuscher/macaw": "dev-master"
  },
  "autoload": {
    "psr-4": {
      "controllers\\": "app/controllers/"
    }
  }
}

如上修改, 则可以自动加载类,不需要手动 composer dump-autoload. 此时,在 vendor/composer/autoload_psr4.php 中可以看到 contorllers的配置.

4 写一个父类,让控制器都基础自这个父类, 例如 BaseController.php

  1. 如下,先添加2个方法,后期可以根据具体的情况完善.

// +----------------------------------------------------------------------
// | User: zq
// +----------------------------------------------------------------------
// | Time: 2020/10/28 3:10 下午
// +----------------------------------------------------------------------
namespace controllers;

class BaseController
{
    //成功之后
    function success($url, $msg)
    {
        echo "";
    }

    //失败之后
    function error($url, $msg)
    {
        echo "";
    }
}
  1. 子类都继承父类

class Test extends BaseController

5 单个文件的自动加载 helpers.php

  • 这个文件是自动加载的, 所以这个文件中的方法, 在 控制器,模型等, 所有的地方都可以使用.
  1. 举例: 在 app下新建一个 helpers.php

// +----------------------------------------------------------------------
// | User: zq
// +----------------------------------------------------------------------
// | Time: 2020/10/28 3:18 下午
// +----------------------------------------------------------------------

// 自动加载文件, 其中的方法,在控制器,模型等,所有的位置都可以用
// 因为这里没有命名空间,所以为了防止重复,最好做一个判断

if (!function_exists("dd")) {
    function dd(...$args)
    {
        http_response_code("500");
        foreach ($args as $x) {
            var_dump($x);
        }
        die(1);
    }
}

  1. 在 composer.php 下面加一个 files, 具体如下
{
  "require": {
    "monolog/monolog": "2.1.1",
    "noahbuscher/macaw": "dev-master"
  },
  "autoload": {
    "psr-4": {
      "controllers\\": "app/controllers/"
    },
    "files": [
      "app/helpers.php"
    ]
  }
}
  1. 第一次加的时候, 我们需要在命令行中 输入 composer dump-autoload, 这样这个文件就能实现自动加载了.
  2. 我们测试一下, 在 控制器中 调用这个方法,测试行不行.

// +----------------------------------------------------------------------
// | User: zq
// +----------------------------------------------------------------------
// | Time: 2020/10/28 2:38 下午
// +----------------------------------------------------------------------
namespace controllers;

class Test extends BaseController
{
    function index()
    {
        dd("aaaa", array(1, 2, 3, 4));
    }
    
}

浏览器打开, 可以输出 string(4) “aaaa” array(4) { [0]=> int(1) [1]=> int(2) [2]=> int(3) [3]=> int(4) } ,没有问题.


6 使用Composer组件 twig/twig 创建视图

  1. 命令行安装 composer require twig/twig
  2. 用法,要看手册 https://twig.symfony.com/doc/3.x/
  3. 查看文档中, 视图的写法如下
require_once '/path/to/vendor/autoload.php';

$loader = new \Twig\Loader\ArrayLoader([
    'index' => 'Hello {{ name }}!',
]);
$twig = new \Twig\Environment($loader);

echo $twig->render('index', ['name' => 'Fabien']);
  1. 如上,我们把上述方法封装成2个其他框架常用的 assgin 和 display 方法, 写在父类 BaseController中,如下

namespace controllers;

class BaseController
{
    protected $twig;
    protected $data = array();

    //构造方法
    public function __construct()
    {
        $loader = new \Twig\Loader\FilesystemLoader(dirname(__DIR__) . '/views/');
        $this->twig   = new \Twig\Environment($loader, [
            //'cache' => '/path/to/compilation_cache',
        ]);


    }

    // assign 分配变量给到模板
    public function assign($var, $value = null)
    {
        if (is_array($var)) {
            $this->data = array_merge($this->data, $var);
        } else {
            $this->data[$var] = $value;
        }
    }

    public function display($template)
    {
        echo $this->twig->render($template . ".html", $this->data);
    }


    //成功之后
    function success($url, $msg)
    {
        echo "";
    }

    //失败之后
    function error($url, $msg)
    {
        echo "";
    }


}
  1. 如何调用可以看文档, 下面举一个最简单的例子, 在控制器中赋值,然后调用模板
class Test extends BaseController
{
    function index()
    {
        $this->assign("title", "@@@@@@@@");
        $this->assign("one", "abc");
        $this->assign("two", "ttt");
        $this->assign("alist", array("aa" => "bb", "ccc" => "3333", "ddd", "wwwww"));

        //dd($this->data);
        $this->display('index');
    }

}

模板中调用如下即可. 至于循环等,看文档中介绍.

<title> {{ title }}</title>

<ul id="navigation">
    {% for item in alist %}
    <li>{{item}}</li>
    {% endfor %}
</ul>

7 使用 Composer 组件 catfan/medoo 制作ORM数据库映射模型

  1. 命令行进入项目目录, 使用如下命令按照

composer require catfan/medoo

  1. 具体的操作还需要看文档说明 https://packagist.org/packages/catfan/medoo
  2. 在 composer.json 中, 在 psr-4 下加入 “models\”:“app/models”, **再在命令行中进入项目目录,加载 composer dump-autoload 即可.
{
  "require": {
    "monolog/monolog": "2.1.1",
    "noahbuscher/macaw": "dev-master",
    "twig/twig": "^3.1",
    "catfan/medoo": "^1.7"
  },
  "autoload": {
    "psr-4": {
      "controllers\\": "app/controllers/",
      "models\\": "app/models/"
    },
    "files": [
      "app/helpers.php"
    ]
  }
}

  1. 在models中建立 model的父类 BaseDao

namespace models;

use Medoo\Medoo;

class BaseDao extends Medoo
{
    function __construct()
    {
        $options = [
            'database_type' => 'mysql',
            'database_name' => 'lmonkey',
            'server'        => 'localhost',
            'username'      => 'root',
            'password'      => 'root',
            'prefix'        => 'ew_',
        ];
        parent::__construct($options);
    }
}
  1. 其他的model继承 父类BaseDao, 例如新建一个 User.php 如下
namespace models;


class User extends BaseDao
{

}
  1. 在控制器中如何使用? 如下, 具体的语句可以查看文档
$data = $user->select("user", "*");
$this->assign("userlist", $data);

上述,框架的几大部分都结束了. 如果此时代码给到其他人,需要在项目目录下,命令行输入命令 composer install 来安装一下.


八 基于自己的框架进行应用开发

  • 图书管理系统为例来演示基于自己的框架进行应用开发

1 设计项目的基本结构

  1. 设置2个分类显示 分类管理(catelist) 图书管理(booklist)
  2. 设置 分类管理(catelist) 的数据库设计
create table ew_category(
    id int(10) not null auto_increment,
    catname varchar(30) not null,
    pid decimal(10, 0) not null,
    ord decimal(10, 0) not null,
    primary key(`id`)
) default charset = utf8mb4;

insert into ew_category values(1, "one", "0", "3");
insert into ew_category values(2, "two", "0", "0");
insert into ew_category values(3, "three", "0", "0");
insert into ew_category values(4, "four", "0", "0");

insert into ew_category values(5, "a111", "1", "3");
insert into ew_category values(6, "b111", "1", "0");
insert into ew_category values(7, "a222", "2", "0");
insert into ew_category values(8, "b222", "2", "0");

insert into ew_category values(9, "aaaaa", "5", "3");
insert into ew_category values(10, "bbbbb", "5", "0");
insert into ew_category values(11, "xxxxxx", "7", "0");
insert into ew_category values(12, "yyyyyy", "7", "0");
  1. 在 入口文件,添加新的2个分类的路由
// 分类管理
Macaw::get("/catelist", "controllers\\Category@index");

// 图书管理
Macaw::get("/booklist", "controllers\\Book@index");

2 无限极分类的列表制作

  1. 在app同级新建一个 class 目录,然后加入准备好的一个类 cattree.php,用来处理无限分类.
  2. 在 index.php 入口文件中, 引入这个文件

require(“class/cattree.php”);

  1. 在具体的控制器中, 用之前要引入

use lmonkey\CatTree as CT;

  1. 控制器中写法
class Category extends BaseController
{
    public function index()
    {
        $db = new BaseDao();

        $treelist = $db->select("category", ["id", "catename", "pid", "ord"]);

        //$ntree = CT::getTree($treelist);
        $ntree = CT::getList($treelist);

        $this->assign("treeList", $ntree);
        $this->display("category/index");
    }
}
  1. 视图中写法
{% for item in treeList %}
<tr>
    <td><input type="text" size="2" value="{{item.ord}}"></td>
    <td>

        {% for i in 0..item.level*8 %}
            &nbsp;
        {% endfor %}

        |-{{item.catename}}</td>
    <td>修改/删除</td>
</tr>
{% endfor %}

显示的演示如下:

Composer笔记和利用Composer来建立自己的框架_第8张图片

3 无限极排序和添加编写

  1. 先新加一个 路由. /category/toadd

Macaw::get("/category/toadd", “controllers\Category@toadd”);

  1. 控制器中,添加 toadd 方法


namespace controllers;

use lmonkey\CatTree as CT;

use models\BaseDao;

class Category extends BaseController
{
    public function index()
    {
        $db = new BaseDao();

        $treelist = $db->select("category", ["id", "catename", "pid", "ord"]);

        //$ntree = CT::getTree($treelist);
        $ntree = CT::getList($treelist);

        $this->assign("treeList", $ntree);
        $this->display("category/index");
    }

    //排序方法
    public function order()
    {
        $db = new BaseDao();

        foreach ($_POST["id"] as $key => $value) {
            $db->update("category", ['ord' => $value], ["id" => $key]);
        }

        $this->success("/catelist", "排序成功!");
    }


    //添加方法展示
    public function toadd()
    {
        $db = new BaseDao();

        $treelist = $db->select("category", ["id", "catename", "pid", "ord"]);

        $ntree = CT::getList($treelist);

        $this->assign("treeList", $ntree);
        $this->display("category/toadd");
    }

    //添加方法post添加
    public function doadd()
    {
        $db = new BaseDao();
        unset($_POST['submit']);
        $data = $db->insert("category", $_POST);

        if ($data->rowCount() > 0) {
            $this->success("/catelist", "添加成功!");
        }else{
            $this->error("/category/toadd", "添加失败!");
        }
    }


}

4 无限极修改和删除

部分源码, 主要是 流程的上的,避免逻辑错误.

//修改方法展示
    public function toupdate()
    {
        $db = new BaseDao();

        $treelist = $db->select("category", ["id", "catename", "pid", "ord"]);
        $ntree    = CT::getList($treelist);
        $this->assign("treeList", $ntree);

        //获取一条要修改的记录
        $cate = $db->get("category", ["id", "catename", "pid", "ord"], ["id" => $_GET['id']]);
        $this->assign("cate", $cate);

        $this->display("category/toupdate");
    }


    //修改方法
    public function doupdate()
    {
        $db = new BaseDao();
        unset($_POST['submit']);

        $id = $_POST["id"];
        unset($_POST["id"]);

        $treelist = $db->select("category", ["id", "catename", "pid", "ord"]);
        $ntree    = CT::getList($treelist);

        $selftree = $ntree[$id];

        if (in_array($_POST["pid"], explode(",", $selftree["childs"]))) {
            $this->error("/catelist", "不能将分类修改到自己的子类下面!");
        } else {
            $data = $db->update("category", $_POST, ["id" => $id]);

            if ($data->rowCount() > 0) {
                $this->success("/catelist", "修改成功!");
            } else {
                $this->error("/catelist", "修改失败!");
            }
        }


    }


    // 删除
    public function dodelete()
    {
        $db = new BaseDao();

        $treelist = $db->select("category", ["id", "catename", "pid", "ord"]);
        $ntree    = CT::getList($treelist);

        $selftree = $ntree[$_GET["id"]];

        if (!empty($selftree["childs"])) {
            $this->error("/catelist", "只能删除空文分类!");
        } else {

            $data = $db->delete("category", ["id" => $_GET["id"]]);

            if ($data->rowCount() > 0) {
                $this->success("/catelist", "删除成功!");
            } else {
                $this->error("/catelist", "删除失败!");
            }
        }

    }

5 文件上传和处理

  1. input 修改为 file 类型
  2. form 中加上属性 enctype=“multipart/form-data”
  3. composer 找一个 文件上传的插件 slince/upload
  4. 在项目目录中, composer require slince/upload 下载 slince/upload
  5. slince/upload 使用文档: https://packagist.org/packages/slince/upload
  6. 处理图片的插件 intervention/image
  7. 使用文档: http://image.intervention.io/getting_started/installation

参考代码如下:

    //添加方法post添加
    public function doadd()
    {
        $db = new BaseDao();
        unset($_POST['submit']);

        //上传路径
        $path = dirname(dirname(__DIR__)) . "/uploads";

        // 文件上传
        $builder = new UploadHandlerBuilder(); //create a builder.
        $handler = $builder
            ->allowExtensions(['jpg', 'png', 'gif'])
            ->allowMimeTypes(['image/*', 'text/plain'])
            ->saveTo($path) //save to local
            ->getHandler();

        $files    = $handler->handle();
        $filename = $files['filename']->getUploadedFile()->getClientOriginalName();

        // 图片处理的包(大小,尺寸,水印)
        $img = Image::make($path . '/' . $filename);

        $img->resize(150, 240);

        // insert a watermark, 加水印
        $img->insert($path . '/watermark.png');

        // save image in desired format
        $img->save($path . '/pre_' . $filename);


        $_POST["filename"] = $filename;

        $data = $db->insert("book", $_POST);

        if ($data->rowCount() > 0) {
            $this->success("/booklist", "添加成功!");
        } else {
            $this->error("/book/toadd", "添加失败!");
        }
    }

6 分页

  1. jasongrimes/paginator 文档: https://packagist.org/packages/jasongrimes/paginator
public function index($num = 1)
{
    $db = new BaseDao();

    $treelist = $db->select("category", ["id", "catename", "pid", "ord"]);

    //$ntree = CT::getTree($treelist);
    $ntree = CT::getList($treelist);

    //分页
    $totalItems   = $db->count("book");
    $itemsPerPage = 5;
    $currentPage  = $num;
    $urlPattern   = '/booklist/(:num)';

    $start = ($currentPage - 1) * $itemsPerPage;
    $books = $db->select("book", "*", ["LIMIT" => [$start, $itemsPerPage]]);
    $this->assign("books", $books);

    $paginator = new Paginator($totalItems, $itemsPerPage, $currentPage, $urlPattern);
    $this->assign("fpage", $paginator);

    $this->assign("treeList", $ntree);
    $this->display("book/index");
}

九 Composer 的总结

composer 是一个非常好的php包管理工具, 将一些功能化的操作放到包中. 用的时候, composer拿下来用.

大概步骤:

  1. https://packagist.org/packages/ 寻找包, 例如 twig/twig
  2. cmd 进入自己的项目文件中, composer require twig/twig, 将这个包拉到本地.
  3. 查看文档, 就可以知道详细的操作.

后期,自己会记录创建一个属于自己的 composer包.


你可能感兴趣的:(composer)