zoukankan      html  css  js  c++  java
  • php源码建博客5--建库建表-配置文件-错误日志

    主要:

    1. 整理框架
    2. 建库建表
    3. 配置文件类
    4. 错误日志记录
    --------------本篇后文件结构:--------------------------------------
    blog
    ├─App
    │  ├─Model 模型目录
    │  ├─View 视图目录
    │  │  ├─Admin后台目录
    │  │  └─Home前台目录
    │  ├─Common 配置目录
    │  │  └─config.php  配置文件
    │  ├─Log 日志目录
    │  │  └─log.txt  日志文件
    │  ├─Controller 控制器
    │  │  ├─Admin后台
    │  │  │  └─DemoController.class.php 测试控制器
    │  │  └─Home前台
    ├─Public   静态公共文件(js,css,images)
    │  ├─Plugins 插件
    │  ├─Back后台
    │  └─Home前台
    ├─Frame 公共使用的类
    │   ├─BaseModel.class.php 数据库连接类
    │   ├─BaseController.class.php 控制器公共操作(设置编码,信息跳转)
    │   ├─FactoryModel.class.php  模型工厂类
    │   ├─Log.class.php  日志厂类
    │   ├─Config.class.php  配置文件读取类
    │   ├─Init.class.php  初始化应用类
    │   └─MySQLDB.class.php 数据库操作工具类
    └─index.php  入口文件
    -----------------------------------------------------------------------------------------------------

    利用上篇中搭建好的mvc框架结构,正式开始开发博客项目。首先建立数据表,然后开始搭建后台,数据前台展示,完成博客主要模块展示。

    下载查看该项目源码https://gitee.com/NewbiesYang/young_blog

    整理框架

      清理测试页面

        1)前面构建框架结构,使用了用户登录测试页面以及后台首页页面。在此全部去掉,从新开始构建前台和后台页面。类似于我们下载了一个ThinkPHP或Laravel或其他的框架。 现在开始在这个微型框架上来构建我们的项目

        2) 实际开发,会用前端人员做好的静态页面来进行开发。所以也可以在 【模板之家】或其他网站 下载 后台模板和前台博客静态页面。然后专注于后端开发,可以加快速度。本项目供学习研究使用,也就不那么着急了。

         原本是准备全部利用别人写好的前端页面(包括前端显示和后台页面),专注于后端逻辑的开发。而且已经把分类页面列表都做好了。还提交传送了。
    
         此刻,仔细想想,要是这样玩,那我直接用框架更好了。既然做后端开发,自己写个后端页面+程序处理,没什么问题吧..., 置于前端显示页面,那再用前辈写的前端页面倒是可以的
    
        于是乎,卷起柚子,说干就干,先来整理框架,开始搭建博客。。。。。
    说一说

      框架结构:

    --------------清理后MVC框架文件结构:--------------------------------------
    blog
    ├─App
    │  ├─Model 模型目录
    │  ├─View 视图目录
    │  │  ├─Back后台
    │  │  └─Home前台
    │  ├─Controller 控制器目录
    │  │  ├─Back后台
    │  │  └─Home前台
    ├─Public   静态公共文件(js,css,images)
    │  ├─Plugins 插件
    │  ├─Back后台
    │  └─Home前台 
    ├─Frame 公共使用的类
    │   ├─BaseModel.class.php 数据库连接类
    │   ├─BaseController.class.php 控制器公共操作(设置编码,信息跳转)
    │   ├─FactoryModel.class.php  模型工厂类
    │   ├─Init.class.php  初始化应用类
    │   └─MySQLDB.class.php 数据库操作工具类
    └─index.php  入口文件
    -----------------------------------------------------------------

      后续的开发只需要复制该目录结构文件, 就可以在此基础上进行开发了。

    提交传送代码

    git add -A
    git commit -m "清理MVC结构"
    git push origin master

      插件准备

        1) layui插件: 搭建后台程序,准备使用layui前端框架,这个框架个人认为做后台界面还是不错的。它还包含一些比较使用模块。 

            用bootstrap也可以,我更加倾向于用它来做前台页面。

          下载网址: http://www.layui.com/

        2) jQuery库:  更方便操作DOM, 尤其是经常使用ajax请求。

        3) 其他插件: 如Ueditor编辑器等 需要使用时再下载吧。一般插件都会有demo示例, 按照示例和手册,懂web开发基本能使用。

        上述插件暂时不熟悉没有关系,官网上有手册,需要什么模块,便查手册便使用,就像搭积木,如果要做得更好,当然要花更多的时间多练习。我本着后台给程序管理员使用,也不一定要非常漂亮,实用就好。

    建库建表

      准备: 创建分支

    $ git checkout master
    $ git checkout -b "start-admin-module"

      建表思路:

        根据博客模板,从首页开始分析,  分析哪些需要动态数据,以便建立对应数据表。

          用户: 登录, 注册, 修改, 删除

          文章: 分类管理, 博文管理, 评论管理

          角色管理: 管理员,普通用户

          菜单管理: 不同权限人员,对应菜单栏也有区别

        建表工具可以任意选择。初期手工写建表语句,熟悉后直接使用工具。 本项目中使用 Navicat 建立数据库和表

       数据库,表

        1) 创建数据库:php_blog

    create database php_blog charset utf8

        2) 用户表: y_users 

    CREATE TABLE `y_user` (
      `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '用户主键',
      `username` varchar(20) NOT NULL COMMENT '用户名',
      `password` char(32) NOT NULL COMMENT '密码',
      `email` varchar(50) NOT NULL DEFAULT '' COMMENT '注册邮箱',
      `token_email` varchar(32) NOT NULL DEFAULT '' COMMENT '邮箱验证',
      `status` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '状态, 0-正常,1-禁用',
      `gid` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '角色id,1-管理员,2-普通用户,0-无效',
      `login_ip` varchar(20) NOT NULL DEFAULT '' COMMENT '最后登录的ip地址',
      `login_times` smallint(6) unsigned NOT NULL DEFAULT '0' COMMENT '登录次数',
      `created_at` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '注册时间',
      `updated_at` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最后一次登录时间',
      PRIMARY KEY (`id`),
      UNIQUE KEY `username` (`username`),
      UNIQUE KEY `email` (`email`)
    ) ENGINE=MyISAM AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 COMMENT='用户表';
    用户表SQL

        3)角色表: y_user_group

    CREATE TABLE `y_user_group` (
      `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '角色id',
      `name` varchar(20) NOT NULL DEFAULT '' COMMENT '角色名称',
      `auths` varchar(255) NOT NULL DEFAULT '' COMMENT '角色权限',
      PRIMARY KEY (`id`)
    ) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COMMENT='角色表';
    角色表SQL

        4) 菜单表: y_menus

    CREATE TABLE `y_menus` (
      `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '菜单id',
      `title` varchar(20) DEFAULT '' COMMENT '菜单名称',
      `controller` varchar(30) DEFAULT '' COMMENT '控制器名称',
      `action` varchar(30) DEFAULT '' COMMENT '操作名称',
      `status` tinyint(1) unsigned DEFAULT '1' COMMENT '状态,1-正常,0-禁用',
      `is_hidden` tinyint(1) unsigned DEFAULT '0' COMMENT '是否隐藏,0-正常显示,1-隐藏',
      `sort` int(10) unsigned DEFAULT '0' COMMENT '排序',
      `pid` int(10) unsigned DEFAULT '0' COMMENT '上一级菜单',
      PRIMARY KEY (`id`)
    ) ENGINE=MyISAM DEFAULT CHARSET=utf8mb4 COMMENT='菜单表';
    菜单表SQL

        5) 文章表 y_article

    CREATE TABLE `y_article` (
      `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '文章id',
      `title` varchar(60) NOT NULL DEFAULT '' COMMENT '标题',
      `description` varchar(200) NOT NULL DEFAULT '' COMMENT '文章简介',
      `content` text NOT NULL COMMENT '内容',
      `cid` int(10) unsigned NOT NULL COMMENT '文章类别',
      `pic` varchar(150) NOT NULL DEFAULT '' COMMENT '文章封面图',
      `pic_watermark` varchar(150) NOT NULL DEFAULT '' COMMENT '水印图',
      `pic_thumb` varchar(150) NOT NULL DEFAULT '' COMMENT '缩略图',
      `uid` int(10) unsigned NOT NULL COMMENT '作者',
      `clicks` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '阅读数(点击数)',
      `updated_at` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '更新时间',
      `created_at` int(11) NOT NULL DEFAULT '0' COMMENT '发布时间',
      PRIMARY KEY (`id`),
      KEY `title` (`title`),
      KEY `uid` (`uid`),
      KEY `clicks` (`clicks`),
      KEY `cid` (`cid`) USING BTREE
    ) ENGINE=MyISAM AUTO_INCREMENT=4 DEFAULT CHARSET=utf8 COMMENT='文章表';
    文章表SQL

        6) 文章类别表 y_category

    CREATE TABLE `y_category` (
      `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '分类id',
      `catename` varchar(15) NOT NULL COMMENT '分类名',
      `description` varchar(255) NOT NULL DEFAULT '' COMMENT '简介',
      PRIMARY KEY (`id`)
    ) ENGINE=MyISAM AUTO_INCREMENT=15 DEFAULT CHARSET=utf8 COMMENT='文章类别表';
    文章类别表SQL

        7) 评论(回复)表 y_comment

    CREATE TABLE `y_comment` (
      `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '评论id',
      `uid` int(10) unsigned NOT NULL COMMENT '评论者',
      `created_at` int(11) DEFAULT NULL COMMENT '评论时间',
      `content` varchar(255) NOT NULL DEFAULT '' COMMENT '评论内容',
      `aid` int(10) unsigned NOT NULL COMMENT '被评论的文章',
      PRIMARY KEY (`id`)
    ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='评论(回复)表';
    评论(回复)表SQL

        8) session数据表 y_session  (其实可以不用这个,目的是为了操作 "将session写入数据库" )

    CREATE TABLE `y_session` (
      `sess_id` varchar(50) NOT NULL DEFAULT '' COMMENT 'session id',
      `data` text NOT NULL COMMENT 'session数据',
      `created_at` int(11) NOT NULL COMMENT 'session创建时间',
      PRIMARY KEY (`sess_id`)
    ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='session数据表';
    session数据表SQL

        为了避免弄的太复杂, 暂时建立这些数据表,字段后续可以进行调整。如果需要加入模块功能,可以相应增加相应数据表。

      连接数据库

        在badeModel中修改数据连接的数组信息 【Frame/BaseModel.class.php】  (如果使用配置文件类,此处就可以省略了)

     1 class BaseModel {
     2     。。。
     3     。。。
     4     。。。
     5     function __construct(array $config=null)
     6     {
     7         $conf = array(
     8             'host'=>'localhost',
     9             'user'=>'root',
    10             'pwd'=>'root',
    11             'port'=>'3306',
    12             'charset'=>'utf8',
    13             'dbname'=>'php_blog',
    14         );
    15         $conf = empty($config)? $conf : array_merge($conf,$config);
    16         $this->db = Db::getDb($conf);
    17     }
    18 }
    设置连接数据库信息

    配置文件类

      需求分析:

        为了框架便于数据库连接以及方便读取配置文件。如 希望在 App/Common/config.php 做一些配置项,要求能读取这些配置并应用到项目

      思路:

    step 1:  创建文件  App/Common/config.php  并将数据库连接信息写入该配置文件
    
    step 2:  在Frame/目录下创建读取配置文件类 Config.class.php
    
    step 3: 设置自动加载 读取配置类
    
    step 4: 基础模型类实例化 读取配置类。 操作数据库必须要经过基础模型类
    
    step 5:  调整数据库工具类获取配置信息,既 其构造方法中通过传递进来的数据配置信息对象获取
    
    step 6: 测试连接数据结果,验证获取配置
    实现连接数据库-读取数据库配置信息思路

      代码实现

        1) 创建配置文件config.php  【App/Common/Config.php】

    <?php
    /**
     * 配置文件
     * User: young
     */
    return [
        //数据库连接配置
        'host'=>'localhost',
        'user'=>'root',
        'pwd'=>'root',
        'port'=>'3306',
        'charset'=>'utf8',
        'dbname'=>'php_blog',
    ];
    配置文件-数据库配置信息

        2) 创建读取配置文件类 【Frame/Config.class.php】

     1 <?php
     2 /**
     3  * 配置文件读取类
     4  * User: young
     5  */
     6 
     7 class Config
     8 {
     9     protected static $ins = null;  //本类实例
    10     protected $cfg = array(); //存储配置项
    11 
    12     /**
    13      *  获取本类实例
    14      * @access public
    15      * @return  object     本类的单例对象
    16      */
    17     public static function getIns() {
    18         if(false === (self::$ins instanceof self)){
    19             self::$ins = new self();
    20         }
    21         return self::$ins;
    22     }
    23 
    24     /**
    25      *  构造方法: 读取配置项
    26      * @access public
    27      * @return  void
    28      */
    29     final protected function __construct() {
    30         require APP.'Common'.DS.'config.php'; //读取配置项
    31         $this->cfg = $cfg;
    32     }
    33 
    34     /**
    35      * 根据指定的配置项,返回该配置项的值
    36      * @param string $k  配置项
    37      * @return mixed|null 返回配置项的数据
    38      */
    39     public function __get($k) {
    40         if(!isset($this->cfg[$k])) {
    41             return null;
    42         }
    43         return $this->cfg[$k];
    44     }
    45 
    46 
    47     /**
    48      * 根据指定的配置项,返回配置项的值
    49      * @param  string $k 配置项名称
    50      * @param string $v 配置项对应的值
    51      */
    52     public function __set($k,$v) {
    53         $this->cfg[$k] = $v;
    54     }
    55 }

        3)  自动加载配置类

          需要自动加载该类, 该类在Frame目录下, 所以可以写入到 Init.class.php 类中的属性数组中   【Frame/Init.class.php】

     1 <?php
     2 /**
     3  * 初始化应用类
     4  * User: young
     5  */
     6 
     7 class Init
     8 {
     9     protected static $frame = array('BaseController','BaseModel','Db','FactoryModel','Config');
    10 。。。
    11 。。。
    12 。。。
    自动加载配置类

        4)基础模型类实例化配置类【Frame/BaseModel.class.php】

     1 <?php
     2 
     3 /**
     4  * BaseModel.class.php 基础模型类
     5  *     连接数据库
     6  *  @author young
     7  */
     8 class BaseModel
     9 {
    10     protected $db = null;
    11     /**
    12      * 构造方法: 实例化数据库类
    13      * @access public
    14      */
    15     function __construct()
    16     {
    17        $conf =  Config::getIns(); //读取配置项实例
    18         $this->db = Db::getDb($conf);
    19     }
    20 }

        5)数据库读取配置项信息  【Frame/Db.class.php】     

     1 <?php
     2 /**
     3  * Db.class.php 数据库操作工具类
     4  * @author young
     5  */
     6 
     7 class Db {
     8 。。。
     9 。。。
    10 。。。
    11     /**
    12      * 构造方法: 保存数据库连接信息,连接数据库
    13      * @access private
    14      * @param array $conf 数据库连接信息
    15      */
    16     private function __construct($conf)
    17     {
    18         $this->host = $conf->host;
    19         $this->user = $conf->user;
    20         $this->pwd = $conf->pwd;
    21         $this->port = $conf->port;
    22         $this->charset = $conf->charset;
    23         $this->dbname = $conf->dbname;
    24         $this->connect();
    25     }
    26 。。。
    27 。。。
    28 。。。
    29 }
    数据库工具类获取配置信息

        6) 测试 在App/Controller/Home/DemoController.class.php  用于测试数据库连接情况

    <?php
    /**
     * 测试控制器类
     * User: young
     */
    
    class DemoController extends BaseController
    {
        public function test()
        {
            $db = new BaseModel();
            $data = $db->db->getAllRows("select * from y_user");
            var_dump($data);
        }
    }
    测试控制器类测试连接数据库

      注: 前提,需要将BaseModel.class.php中的$db属性先临时修改为public公开,才能测试成功 (原因:在Demo控制器中实例化的基础模型类,数据库操作实例是放在类的属性db中,外部不能访问protected属性), 本节所有测试,可以临时将db设置为公开的。

    还可以使用配置如: 上传目录,网站配置信息等,根据需求自定义配置需求,再通过读取配置类读取配置的数据

    提交代码

    git add -A
    git commit -m "完成读取配置文件类"

    错误日志记录

      除了开发阶段调试错误, 项目上线一般会将错误信息写入指定文件中。安全性更好。

      需求分析:

        将错误写入日志文件中,这里暂时主要记录数据库操作的错误。 如:默认将错误记录在App/log/logError.txt。 如果在配置文件中进行了配置,则将日志信息写入到配置项log指定的目录中

      思路:

    step 1: 制作日志类Frame/Log.class.php, 用于将错误信息写入到指定文件中。  (设置日志文件位置,正好可以利用上面写的配置项,通过读取配置来实现)
    
    step 2: 在基础模型类BaseModel中,读取配置项后, 可以将日志目录路径写入常量。 使用try..catch 捕捉异常,将错误写入日志
    
    step 3: 实现日志类自动加载。Log类在Frame目录中,所以只要在初始化应用类Init中的属性$frame数组中加入 “Log”
    
    step 4: 记录错误。 数据库连接可能失败, sql语句可能执行失败
    
    step 5: 测试错误日志记录功
    实现错误日志记录过程思路

       代码实现

      1) 制作错误日志类 【Frame/Log.class.php】

     1 <?php
     2 /**
     3  * 日志类
     4  * User: young
     5  */
     6 
     7 class Log
     8 {
     9     /**
    10      * 记录错误信息到文件中
    11      * @param string $err 错误信息
    12      */
    13     public static function write($err)
    14     {
    15         date_default_timezone_set('PRC'); //时区设置
    16         //打开文件
    17         $fh = fopen(LOG.'log.txt','a'); // 追加方式打开
    18 
    19         //拼接信息
    20         $err = date('Y年m月d日 H:i:s',time()) . "	
    " . $err . "	
    ";
    21 
    22         //写入
    23         fwrite($fh,$err);
    24 
    25         //关闭
    26         fclose($fh);
    27     }
    28 }

      2)  读取日志位置,捕捉错误  【Frame/BaseModel.class.php】

        发生错误记录后,这里只是简单使用exit(..)退出, 可以自定error错误页面会更好

     1 <?php
     2 
     3 /**
     4  * BaseModel.class.php 基础模型类
     5  *     连接数据库,捕捉记录错误
     6  *  @author young
     7  */
     8 class BaseModel
     9 {
    10     Public $db = null;
    11     /**
    12      * 构造方法: 实例化数据库类
    13      * @access public
    14      */
    15     function __construct()
    16     {
    17         $conf =  Config::getIns(); //读取配置项实例
    18 
    19         //读取日志配置项目 并写成常量
    20         $logPath = $conf->log;
    21         $logPath = !isset($logPath) ? APP."log".DS  : $logPath;
    22         define('LOG',$logPath);
    23 
    24         //监控数据库操作
    25         try {
    26             $this->db = Db::getDb($conf);
    27         }catch(Exception $e) {
    28             $err = '';
    29             $err .= '错误代码:' . $e->getCode() . "
    ";
    30             $err .= '错误信息:' . $e->getMessage() . "
    ";
    31             $err .=  '文件:' . $e->getFile() . "
    ";
    32             $err .=  '行号:' . $e->getLine() . "
    
    ";
    33             Log::write($err);
    34             exit("<h2>客官!页面暂时无法响应,请稍后访问</h2>");
    35         }
    36     }
    37 }
    点击查看【基础模型类中监测并记录错误】

      3)自动加载日志记录类 【Frame/Init.class.php】

     1 <?php
     2 /**
     3  * 初始化应用类
     4  * User: young
     5  */
     6 
     7 class Init
     8 {
     9     protected static $frame = array('BaseController','BaseModel','Db','FactoryModel','Config','Log');
    10 。。。
    11 。。。
    12 。。。
    点击查看【自动加载日志类】

      4) 记录错误  【Frame/Db.class.php】

    数据库连接可能发生错误处理

     1  class Db
     2 {
     3 。。。
     4 。。。
     5 。。。
     6     /**
     7      * 连接数据库,设置编码,选库
     8      * @access private
     9      */
    10     private function connect()
    11     {
    12         $this->link = @ mysql_connect("{$this->host}:{$this->port}", "$this->user", "$this->pwd") ;
    13         if(!$this -> link) {
    14             $error = new Exception("数据库连接不上",10000);
    15             throw $error;
    16         }
    17         $this->setCharset($this->charset);
    18         $this->useDb($this->dbname);
    19     }
    20 。。。
    21 。。。
    22 。。。
    点击查看【数据库连接错误抛出】

    sql语句发生错误处理

     1  class Db 
     2 {
     3 。。。
     4 。。。
     5 。。。
     6     /**
     7      * 执行sql语句
     8      * @param  string $sql sql语句
     9      * @return mixed
    10      */
    11     private function query($sql)
    12     {
    13         $result = mysql_query($sql, $this->link);
    14 //        if(false === $result) {
    15 //            echo "<p>sql执行失败!<br>";
    16 //            echo "<br>失败语句:".$sql;
    17 //            echo "<br>错误代号".mysql_errno();
    18 //            echo "<br>错误提示: ".mysql_error()."</p>";
    19 //            exit();
    20 //        }
    21         if(false === $result) {
    22             $err = "sql执行失败!
    失败语句:".$sql."
    错误代号:".mysql_errno()."
    错误提示:".mysql_error()."
    
    ";
    23             Log::write($err);
    24             exit("<h2>查询出错,请稍后访问</h2>");
    25         }
    26         return $result;
    27     }
    28 。。。
    29 。。。
    30 。。。
    点击查看【执行SQL错误处理】

      测试

      可以在【App/Common/config.php】中配置日志文件目录。 如果不进行配置, 默认记录在App/log/目录中

     1 <?php
     2 /**
     3  * 配置文件
     4  * User: young
     5  */
     6 return [
     7     //数据库连接配置
     8     。。。
     9 、 。。。
    10     。。。
    11 
    12     //日志文件位置配置
    13     'log' => APP,
    14 ];
    点击查看【日志文件配置】

      以下测试可以 开启配置项中的配置log  和关闭后分别测试。  注意: 如果没有做配置log, 则要首先在App目录下建立一个log目录

       1. 在配置文件中故意写错数据库连接信息,如密码写错

       2. 执行sql错误

    最后说明: 配置目录,日志目录都是不希望浏览器直接访问的,所以需要将.htaccess文件放入目录中 (由于App目录中已经存在,故也可以省略)

    提交传送代码

    git add -A
    git commit -m "完成日志类"
    git checkout master
    git merge start-admin-module
    git push origin master

     小结: 本篇主要实现了 框架清理,博客数据库表搭建,创建配置读取类,日志记录类。

        实际上,到此仍然只是更加完善了一下框架结构,增加了2个功能。正如前篇所提,还有很多是可以改进的。这里就暂时不再继续增加功能了。

    提出问题:

      1. 如何使用该自制框架搭建项目 ==> 用户操作+mvc实现

      2. 如何着手使用ajax实现后台登录功能  ==> ajax应用

      3. 如何着手实现分类模块功能,它有哪些操作 ==> 增删改查

    下一步: 后台模板视图制作,后台登录,文章分类模块功能。

  • 相关阅读:
    查询父节点parentNode
    008-流程控制 case 语句
    007-流程控制 if 语句
    006-条件判断
    005-sort 命令使用
    004-sed 命令使用
    003-awk 命令使用
    002-printf 命令用法
    001-cut 的用法
    002-变量
  • 原文地址:https://www.cnblogs.com/yangp67/p/9268767.html
Copyright © 2011-2022 走看看