后台管理员权限分级表的设计

在web1.0时期,一个网站普遍只有一个管理员,管理员登录网站, 对网站的内容进行增删改查, SNS流行后, 一个网站管理员已经不能满足当前环境的所需,这个时候就需要拥有不同权限的后台管理账户, 比如文章管理员, 不能让他有添加管理员的权限, 只让超级管理员拥有全局的权限。这个时候,就要对管理员表进行设计。

我们选用的是角色权限控制, 所以得需要一张角色表,需要根据不同角色访问不同的页面, 还需要一个规则, 需要存储账户密码信息, 还需要一张存储账户密码信息表, 一共三张表。

my_admin_user表

一个索引id
账户username
密码password
密码混淆(key)solt
当前账户角色 role_id

my_admin_role角色表

索引id

角色名roleName

角色描述

规则名称

my_admin_rule规则表

一个索引id
一个规则

可以根据角色id进入规则, 根据规则id选择进入不同的页面,也可以根据此判断账户权限。

发表在 mysql | 标签为 , , , | 后台管理员权限分级表的设计已关闭评论

Thinkphp5入门二使用验证码类

Thinkphp官方给提供了一个很好的处理验证码的扩展, 下载地址在这里 Thinkphp验证码类 下载回来后,需要放到thinkphp核心目录下。 回到Login.php文件, 新建一个方法

function verify()
    {
        $Verify = new \org\Verify();
        $Verify->entry();
    }

回到模板文件, 调用

{:U('Verify')}

刷新页面, 验证码就出来了。

{:U()} 为模板用法, 可以根据当前路径和模式自动生成对应的url地址, 本例是生成当前模块的Verify地址。

发表在 thinkphp5 | 标签为 , , | Thinkphp5入门二使用验证码类已关闭评论

Thinkphp5入门一

Thinkphp项目的发起人为中国内地的著名程序员刘晨,到2016年2月为止,已经经历了数个版本,目前的最新版为ThinkPHP5.0.0 RC1,所以我们就从tp5开始看起。

tp5的下载地址为Thinkphp5下载 下载回来以后, 可以看到三个主目录, 和目录下的一些文件, application是应用目录,里面放的是应用的配置文件, 控制器, 模型,视图什么的, public是部署目录, 里面放的是入口文件, htaccess, 什么的, 可以从index.php文件里看到它具体都做了什么

// 应用入口文件

// 定义项目路径
define('APP_PATH', __DIR__ . '/../application/');
// 开启调试模式
define('APP_DEBUG', true);

// 加载框架引导文件
require __DIR__ . '/../thinkphp/start.php';
// 执行应用
\think\App::run();

使用常量形式定义了应用目录路径,加载了核心模块下的start.php引导文件, 然后使用类名APP:run(); 方法名, 完成初始化和运行。

thinkphp是框架的核心目录, 里面是系统封装好的一些类, 扩展类,第三方类, 方法常量配置文件,模板,引导文件什么的,把上述内容了解清楚后,将thinkphp目录解压到htdocs目录下,或者新建一个目录,取名tp或者其他,把文件放入目录, 然后访问

http://localhost/public

如果你看到了一个笑脸加一行字, 欢迎使用Thinkphp5,就说明Thinkphp已经部署成功了,这个时候, 我们就可以进行一下简单的测试,在测试之前, 要说的是, thinkphp5的url访问模式在没有进行url重写的情况下默认是这样的

http://localhost/入口引导文件/模块/类名/方法名

知道了这些以后, 我们就可以前往application目录, 新建一个test目录,然后在test目录里建一个controller目录, 在目录里建立一个Test.php(首字母大写), 然后编写文件

<?php

namespace app\test\controller;

class Test
{
    function hi()
    {
        echo 'Hello Word';
    }
}

访问

http://127.0.0.1/t5/public/test/test/hi

出现Hello Word提示, 就说明成功了, 需要注意的是, 类名必须要和文件名对应, 因为thinkphp的定义是一个php文件即是一个类, 名字不同会报错。 前面我们知道了, thinkphp采用的是面向对象思想, MVC结构, 所以在进行实例项目的时候, 就可以分别建立三个目录, 对应 模型/视图/控制器, 视图下面放置模板文件, 使用控制器处理, 模型负责数据交互。 如果要写后台, 就可以按照这个来, 比如

在应用目录下建立 admin目录, 在admin目录里建立controller,view,model目录, 在controller目录里建立一个Login.php对应后台入口,把html模板放到view二级目录下, 类名对应二级文件夹名,比如Login类的模板就为view/login/index.html, 依次类推, 然后再把模板的css,js文件放到可以被直接访问的目录下, 修改好文件中的路径, 在Login.php里写入

