├── README.md ├── SearchController.php ├── Page.php ├── Code.php ├── Tpl.php ├── Image.php ├── Upload.php └── Model.php /README.md: -------------------------------------------------------------------------------- 1 | # - 2 | 我 的代码 3 | -------------------------------------------------------------------------------- /SearchController.php: -------------------------------------------------------------------------------- 1 | user = new UserModel(); 18 | $this->details = new DetailsModel(); 19 | $this->reply = new ReplyModel(); 20 | } 21 | 22 | 23 | function cha() 24 | { 25 | 26 | //判断是否登录 27 | if (!empty($_SESSION['username'])) { 28 | $username = $_SESSION['username']; 29 | $u = $this->user->getByUsername($username); 30 | $udertype = $u[0]['udertype']; 31 | $pic = $u[0]['picture']; 32 | $this->assign('username',$username); 33 | $this->assign('pic',$pic); 34 | $this->assign('udertype',$udertype); 35 | } 36 | //帖子展示 37 | 38 | $name = $_GET['name']; 39 | $total = $this->details->mucount($name); 40 | 41 | $page = new Page('3',$total); 42 | $allPage = $page->allPage(); 43 | $limit = $page->limit(); 44 | $message = $this->details->muhu1($name,$limit); 45 | 46 | //最新发表 47 | $article = $this->details->field('title,id')->table('bg_details')->where('isdel=0')->order('id desc')->limit('0,10')->select(); 48 | 49 | 50 | //点击排行 51 | $hits = $this->details->field('title,id')->table('bg_details')->where('isdel=0')->order('hits desc')->limit('0,5')->select(); 52 | 53 | $this->assign('total',$total); 54 | $this->assign('allPage',$allPage); 55 | $this->assign('hits', $hits); 56 | $this->assign('article',$article); 57 | $this->assign('message',$message); 58 | 59 | 60 | $this->display(); 61 | } 62 | } -------------------------------------------------------------------------------- /Page.php: -------------------------------------------------------------------------------- 1 | number = $number; 21 | $this->totalCount = $totalCount; 22 | 23 | //得到总页数 24 | $this->totalPage = $this->getTotalPage(); 25 | //得到当前页 26 | $this->page = $this->getPage(); 27 | //得到url 28 | $this->url = $this->getUrl(); 29 | // echo $this->url; 30 | } 31 | 32 | protected function getTotalPage() 33 | { 34 | return ceil($this->totalCount / $this->number); 35 | } 36 | 37 | protected function getPage() 38 | { 39 | if (empty($_GET['page'])) { 40 | $page = 1; 41 | } else { 42 | $page = $_GET['page']; 43 | } 44 | return $page; 45 | } 46 | 47 | protected function getUrl() 48 | { 49 | //得到协议 50 | $scheme = $_SERVER['REQUEST_SCHEME']; 51 | //得到主机名 52 | $host = $_SERVER['SERVER_NAME']; 53 | //得到端口号 54 | $port = $_SERVER['SERVER_PORT']; 55 | //得到文件路径和参数 56 | $pathData = $_SERVER['REQUEST_URI']; 57 | 58 | // index.php?username=goudan&page=3 59 | //对url进行处理,有page参数,将page参数干掉 60 | $data = parse_url($pathData); 61 | //得到文件路径 62 | $path = $data['path']; 63 | //判断有没有query,如果有,将里面的page干掉 64 | if (!empty($data['query'])) { 65 | //将query中page干掉 66 | parse_str($data['query'], $arr); 67 | unset($arr['page']); 68 | //将其他的参数再次拼接 69 | $query = http_build_query($arr); 70 | //将其拼接到path后面 71 | $path = $path.'?'.$query; 72 | 73 | } 74 | $path = trim($path, '?'); 75 | 76 | //根据上面的所有信息拼接你的url hebe 77 | $url = $scheme.'://'.$host.':'.$port.$path; 78 | return $url; 79 | } 80 | 81 | protected function setUrl($str) 82 | { 83 | if (strstr($this->url, '?')) { 84 | return $this->url.'&'.$str; 85 | } else { 86 | return $this->url.'?'.$str; 87 | } 88 | } 89 | 90 | //首页url 91 | function first() 92 | { 93 | return $this->setUrl('page=1'); 94 | } 95 | //上一页url 96 | function prev() 97 | { 98 | if ($this->page - 1 < 1) { 99 | $page = 1; 100 | } else { 101 | $page = $this->page - 1; 102 | } 103 | return $this->setUrl('page='.$page); 104 | } 105 | //下一页url 106 | function next() 107 | { 108 | if ($this->page + 1 > $this->totalPage) { 109 | $page = $this->totalPage; 110 | } else { 111 | $page = $this->page + 1; 112 | } 113 | return $this->setUrl('page='.$page); 114 | } 115 | //尾页url 116 | function end() 117 | { 118 | return $this->setUrl('page='.$this->totalPage); 119 | } 120 | 121 | function allPage() 122 | { 123 | return [ 124 | 'first' => $this->first(), 125 | 'prev' => $this->prev(), 126 | 'next' => $this->next(), 127 | 'end' => $this->end(), 128 | ]; 129 | } 130 | 131 | function limit() 132 | { 133 | $offset = ($this->page - 1) * $this->number; 134 | return $offset.','.$this->number; 135 | } 136 | } 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | -------------------------------------------------------------------------------- /Code.php: -------------------------------------------------------------------------------- 1 | number = $number; 28 | $this->codeType = $codeType; 29 | $this->width = $width; 30 | $this->height = $height; 31 | $this->imageType = $imageType; 32 | 33 | //调用生成验证码函数 34 | $this->code = $this->getCode(); 35 | } 36 | 37 | //在析构方法中将图像资源销毁 38 | function __destruct() 39 | { 40 | imagedestroy($this->image); 41 | } 42 | 43 | //生成验证码字符串 44 | protected function getCode() 45 | { 46 | switch ($this->codeType) { 47 | //纯数字类型 48 | case 0: 49 | $code = $this->getNumberCode(); 50 | break; 51 | //纯字母类型 52 | case 1: 53 | $code = $this->getCharCode(); 54 | break; 55 | //字母数字混合型 56 | case 2: 57 | $code = $this->getNumCharCode(); 58 | break; 59 | default: 60 | exit('不支持这个类型'); 61 | } 62 | return $code; 63 | } 64 | 65 | //得到纯数字类型字符串函数 66 | protected function getNumberCode() 67 | { 68 | $str = join('', range(0, 9)); 69 | return substr(str_shuffle($str), 0, $this->number); 70 | } 71 | 72 | //得到纯字母类型字符串 73 | protected function getCharCode() 74 | { 75 | $arr = range('a', 'z'); 76 | $str = join('', $arr); 77 | $str .= strtoupper($str); 78 | return substr(str_shuffle($str), 0, $this->number); 79 | } 80 | 81 | //得到数字和字母混合字符串 82 | //0-9 48-57 83 | //a-z 97-122 84 | //A-Z 65-90 85 | protected function getNumCharCode() 86 | { 87 | $str = ''; 88 | for ($i = 0; $i < $this->number; $i++) { 89 | $t = mt_rand(0, 2); 90 | switch ($t) { 91 | case 0: 92 | $str .= chr(mt_rand(48, 57)); 93 | break; 94 | case 1: 95 | $str .= chr(mt_rand(97, 122)); 96 | break; 97 | case 2: 98 | $str .= chr(mt_rand(65, 90)); 99 | break; 100 | } 101 | } 102 | return $str; 103 | } 104 | 105 | //当外部读取code字符串的时候允许读取 106 | function __get($name) 107 | { 108 | if ($name == 'code') { 109 | return $this->code; 110 | } 111 | return false; 112 | } 113 | 114 | public function outImage() 115 | { 116 | //生成画布 117 | $this->image = $this->createImage(); 118 | //填充背景色 119 | $this->fillBackground(); 120 | //画验证码 121 | $this->drawChar(); 122 | //画干扰元素 123 | //disturb:干扰元素 124 | $this->drawDisturb(); 125 | //输出显示到浏览器 126 | $this->show(); 127 | } 128 | 129 | protected function createImage() 130 | { 131 | return imagecreatetruecolor($this->width, $this->height); 132 | } 133 | 134 | protected function fillBackground() 135 | { 136 | imagefill($this->image, 0, 0, $this->lightColor()); 137 | } 138 | 139 | protected function lightColor() 140 | { 141 | return imagecolorallocate( 142 | $this->image, 143 | mt_rand(130, 255), 144 | mt_rand(130, 255), 145 | mt_rand(130, 255) 146 | ); 147 | } 148 | 149 | protected function darkColor() 150 | { 151 | return imagecolorallocate( 152 | $this->image, 153 | mt_rand(0, 120), 154 | mt_rand(0, 120), 155 | mt_rand(0, 120) 156 | ); 157 | } 158 | 159 | protected function drawChar() 160 | { 161 | for ($i = 0; $i < $this->number; $i++) { 162 | $c = $this->code[$i]; 163 | $width = ceil($this->width / $this->number); 164 | $x = mt_rand($i * $width + 10, ($i + 1) * $width - 15); 165 | $y = mt_rand(0, $this->height - 15); 166 | imagechar($this->image, 5, $x, $y, $c, $this->darkColor()); 167 | } 168 | } 169 | 170 | protected function drawDisturb() 171 | { 172 | //画干扰点 173 | for ($i = 0; $i < 150; $i++) { 174 | $x = mt_rand(0, $this->width); 175 | $y = mt_rand(0, $this->height); 176 | imagesetpixel($this->image, $x, $y, $this->darkColor()); 177 | } 178 | 179 | //画干扰弧 180 | for ($i = 0; $i < 5; $i++) { 181 | imagearc( 182 | $this->image, 183 | mt_rand(0, $this->width), 184 | mt_rand(0, $this->height), 185 | mt_rand(0, $this->width), 186 | mt_rand(0, $this->height), 187 | mt_rand(30, 120), 188 | mt_rand(180, 360), 189 | $this->lightColor() 190 | ); 191 | } 192 | } 193 | 194 | protected function show() 195 | { 196 | header('Content-Type:image/'.$this->imageType); 197 | //拼接函数名 198 | $func = 'image'.$this->imageType; 199 | $func($this->image); 200 | } 201 | } 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | -------------------------------------------------------------------------------- /Tpl.php: -------------------------------------------------------------------------------- 1 | checkDir($viewDir)) { 20 | $this->viewDir = $viewDir; 21 | } 22 | } 23 | 24 | if (!empty($cacheDir)) { 25 | if ($this->checkDir($cacheDir)) { 26 | $this->cacheDir = $cacheDir; 27 | } 28 | } 29 | 30 | //过期是否设置 31 | if (!empty($lifeTime)) { 32 | $this->lifeTime = $lifeTime; 33 | } 34 | } 35 | 36 | //检测文件夹是否存在、可读写 37 | protected function checkDir($dirPath) 38 | { 39 | if (!file_exists($dirPath) || !is_dir($dirPath)) { 40 | return mkdir($dirPath, 0755, true); 41 | } 42 | if (!is_writable($dirPath) || !is_readable($dirPath)) { 43 | return chmod($dirPath, 0755); 44 | } 45 | return true; 46 | } 47 | 48 | //assign方法,分配变量 49 | //$title = '王麻子'; 50 | //$tpl->assign('title', $title); compact('title', 'content'); 51 | function assign($name, $value) 52 | { 53 | $this->vars[$name] = $value; 54 | } 55 | 56 | //display方法, 显示模板 57 | /* 58 | $isInclude: 你给我的模板文件,你是需要编译并且include过来还是仅仅只是编译一下而已 59 | $uri: index.php?page=1 就是用来区分你是第几页的,为了让缓存的文件名不重复,我们将文件名和uri拼接起来md5一下,生成缓存的文件名 60 | index_html.php 61 | */ 62 | function display($viewName, $isInclude = true, $uri = null) 63 | { 64 | if (empty($viewName)) { 65 | die('没有传递模板'); 66 | } 67 | 68 | //拼接模板的全路径 69 | $viewPath = rtrim($this->viewDir, '/').'/'.$viewName; 70 | // var_dump($viewPath); 71 | 72 | if (!file_exists($viewPath)) { 73 | die('模板文件不存在'); 74 | } 75 | 76 | //将缓存文件名拼接起来 77 | $cacheName = md5($viewName.$uri).'.php'; 78 | //拼接缓存文件全路径 79 | $cachePath = rtrim($this->cacheDir, '/').'/'.$cacheName; 80 | 81 | //判断缓存文件是否存在 82 | if (!file_exists($cachePath)) { 83 | //编译模板文件 84 | $php = $this->compile($viewPath); 85 | //写入文件,生成缓存 86 | file_put_contents($cachePath, $php); 87 | } 88 | 89 | //如果缓存文件存在,就要判断是否生成缓存 90 | /* 91 | 是否过期,过期要重新生成缓存 92 | 虽然不过期,但是html界面被修改,那么也需要重新生成缓存 93 | */ 94 | $isTimeout = (filectime($cachePath) + $this->lifeTime) > time() ? false : true; 95 | $isChange = filemtime($viewPath) > filemtime($cachePath) ? true : false; 96 | if ($isTimeout || $isChange) { 97 | $php = $this->compile($viewPath); 98 | //写入文件,生成缓存 99 | file_put_contents($cachePath, $php); 100 | } 101 | 102 | //将缓存包含进来 103 | if ($isInclude) { 104 | //将数据解析出来 105 | // ['title' => '你好', 'content' => '打篮球'], 106 | // $title = '你好' $content = '打篮球' 107 | extract($this->vars); 108 | include $cachePath; 109 | } 110 | 111 | } //display函数 112 | 113 | //compile方法, 编译html文件 114 | protected function compile($filePath) 115 | { 116 | //将文件读成字符串 117 | $html = file_get_contents($filePath); 118 | //正则替换,将里面的模板语法替换为我们的php语法 '#\{\$(.+?)\}#' 119 | $array = [ 120 | '{$%%}' => '', 121 | '{if %%}' => '', 122 | '{/if}' => '', 123 | '{else}' => '', 124 | '{elseif %%}' => '', 125 | '{else if %%}' => '', 126 | '{foreach %%}' => '', 127 | '{/foreach}' => '', 128 | '{while %%}' => '', 129 | '{/while}' => '', 130 | '{for %%}' => '', 131 | '{/for}' => '', 132 | '{continue}' => '', 133 | '{break}' => '', 134 | '{$%%++}' => '', 135 | '{$%%--}' => '', 136 | '{/*}' => ' '*/?>', 138 | '{section}' => ' '?>', 140 | '{$%% = $%%}' => '', 141 | '{default}' => '', 142 | '{include %%}' => '', 143 | //时间戳 144 | '{%%(%%)}' =>' ', 145 | ]; 146 | //遍历数组,依次的替换数组中的正则表达式 147 | foreach ($array as $key => $value) { 148 | //生成正则表达式 149 | $pattern = '#'.str_replace('%%', '(.+?)', preg_quote($key, '#')).'#'; 150 | //判断正则表达式中有没有include 151 | if (strstr($pattern, 'include')) { 152 | $html = preg_replace_callback($pattern, [$this, 'parseInclude'], $html); 153 | } else { 154 | //替换 155 | $html = preg_replace($pattern, $value, $html); 156 | } 157 | } 158 | return $html; 159 | } 160 | 161 | //处理include正则表达式 162 | protected function parseInclude($data) 163 | { 164 | //var_dump($data); 165 | //将文件两边引号干掉 166 | $fileName = trim($data[1], '\'"'); 167 | //不包含文件生成缓存 168 | $this->display($fileName, false); 169 | //将缓存文件字符串返回 170 | $cacheName = md5($fileName).'.php'; 171 | $cachePath = rtrim($this->cacheDir, '/').'/'.$cacheName; 172 | return ''; 173 | } 174 | 175 | //删除缓存方法,将缓存文件全部清除 176 | function clearCache() 177 | { 178 | $this->delDir($this->cacheDir); 179 | } 180 | 181 | //删除文件夹中文件 递归删除文件夹中内容 182 | function delDir($dirPath) 183 | { 184 | $dh = opendir($dirPath); 185 | while ($fileName = readdir($dh)) { 186 | if ($fileName == '.' || $fileName == '..') { 187 | continue; 188 | } 189 | $filePath = $dirPath.$fileName; 190 | if (is_dir($filePath)) { 191 | $this->delDir($filePath); 192 | } else { 193 | unlink($filePath); 194 | } 195 | } 196 | } 197 | } 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | -------------------------------------------------------------------------------- /Image.php: -------------------------------------------------------------------------------- 1 | path = $path; 16 | $this->isRandName = $isRandName; 17 | $this->type = $type; 18 | } 19 | 20 | //水印方法 21 | function water($image, $water, $position, $tmd = 100, $prefix = 'water_') 22 | { 23 | //判断图片是否存在 24 | if ((!file_exists($image)) || (!file_exists($water))) { 25 | exit('图片资源不存在'); 26 | } 27 | //得到图片的宽度和高度 28 | $imageInfo = self::getImageInfo($image); 29 | $waterInfo = self::getImageInfo($water); 30 | //判断水印图片是否能忒上去 31 | if (!$this->checkImage($imageInfo, $waterInfo)) { 32 | exit('水印图片太大'); 33 | } 34 | //打开图片 35 | $imageRes = self::openAnyImage($image); 36 | $waterRes = self::openAnyImage($water); 37 | //计算位置 38 | $pos = $this->getPosition($position, $imageInfo, $waterInfo); 39 | //忒上来 40 | imagecopymerge($imageRes, $waterRes, $pos['x'], $pos['y'], 0, 0, $waterInfo['width'], $waterInfo['height'], $tmd); 41 | //得到新的文件名 42 | $newName = $this->createNewName($image, $prefix); 43 | //得到新的文件路径 44 | $newPath = rtrim($this->path, '/').'/'.$newName; 45 | //保存文件 46 | $this->saveImage($imageRes, $newPath); 47 | //销毁图像资源 48 | imagedestroy($imageRes); 49 | imagedestroy($waterRes); 50 | return $newPath; 51 | } 52 | 53 | //缩放方法 54 | function suofang($image, $width, $height, $prefix = 'sf_') 55 | { 56 | //得到图片宽度和高度 57 | $info = self::getImageInfo($image); 58 | //根据原来的宽高和传递进来的宽高计算宽高 59 | $size = $this->getNewSize($width, $height, $info); 60 | //打开图片 61 | $imageRes = self::openAnyImage($image); 62 | //完成缩放 63 | $newRes = $this->kidOfImage($imageRes, $size, $info); 64 | //保存图片 65 | $newName = $this->createNewName($image, $prefix); 66 | $newPath = rtrim($this->path, '/').'/'.$newName; 67 | //保存文件 68 | $this->saveImage($newRes, $newPath); 69 | //销毁图片 70 | imagedestroy($imageRes); 71 | imagedestroy($newRes); 72 | } 73 | 74 | protected function saveImage($imageRes, $newPath) 75 | { 76 | $func = 'image'.$this->type; 77 | $func($imageRes, $newPath); 78 | } 79 | 80 | //得到新的名字 81 | protected function createNewName($imagePath, $prefix) 82 | { 83 | if ($this->isRandName) { 84 | $name = $prefix.uniqid().'.'.$this->type; 85 | } else { 86 | $name = $prefix.pathinfo($imagePath)['filename'].$this->type; 87 | } 88 | return $name; 89 | } 90 | 91 | protected function getPosition($pos, $imageInfo, $waterInfo) 92 | { 93 | $arr1 = [0, ($imageInfo['width'] - $waterInfo['width']) / 2, $imageInfo['width'] - $waterInfo['width']]; 94 | $arr2 = [0, ($imageInfo['height'] - $waterInfo['height']) / 2, $imageInfo['height'] - $waterInfo['height']]; 95 | if ($pos) { 96 | //得到行号和列号 97 | $row = floor(($pos - 1) / 3); //1 98 | $col = ($pos - 1) % 3; //2 99 | $x = $arr1[$col]; 100 | $y = $arr2[$row]; 101 | } else { 102 | $x = mt_rand(0, $imageInfo['width'] - $waterInfo['width']); 103 | $y = mt_rand(0, $imageInfo['height'] - $waterInfo['height']); 104 | } 105 | return ['x' => $x, 'y' => $y]; 106 | } 107 | 108 | //判断水印图片大小 109 | protected function checkImage($imageInfo, $waterInfo) 110 | { 111 | if (($waterInfo['width'] > $imageInfo['width']) || ($waterInfo['height'] > $imageInfo['height'])) { 112 | return false; 113 | } 114 | return true; 115 | } 116 | 117 | protected function kidOfImage($srcImg, $size, $imgInfo) 118 | { 119 | //传入新的尺寸,创建一个指定尺寸的图片 120 | $newImg = imagecreatetruecolor($size['old_w'], $size['old_h']); 121 | //定义透明色 122 | $otsc = imagecolortransparent($srcImg); 123 | if ($otsc >= 0) { 124 | //取得透明色 125 | $transparentcolor = imagecolorsforindex($srcImg, $otsc); 126 | //创建透明色 127 | $newtransparentcolor = imagecolorallocate( 128 | $newImg, 129 | $transparentcolor['red'], 130 | $transparentcolor['green'], 131 | $transparentcolor['blue'] 132 | ); 133 | } else { 134 | //将黑色作为透明色,因为创建图像后在第一次分配颜色时背景默认为黑色 135 | $newtransparentcolor = imagecolorallocate($newImg, 0, 0, 0); 136 | } 137 | //背景填充透明 138 | imagefill( $newImg, 0, 0, $newtransparentcolor); 139 | imagecolortransparent($newImg, $newtransparentcolor); 140 | 141 | imagecopyresampled( $newImg, $srcImg, $size['x'], $size['y'], 0, 0, $size["new_w"], $size["new_h"], $imgInfo["width"], $imgInfo["height"] ); 142 | return $newImg; 143 | } 144 | 145 | 146 | /* 147 | $width:最终缩放的宽度 148 | $height:最终缩放的高度 149 | $imgInfo:原始图片的宽度和高度 150 | */ 151 | protected function getNewSize($width, $height, $imgInfo) 152 | { 153 | $size['old_w'] = $width; 154 | $size['old_h'] = $height; 155 | 156 | $scaleWidth = $width / $imgInfo['width']; 157 | $scaleHeight = $height / $imgInfo['height']; 158 | $scaleFinal = min($scaleWidth, $scaleHeight); 159 | 160 | $size['new_w'] = round($imgInfo['width'] * $scaleFinal); 161 | $size['new_h'] = round($imgInfo['height'] * $scaleFinal); 162 | if ($scaleWidth < $scaleHeight) { 163 | $size['x'] = 0; 164 | $size['y'] = round(abs($size['new_h'] - $height) / 2); 165 | } else { 166 | $size['y'] = 0; 167 | $size['x'] = round(abs($size['new_w'] - $width) / 2); 168 | } 169 | return $size; 170 | } 171 | 172 | //根据文件路径打开任意图片 173 | static function openAnyImage($imagePath) 174 | { 175 | $mime = self::getImageInfo($imagePath)['mime']; 176 | switch ($mime) { 177 | case 'image/png': 178 | $image = imagecreatefrompng($imagePath); 179 | break; 180 | case 'image/gif': 181 | $image = imagecreatefromgif($imagePath); 182 | break; 183 | case 'image/jpeg': 184 | $image = imagecreatefromjpeg($imagePath); 185 | break; 186 | case 'image/wbmp': 187 | $image = imagecreatefromwbmp($imagePath); 188 | break; 189 | } 190 | return $image; 191 | } 192 | 193 | //根据文件路径获取文件信息 194 | static function getImageInfo($imagePath) 195 | { 196 | $info = getimagesize($imagePath); 197 | $data['width'] = $info[0]; 198 | $data['height'] = $info[1]; 199 | $data['mime'] = $info['mime']; 200 | return $data; 201 | } 202 | } 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | -------------------------------------------------------------------------------- /Upload.php: -------------------------------------------------------------------------------- 1 | $value) { 47 | $this->setOption($key, $value); 48 | } 49 | } 50 | 51 | //判断该$key是不是我的成员属性,如果是,那么设置之 52 | protected function setOption($key, $value) 53 | { 54 | //得到所有的成员属性 55 | $keys = array_keys(get_class_vars(__ClASS__)); 56 | //如果$key是成员属性。设置之 57 | if (in_array($key, $keys)) { 58 | $this->$key = $value; 59 | } 60 | } 61 | 62 | //写文件上传函数 63 | //参数:就是input框的name属性值 64 | function uploadFile($key) 65 | { 66 | //判断有没有设置path 67 | if (empty($this->path)) { 68 | $this->setOption('errorNumber', -1); 69 | return false; 70 | } 71 | //判断该路径是否存在、可写 72 | if (!$this->checkDir()) { 73 | $this->setOption('errorNumber', -2); 74 | return false; 75 | } 76 | //判断$_FILES里面的error信息是否为0,如果为0,提取信息保存到成员属性中 77 | $error = $_FILES[$key]['error']; 78 | if ($error) { 79 | $this->setOption('errorNumber', $error); 80 | return false; 81 | } else { 82 | //提取文件相关信息保存到成员属性中 83 | $this->getFileInfo($key); 84 | } 85 | 86 | //判断大小是否符合、mime类型是否符合、后缀是否符合 87 | if ((!$this->checkSize()) || (!$this->checkMime()) || (!$this->checkSuffix())) { 88 | return false; 89 | } 90 | //得到新的文件名,得到新的文件路径 91 | $this->newName = $this->createNewName(); 92 | $this->newPath = $this->createNewPath(); 93 | 94 | //判断是否是上传文件、移动文件 95 | if (is_uploaded_file($this->tmpName)) { 96 | if (move_uploaded_file($this->tmpName, $this->newPath.$this->newName)) { 97 | $this->setOption('errorNumber', 0); 98 | return [$this->newPath.$this->newName,1]; 99 | } else { 100 | $this->setOption('errorNumber', -7); 101 | return false; 102 | } 103 | } else { 104 | $this->setOption('errorNumber', -6); 105 | return false; 106 | } 107 | } 108 | 109 | protected function checkDir() 110 | { 111 | //文件夹不存在或者不是目录,创建文件夹 112 | if (!file_exists($this->path) || !is_dir($this->path)) { 113 | //参数3:是否创建中间目录 114 | return mkdir($this->path, 0755, true); 115 | } 116 | 117 | //判断文件是否可写 118 | if (!is_writable($this->path)) { 119 | return chmod($this->path, 0755); 120 | } 121 | 122 | return true; 123 | } 124 | 125 | //获取文件相关信息 126 | protected function getFileInfo($key) 127 | { 128 | //得到文件名字 129 | $this->oldName = $_FILES[$key]['name']; 130 | //得到文件mime 131 | $this->mime = $_FILES[$key]['type']; 132 | //得到文件临时路径 133 | $this->tmpName = $_FILES[$key]['tmp_name']; 134 | //得到文件大小 135 | $this->size = $_FILES[$key]['size']; 136 | //得到文件后缀 137 | $this->suffix = pathinfo($this->oldName)['extension']; 138 | } 139 | 140 | //判断文件大小函数 141 | protected function checkSize() 142 | { 143 | if ($this->size > $this->maxSize) { 144 | $this->setOption('errorNumber', -3); 145 | return false; 146 | } 147 | return true; 148 | } 149 | 150 | //判断文件mime类型 151 | protected function checkMime() 152 | { 153 | if (!in_array($this->mime, $this->allowMime)) { 154 | $this->setOption('errorNumber', -4); 155 | return false; 156 | } 157 | return true; 158 | } 159 | 160 | //判断文件后缀是否符合 161 | protected function checkSuffix() 162 | { 163 | if (!in_array($this->suffix, $this->allowSuffix)) { 164 | $this->setOption('errorNumber', -5); 165 | return false; 166 | } 167 | return true; 168 | } 169 | 170 | //得到新的文件名 171 | protected function createNewName() 172 | { 173 | if ($this->isRandName) { 174 | $name = $this->prefix.uniqid().'.'.$this->suffix; 175 | } else { 176 | $name = $this->prefix.$this->oldName; 177 | } 178 | return $name; 179 | } 180 | 181 | //得到新的路径 182 | protected function createNewPath() 183 | { 184 | if ($this->isDatePath) { 185 | $path = $this->path.date('y/m/d/'); 186 | if (!file_exists($path)) { 187 | mkdir($path, 0755, true); 188 | } 189 | return $path; 190 | } else { 191 | return $this->path; 192 | } 193 | } 194 | 195 | //写get方法,让外部得到错误号和错误信息 196 | function __get($name) 197 | { 198 | if ($name == 'errorNumber') { 199 | return $this->errorNumber; 200 | } else if ($name == 'errorInfo') { 201 | return $this->getErrorInfo(); 202 | } 203 | } 204 | 205 | //错误号对应的错误信息 206 | protected function getErrorInfo() 207 | { 208 | //-1 =>文件路径没有设置 209 | //-2 =》文件不是目录或者权限错误 210 | //-3 => 文件信息量太大 211 | //-4 => 文件mime类型不符合 212 | //-5 => 文件后缀不符合 213 | //-6 => 文件非上传文件 214 | switch ($this->errorNumber) { 215 | case 0: 216 | $str = '文件上传成功'; 217 | break; 218 | case 1: 219 | $str = '文件超过php.ini设置'; 220 | break; 221 | case 2: 222 | $str = '文件超过html设置'; 223 | break; 224 | case 3: 225 | $str = '部分文件上传'; 226 | break; 227 | case 4: 228 | $str = '没有文件上传'; 229 | break; 230 | case 6: 231 | $str = '找不到临时文件'; 232 | break; 233 | case 7: 234 | $str = '文件写入失败'; 235 | break; 236 | case -1: 237 | $str = '文件路径没有设置'; 238 | break; 239 | case -2: 240 | $str = '文件不是目录或者权限错误'; 241 | break; 242 | case -3: 243 | $str = '文件信息量太大'; 244 | break; 245 | case -4: 246 | $str = '文件mime类型不符合'; 247 | break; 248 | case -5: 249 | $str = '文件后缀不符合'; 250 | break; 251 | case -6: 252 | $str = '文件不是上传文件'; 253 | break; 254 | case -7: 255 | $str = '文件上传失败'; 256 | break; 257 | } 258 | return $str; 259 | } 260 | } 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | -------------------------------------------------------------------------------- /Model.php: -------------------------------------------------------------------------------- 1 | host = $config['DB_HOST']; 41 | $this->user = $config['DB_USER']; 42 | $this->pwd = $config['DB_PWD']; 43 | $this->dbname = $config['DB_NAME']; 44 | $this->charset = $config['DB_CHARSET']; 45 | $this->prefix = $config['DB_PREFIX']; 46 | 47 | //连接数据库,将成功连接后的资源保存起来 48 | $this->link = $this->connect(); 49 | //得到数据表名函数 50 | $this->tableName = $this->getTableName(); 51 | //得到缓存字段数组,将其存放到 $this->fields 下面 52 | $this->fields = $this->getCacheFields(); 53 | 54 | //初始化options数组 init:初始化 55 | $this->initOptions(); 56 | } 57 | 58 | //连接数据库函数 59 | protected function connect() 60 | { 61 | $link = mysqli_connect($this->host, $this->user, $this->pwd); 62 | if (!$link) { 63 | die('数据库连接失败'); 64 | } 65 | mysqli_select_db($link, $this->dbname); 66 | mysqli_set_charset($link, $this->charset); 67 | return $link; 68 | } 69 | 70 | //默认的表名:通过成员属性设置,通过类名获取 71 | protected function getTableName() 72 | { 73 | //如果设置了,以设置的表名为默认 74 | if (!empty($this->tableName)) { 75 | return $this->prefix.$this->tableName; 76 | } 77 | //获取类名,从类名中将表名得到 78 | $className = get_class($this); 79 | //UserModel GoodsModel PhoneModel 80 | $table = strtolower(substr($className, 0, -5)); 81 | return $this->prefix.$table; 82 | } 83 | 84 | //得到缓存字段函数 85 | protected function getCacheFields() 86 | { 87 | //拼接缓存文件路径 88 | $cacheFile = './cache/'.$this->tableName.'.php'; 89 | //判断该文件是否存在,如果存在,直接include进来,如果不存在,我们要生成这个文件 90 | if (file_exists($cacheFile)) { 91 | return include $cacheFile; 92 | } 93 | 94 | //拼接sql语句 95 | $sql = 'desc '.$this->tableName; 96 | //调用结果集查询函数,得到结果 97 | $result = $this->query($sql); 98 | foreach($result as $value) { 99 | $fields[] = $value['Field']; 100 | //得到主键,存放起来 101 | if ($value['Key'] == 'PRI') { 102 | $fields['PRI'] = $value['Field']; 103 | } 104 | } 105 | 106 | //将上面的 数组 变成 数组生成字符串 然后写入到文件中 107 | $str = var_export($fields, true); 108 | $str = "initOptions(); 120 | $result = mysqli_query($this->link, $sql); 121 | if ($result && mysqli_affected_rows($this->link)) { 122 | while ($data = mysqli_fetch_assoc($result)) { 123 | $newData[] = $data; 124 | } 125 | return $newData; 126 | } 127 | return false; 128 | } 129 | 130 | //初始化options数组,将里面的其他的都设置为空 将field设置为缓存字段,将table设置为默认table名 131 | protected function initOptions() 132 | { 133 | $arr = ['where', 'table', 'field', 'order', 'group', 'having', 'limit']; 134 | foreach ($arr as $value) { 135 | //将options中的这些键对应的值先设置为空 136 | $this->options[$value] = ''; 137 | //我要这里面的field默认是我的缓存字段,table默认是我的tableName 138 | if ($value == 'field') { 139 | $this->options[$value] = join(',', array_unique($this->fields)); 140 | } else if ($value == 'table') { 141 | $this->options[$value] = $this->tableName; 142 | } 143 | } 144 | } 145 | 146 | //where函数 147 | function where($where) 148 | { 149 | if (!empty($where)) { 150 | $this->options['where'] = 'where '.$where; 151 | } 152 | return $this; 153 | } 154 | 155 | //table函数 156 | function table($table) 157 | { 158 | if (!empty($table)) { 159 | $this->options['table'] = $table; 160 | } 161 | return $this; 162 | } 163 | 164 | //field函数 id,name,password [id, name, password] 165 | function field($field) 166 | { 167 | if (!empty($field)) { 168 | if (is_string($field)) { 169 | $this->options['field'] = $field; 170 | } else if (is_array($field)) { 171 | $this->options['field'] = join(',', $field); 172 | } 173 | } 174 | return $this; 175 | } 176 | 177 | //group函数 178 | function group($group) 179 | { 180 | if (!empty($group)) { 181 | $this->options['group'] = 'group by '.$group; 182 | } 183 | return $this; 184 | } 185 | 186 | //having函数 187 | function having($having) 188 | { 189 | if (!empty($having)) { 190 | $this->options['having'] = 'having '.$having; 191 | } 192 | return $this; 193 | } 194 | 195 | //order函数 196 | function order($order) 197 | { 198 | if (!empty($order)) { 199 | $this->options['order'] = 'order by '.$order; 200 | } 201 | return $this; 202 | } 203 | 204 | //limit函数 205 | function limit($limit) 206 | { 207 | if (!empty($limit)) { 208 | if (is_string($limit)) { 209 | $this->options['limit'] = 'limit '.$limit; 210 | } else if (is_array($limit)) { 211 | $this->options['limit'] = 'limit '.join(',', $limit); 212 | } 213 | } 214 | return $this; 215 | } 216 | 217 | //查询函数 218 | function select() 219 | { 220 | //带有占位符的sql语句 221 | $sql = 'select %FIELD% from %TABLE% %WHERE% %GROUP% %HAVING% %ORDER% %LIMIT%'; 222 | //将options中对应的值依次的替换上面的占位符 223 | $sql = str_replace( 224 | ['%FIELD%', '%TABLE%', '%WHERE%', '%GROUP%', '%HAVING%', '%ORDER%', '%LIMIT%'], 225 | [$this->options['field'], $this->options['table'], $this->options['where'], $this->options['group'], $this->options['having'], $this->options['order'], $this->options['limit']], 226 | $sql); 227 | //保存一份sql语句 228 | $this->sql = $sql; 229 | //执行sql语句 230 | return $this->query($sql); 231 | } 232 | 233 | //增删改语句执行函数 234 | function exec($sql, $insertId=false) 235 | { 236 | //在这将options数组还原为初始状态 237 | $this->initOptions(); 238 | $result = mysqli_query($this->link, $sql); 239 | if ($result && mysqli_affected_rows($this->link)) { 240 | if ($insertId) { 241 | return mysqli_insert_id($this->link); 242 | } else { 243 | return mysqli_affected_rows($this->link); 244 | } 245 | } 246 | return false; 247 | } 248 | 249 | //insert函数 $data:关联数组,键就是字段名 值就是字段值 250 | function insert($data) 251 | { 252 | //处理关联数组中的值如果是字符串,两边加引号 253 | $data = $this->parseValue($data); 254 | //提取所有的键,即所有的字段 255 | $keys = array_keys($data); 256 | //提取所有的值 257 | $values = array_values($data); 258 | $sql = 'insert into %TABLE%(%FIELD%) values(%VALUES%)'; 259 | $sql = str_replace( 260 | ['%TABLE%', '%FIELD%', '%VALUES%'], 261 | [$this->options['table'], join(',', $keys), join(',', $values)], 262 | $sql); 263 | $this->sql = $sql; 264 | return $this->exec($sql, true); 265 | } 266 | 267 | //传递给我一个数组,将数组中的值是字符串的两边加上引号 268 | protected function parseValue($data) 269 | { 270 | foreach ($data as $key => $value) { 271 | if (is_string($value)) { 272 | $value = '"'.$value.'"'; 273 | } 274 | $newData[$key] = $value; 275 | } 276 | return $newData; 277 | } 278 | 279 | //删除函数 280 | function delete() 281 | { 282 | $sql = 'delete from %TABLE% %WHERE%'; 283 | $sql = str_replace( 284 | ['%TABLE%', '%WHERE%'], 285 | [$this->options['table'], $this->options['where']], 286 | $sql); 287 | $this->sql = $sql; 288 | return $this->exec($sql); 289 | } 290 | 291 | //更新函数 传入关联数组 292 | function update($data) 293 | { 294 | //处理$data中值为字符串的引号问题 295 | $data = $this->parseValue($data); 296 | //将$data拼接为固定的格式 键=值,键=值 297 | $value = $this->parseUpdate($data); 298 | $sql = 'update %TABLE% set %VALUE% %WHERE%'; 299 | $sql = str_replace( 300 | ['%TABLE%', '%VALUE%', '%WHERE%'], 301 | [$this->options['table'], $value, $this->options['where']], 302 | $sql); 303 | $this->sql = $sql; 304 | return $this->exec($sql); 305 | } 306 | 307 | //将关联数组拼接为更新格式的字符串 例如 键=值,键=值 308 | protected function parseUpdate($data) 309 | { 310 | foreach ($data as $key => $value) { 311 | $suibian[] = $key.'='.$value; 312 | } 313 | return join(',', $suibian); 314 | } 315 | 316 | function __destruct() 317 | { 318 | mysqli_close($this->link); 319 | } 320 | 321 | //获取sql语句 322 | function __get($name) 323 | { 324 | if ($name == 'sql') { 325 | return $this->sql; 326 | } 327 | return false; 328 | } 329 | 330 | //实现类似于 getByUsername() 331 | function __call($name, $args) 332 | { 333 | //获取前5个字符,看是不是getBy 334 | $str = substr($name, 0, 5); 335 | //获取后面的所有字符,即字段名 336 | $field = strtolower(substr($name, 5)); 337 | if ($str == 'getBy') { 338 | //$sql = "select {$this->options['field']} from {$this->options['table']} where $field = {$args[0]}"; 339 | //return $this->query($sql); 340 | return $this->where($field.'="'.$args[0].'"')->select(); 341 | } 342 | return false; 343 | } 344 | 345 | //count max min sum 346 | function count($field = null) 347 | { 348 | if (empty($field)) { 349 | $field = $this->fields['PRI']; 350 | } 351 | $result = $this->field('count('.$field.') as count')->select(); 352 | return $result[0]['count']; 353 | } 354 | 355 | function max($field = null) 356 | { 357 | if (empty($field)) { 358 | $field = $this->fields['PRI']; 359 | } 360 | $result = $this->field('max('.$field.') as max')->select(); 361 | return $result[0]['max']; 362 | } 363 | 364 | function min($field = null) 365 | { 366 | if (empty($field)) { 367 | $field = $this->fields['PRI']; 368 | } 369 | $result = $this->field('min('.$field.') as min')->select(); 370 | return $result[0]['min']; 371 | } 372 | 373 | function sum($field = null) 374 | { 375 | if (empty($field)) { 376 | $field = $this->fields['PRI']; 377 | } 378 | $result = $this->field('sum('.$field.') as sum')->select(); 379 | return $result[0]['sum']; 380 | } 381 | } 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | --------------------------------------------------------------------------------