<?php

namespace app\admin\controller;
use think\Controller;
use think\controller\Rest;

class Login extends Rest
{
    function index()
    {
        $controller = new Controller();
        return $controller->fetch();
    }
}

访问

http://localhost/public/admin/login

出现后台页面, 就说明模板渲染成功了。

发表在 thinkphp5 | 标签为 , , , , | Thinkphp5入门一已关闭评论

理解MVC

Model ———–和数据库操作有关的类

View ———-视图层,展现出的部分

Controller —— 负责处理视图层和模型的交互

用户通过View提交表单, Controller处理决定是否调用Model, 如果调用会返回信息,Controller再把信息反馈给View。

发表在 php | 理解MVC已关闭评论

php文件系统目录递归部分一

<?php
header("Content-Type:text/html;charset=gb2312");
date_default_timezone_set('PRC');
$dir = 'filesys';
$dirname = opendir($dir);
while($filename = readdir($dirname))
{
  $file = $dir.'/'.$filename;
  if($filename != '.' && $filename != '..')
    {
      if(is_file($file))
        {
          echo '<font color="red">'.$filename.'------'.'是文件!'.'</font>'.'-------'.'文件创建日期:'.date('Y-m-d H:i:s',filectime($file)).'------'.'文件大小:'.toSize(filesize($file)).'<br>';
        }
        else
        {
            echo '<font color="green">'.$filename.'</font>'.'------'.'目录大小:'.toSize(dirsize($file)).'<br>';
        }
    }
}

function toSize($size)
{
    $dw = 'Byte';
    if($size >= pow(2,30))
    {
        $size = round($size/pow(2,30),2);
        $dw = 'GB';
    }
    else if($size >= pow(2,20))
    {
        $size = round($size/pow(2,20),2);
        $dw = 'MB';
    }
    else if($size >= pow(2,10))
    {
        $size = round($size/pow(2,10),2);
        $dw = 'KB';
    }
    else
    {
        $dw = 'Byte';
    }
    return $size.$dw;
}

function dirsize($dirname)
{
 $dirsize = 0;
 $dir = opendir($dirname);
 while($filename = readdir($dir))
    {
      $file = $dirname.'/'.$filename;
      if($filename != '.' && $filename != '..')
        {
           if(is_dir($file))
            {
               $dirsize+=dirsize($file);
            }
            else
            {
                $dirsize+=filesize($file);
            }
        }
    }
    return $dirsize;
}

dirsize接收传入的是一个目录资源,实际为filesys/images这样的格式, 进入到while后, 就会读出images里的每一个文件, 然后拼接一个images/filename.php 的当前目录, 再然后进入到判断, 如果是一个目录, 就再次调用自身进行readdir, 因为实际打开句柄后, 都已经成了images/xxx.xxx的格式, 所以进入到else执行filesize相加, 最后return出目录总大小得出结果。

发表在 php | 标签为 , , | php文件系统目录递归部分一已关闭评论

php修改文件

<?php

if(isset($_POST['sub']))
{
    setConfig($_POST);
}
function setConfig($post)
{
    $zz = array();
    $rep = array();
    $str = file_get_contents("config.inc.php");
    foreach($post as $key=>$value)
    {
        $zz[] = "/define\("{$key}",\s*.*?\);/i";
        $rep[] = "define("{$key}","{$value}");";
    }
    $str = preg_replace($zz,$rep,$str);
    file_put_contents("config.inc.php",$str);
}
?>
<html>
<head>
<title>Install Test</title>
</head>
<body>
<form action="" method="post">
DB_USER: <input type="text" name="DB_USER">
DB_PASS: <input type="text" name="DB_PASS">
<input type="submit"  name="sub" value="change">
</form>
</body>
</html>

检测到表单提交sub变量后, 就会进入到正, 正里面是一个函数处理$_POST接收到的数组, 来到setConfig函数, 该函数提供了一个形式参数$post接收传入信息, 然后创建了两个用来匹配的空数组,再往下获取原文件内容, 然后通过foreach遍历出所有key和value, 循环第一次的时候, 第一个$zz匹配出了原文件内容($key), 第二个匹配出了传入的新内容($key $value), 然后执行替换, 因为符合正则条件,所以执行替换, 最后把替换结果写入原文件。

发表在 php | 标签为 , , | php修改文件已关闭评论

php文件操作函数

<?php

/*

 Type:getFile function
 Date:2016/2/2

*/
date_default_timezone_set('PRC');
function getFile($filename)
{
    if(!file_exists($filename))
    {
        echo "{$filename},不存在!";
    }
    else
    {
        echo "{$filename}类型为".filetype($filename).'<br>'.'大小为:'.getFileSize(filesize($filename)).'<br>'.'创建时间为:'.date('Y-m-d H:i:s',filectime($filename)).'<br>'.'最后一次修改时间为:'.date('Y-m-d H:i:s',filemtime($filename)).'<br>'.'最后一次访问时间为'.date('Y-m-d H:i:s',fileatime($filename)).'<br>';
    }
    if(is_dir($filename))
    {
        echo "{$filename}是一个目录!".'<br>';
    }
    if(is_file($filename))
    {
        echo "{$filename}是一个文件!".'<br>';
    }
    if(is_readable($filename) && is_writeable($filename))
    {
        echo "{$filename}可读!也可以写!".'<br>';
    }
    if(is_executable($filename))
    {
        echo "{$filename}可执行!".'<br>';   //测试出现了问题, 该函数有可能在清除缓存后也会存在判断错误的问题。。
    }
}
function getFileSize($filesize)
{
    $company = 'Byte';
    if($filesize>=pow(2,40))
    {
        $filesize = round($filesize/pow(2,40),2);
        $company = 'TB';
    }
    else if($filesize>=pow(2,30))
    {
        $filesize = round($filesize/pow(2,30),2);
        $company = 'GB';
    }
    else if($filesize>=pow(2,20))
    {
        $filesize = round($filesize/pow(2,20),2);
        $company = 'MB';
    }
    else if($filesize>=pow(2,10))
    {
        $filesize = round($filesize/pow(2,20),2);
        $company = 'KB';
    }
    else
    {
        $company = 'Byte';
    }
    return $filesize.$company;
}
getFile('test.txt');

讲讲那个计算文件大小的, 首先是, 这个计算是按相对计算的, 因为空间没有绝对大小, 每个硬件厂商的计算标准都不同, 比如第一个, 2的40次方为1099511627776(B), 又知道了, 计算的级别单位为1024, 比如1mb = 1024kb, 故计算TB就为1024*1024*1024*1024*1024 (B,KB,MB,GB,TB), 如果符合大于或者等于的这个条件, 就进入该结果, 把company重新赋值为TB, 依次类推, 最后返回传入的大小.最终的单位。使用round精确到2位里面给一个除法的也很好理解, 就是比如如果不大于等于2的40次方,就会进入下一个循环,然后直到找到符合条件的,计算和传入的都是B,比如到MB符合了,传入的为 1148576,那么进入循环体,经过计算后,结果就约等于1MB。 那个is_executable函数我在实际使用的时候遇到了问题, 就是突然失效了。。

发表在 php | 标签为 , , , , | php文件操作函数已关闭评论

php正则表达式中常用的模式修正符

模式修正符是用来扩展正则匹配的, 意思是可以开辟更多的匹配空间或者是修正一些匹配模式,在有的语言中的正则没有这个模式修正符,因为我最近正在学习php,所以本篇说的就是php中的环境。前面我们知道了,模式修正符是被用来修饰正则匹配模式的,也可以说扩展正则匹配,它是被用到定界符之外的,如果不和正则配合使用,就是普通的字母。 那就来看几个常见的模式修正符。

1. i 匹配大小写(不区分大小写)

比如我们要匹配一段话, 这段话里既有小写, 又有大写, 而我们模式里匹配的只有小写, 就可以通过加模式修正符i的方式让他同时匹配大小写。

<?php
/*

不区分大小写匹配

*/
$p = "/imfinal/i";
$s = "thisisAImFinAltesta";
$result = preg_match($p,$s,$arr);
print_r($arr);

当然, 在不存在模式修正符的语言里, 我们还可以这样

<?php
/*

不区分大小写匹配

*/
$p = "/im\wfinal/";
$s = "thisisAImFinAltesta";
$result = preg_match($p,$s,$arr);
print_r($arr);

一样是匹配的到的

2. m 匹配多行 (把一行的每个段落都当作一个新行)

<?php
/*

把每一个段落当成一行匹配

*/
$p = "/^abc/im";
$s = "dfssadg
dsafa
QWW
WDWQFD
abw
addf
abc
www
Abc
";
$result = preg_match_all($p,$s,$arr);
print_r($arr);

匹配abc开头, 因为使用了i和m修饰, 就会忽略大小写和把每一一个换行都当成一个新行匹配,因为用了all, 所以会匹配出所有解决, abc Abc。

3. s 匹配单行, 把所有的段落当成一个匹配, 如果存在.就匹配换行符

<?php
/*

把所有段落当成一行匹配,如果这个时候模式里用了.就会重新匹配换行符,因为修正符里使用了s已经把字符串修正成了一行。

*/
$p = "/^ab.+c/is";
$s = "abcdfssadg
dsafa
QWW
WDWQFD
abw
addf
abc
www
Abc
";
$result = preg_match_all($p,$s,$arr);
print_r($arr);

4. A 匹配必须以什么开头(和^同义)

<?php

$p = "/abc/imA";
$s = "abcalsdfkjadf
abc
Abcdfegfwr
aaaaafd
aBc
dsccdvc
aaaabc";
if(preg_match_all($p,$s,$arr))
{
    print_r($arr);
}

i不区分大小写, m把每一个段落都当成一个新行匹配, A表示必须以abc开头, 要注意的是,这里只会匹配第一行,因为强制要求了abc开头, 所以这里实际上又把它当成了一行。

5. x 忽略正则匹配模式中的空格

<?php

$p = "/a b c/imx";
$s = "aaaddfsdgfthisisaabcsfdf";
if(preg_match_all($p,$s,$arr))
{
    print_r($arr);
}

继续阅读

发表在 正则 | 标签为 , , | php正则表达式中常用的模式修正符已关闭评论

php正则表达式之元字符

前面我们知道了,正则表达式是由定界符,原子,元字符,模式修正符组成的,原子是正则中的基本组成单位,它可以独立使用,元字符是用来修正原子的,今天就再来复习一下几个元字符的用法。比如* 我们前面说了,*的意思是在此之前的原子可以出现0次1次或者多次,如果想把它作为元字符使用\*转义掉就可以了。所以它的作用就不详细介绍了。继续下面的。

+ 在此之前的原子可以出现一次或者多次, 意思是至少要出现一次。

? 在此之前的原子可以出现0次或者1次。

{} 自定义在此之前原子的重复次数,可以是单数也可以是一个范围{x,n}至少几次,最大几次。

. 匹配除了换行外的任意字符。

| 或者的意思, 提供一个选项, 匹配中一个即可。

() 子匹配模式, 正则匹配完全文后会首先去查找子匹配正则。也可以在()内使用?:取消该子模式,结果是一个数组,第一个子模式就放到第一个元素当中,可以把子模式取出来再当成正则表达式的一部分,取出第一个子模式用\1..

\b 匹配边界。

\B 匹配非边界。

^ 在原子表中使用代表取反, 在正则中使用代表要以它为开头。

$ 匹配一个结尾

<?php

$p = '/ax+b/';
$s = 'axb';
if(preg_match($p,$s))
{
    echo "匹配成功";
}

x出现了一次, 所以匹配成功。

<?php

$p = "/^a\B\d{2}(\W)\s\\1\d{2,4}$/";
$s = "a23/ /5678";
if(preg_match($p,$s,$arr))
{
    print_r($arr);
}

^a匹配出了以a开头\B匹配出了非边界\d{2}匹配出了两位十进制数,\W匹配出了非a-zA-Z0-9_ \s匹配出了空格和空字符\1引用了第一个子匹配模式,\d{2,4}$匹配出了必须要以至少2位最多4位的十进制数字为结尾,合在一起就是匹配出了结果,a23/ /5678 ,php正则中可以有多个子匹配模式, 如果给了$arr这个参数, 就会按数组的索引排列 $arr[1],$arr[2] ..以此类推。

发表在 正则 | 标签为 , , , | php正则表达式之元字符已关闭评论

php正则表达式入门

之前学python的时候看过python里的正则, 也就是re, 最近这段时间看php, 看到了正则, 也就把正则从新复习了一遍。 其实正则也可以说是一种编程语言, 它和asm一样, 可以嵌套到很多程序当中去, 进行删除,修改,替换。说到正则,首先应该想了, 什么是正则? 正则就是描述字符串排列模式的一种自定义的语法规则,它本身也是属于是一段字符串,要和函数配合使用。 正则是由定界符,原子,元字符,模式修正符组成的,除了数字,字母和\的任意其他字符都可以被用来当作定界符,定界符的作用就是定界开始和结束,在正则中可以单独使用的字符都可以被称为原子, 比如\s \d \t \r src img, 如果想要在原子中使用具有特殊意义的字符, 比如这个字符既属于元字符还想在原子中使用, 即可以把它使用\转义, 元字符是用来被修饰原子的, 比如匹配<>中的任意十进制数字, 就可以使用<\d>, 可以使用[]表示是一个原子表,比如匹配一定范围的内容[1234567],即代表匹配原子表中的任意一个数字, 如果不加中括号, 即代表匹配的是一个连贯的数字,还可以在原子表中的第一个字符前加^表示取反,可以使用-代表一个范围。现在php沿用的正则是与perl兼容的, 下面就来看几个例子。

首先说一下, 几个常见的匹配原子和元字符

\d 匹配任意十进制数

\D 匹配任意非数字

\s 匹配任意空白和空白字符

\S 匹配任意非空白

\w 匹配a-zA-Z0-9_

\W 匹配非a-zA-Z0-9_

* 匹配任意字符0次或者多次 (php中的元字符*作为元字符使用时不能单独使用,要配合原子使用,修饰自身之前原子)

+ 匹配任意字符一次或者多次 (至少要出现一次,修饰自身之前原子)

^ 取反

下面来看一个例子

该函数的意思是执行一个正则表达式匹配,支持 php4,5,7。

int preg_match ( string $pattern , string $subject [, array &$matches [, int $flags = 0 [, int $offset = 0 ]]] )

第一个变量是一个字符串,代表的是一个匹配模式, 也就是正则, 第二个是被匹配的字符串, 也就是输入的信息,第三个$matches代表的是如果给它提供了参数它将会被填充为结果, 同时它支持数组用法, 如果$matches[0]代表的是将完整的匹配模式匹配到文本,$matches[1]代表的是第一个子匹配模式匹配到文本..flags提供了一个参数PREG_OFFSET_CAPTURE,如果使用了该参数即代表会对每一个匹配的结果附加字符串偏移量。 $offset指定搜索位置, 单位是字节, 可以指定从x字节位开始搜索。 一般情况下, 我们只需要用到$pattern 和 $subject。 如果preg_match匹配失败, 将会返回false。

<?php

$pat = '/\d/';
$s = '01234567a.zd';
if(preg_match($pat,$s))
{
    echo '我已经被匹配出来了';
}
else
{
    echo '匹配失败了!';
}

///////////////////
<?php

$pat = '/123456789/';
$s = '012349a.zd';
if(preg_match($pat,$s))
{
    echo '我已经被匹配出来了';
}
else
{
    echo '匹配失败了!';
}

因为\d代表的是匹配十进制数的0-9, 匹配的字符串里虽然包含了非数字的信息, 但是也包含了十进制数0-9之间的几个数, 所以会提示, 我已经被匹配出来了。 但是如果匹配采用的是实际意义的数字, 并且不是属于原子表,即代表必须包含这些连贯的数字, 所以会提示, 匹配失败了。

<?php

$pat = '/\D/';
$s = '0123456789';
if(preg_match($pat,$s))
{
    echo '我已经被匹配出来了';
}
else
{
    echo '匹配失败了!';
}

匹配非数字, 所以会提示, 匹配失败了!

<?php

$pat = '/\s/';
$s = ' \r \t \n \p ';
if(preg_match($pat,$s))
{
    echo '我已经被匹配出来了';
}
else
{
    echo '匹配失败了!';
}

匹配字符中包含空格也包含空格符, 所以匹配成功。

<?php

$pat = '/\w/';
$s = '09838292732712aAJDIJSKZzjss_as()';
if(preg_match($pat,$s))
{
    echo '我已经被匹配出来了';
}
else
{
    echo '匹配失败了!';
}

包含数字和字母中的匹配, 所以提示, 我已经被匹配出来了。 其它的以此类推。 比如匹配一个范围

<?php

$pat = '/[0-9]/';
$s = 'asasdasfdas';
if(preg_match($pat,$s))
{
    echo '我已经被匹配出来了';
}
else
{
    echo '匹配失败了!';
}

因为匹配的是0-9之间的任意数字,所以会提示, 匹配失败。

<?php

$pat = '/[^0-9]/';
$s = 'asasdasfdas';
if(preg_match($pat,$s))
{
    echo '我已经被匹配出来了';
}
else
{
    echo '匹配失败了!';
}

匹配非0-9, 所以会提示, 我已经被匹配出来了 。 表面上看, 正则很乱, 没有顺序的样子 ,其实正则也是具有一定意义的语法规则, 只要了解了它的组成和用法用起来也很简单。

发表在 正则 | 标签为 , , | php正则表达式入门已关闭评论