首页
关于
Search
1
给你10个市场数据调研报告的免费下载网站!以后竞品数据就从这里找!
182 阅读
2
php接口优化 使用curl_multi_init批量请求
144 阅读
3
《从菜鸟到大师之路 ElasticSearch 篇》
107 阅读
4
2024年备考系统架构设计师
104 阅读
5
PHP 文件I/O
92 阅读
php
thinkphp
laravel
工具
开源
mysql
数据结构
总结
思维逻辑
令人感动的创富故事
读书笔记
前端
vue
js
css
书籍
开源之旅
架构
消息队列
docker
教程
代码片段
redis
服务器
nginx
linux
科普
java
c
ElasticSearch
测试
php进阶
php基础
登录
Search
标签搜索
php函数
php语法
性能优化
安全
错误和异常处理
问题
vue
Composer
Session
缓存
框架
Swoole
api
并发
异步
正则表达式
php-fpm
mysql 索引
开发规范
协程
dafenqi
累计撰写
786
篇文章
累计收到
30
条评论
首页
栏目
php
thinkphp
laravel
工具
开源
mysql
数据结构
总结
思维逻辑
令人感动的创富故事
读书笔记
前端
vue
js
css
书籍
开源之旅
架构
消息队列
docker
教程
代码片段
副业
redis
服务器
nginx
linux
科普
java
c
ElasticSearch
测试
php进阶
php基础
页面
关于
搜索到
138
篇与
的结果
2023-09-05
PHP常见算法
排序冒泡排序依次比较相邻的两个数,将比较小的数放在前面,比较大的数放在后面。$arr = [8,1,10,9,5,7]; function bubbleSort($arr){ // 外层 for 循环控制循环次数 for ($i=0; $i<count($arr) ; $i++) { //内层 for 循环进行两数交换,找每次的最大数,排到最后 for ($j=0; $j < count($arr)-1; $j++) { //数组里第一个和第二个对比,如果1>2,执行数值互换 if($arr[$j] >$arr[$j+1]){ $x = $arr[$j]; //第一赋给一个变量 $arr[$j] = $arr[$j+1]; //第二赋给第一 $arr[$j+1] = $x; //把变量给第二,结果就是1,2的数值互换 // $a=10; // $b=20; // $x=$a; $x=10 // $a=$b; $a=20 // $b=$X; $b=10 } } } return $arr; } print_r(bubbleSort($arr));快速排序快速排序是对冒泡排序的一种改进。设置一个基准元素,通过排序将需要排序的数据分割成两个部分,其中一部分的所有数据比基准元素小,另一部分的所有数据比基准元素大,然后对这两部分数据分别进行递归快速排序,最后将得到的数据和基准元素进行合并,就得到了所需数据。$arr = [8,1,10,9,5,7]; function quickSort($arr){ $lenth = count($arr);//获取数组个数 if($lenth <= 1){//小于等于一个不用往下走了 return $arr; } //选择基准元素。一般选第一个或最后一个 $first = $arr[0]; $left = array();//接收小于基准元素的值 $right = array();//接收大于基准元素的值 //循环从1开始,因为基准元素是0 for($i=1;$i<$lenth;$i++){ if($arr[$i]<$first){//小于基准元素的值 $left[] = $arr[$i]; }else{//大于基准元素的值 $right[] = $arr[$i]; } } //递归排序 $left = quickSort($left); $right = quickSort($right); //合并返回数组 return array_merge($left,array($first),$right); } print_r(quickSort($arr));选择排序1.找到数组中最小的元素,拎出来,将它和数组的第一个元素交换位置; 2.在剩下的元素中继续寻找最小的元素,拎出来,和数组的第二个元素交换位置; 3.如此循环,直到整个数组排序完成。$arr = [8,1,10,9,5,7]; function selectSort($arr){ //实现思路 双重循环完成,外层控制轮数,当前的最小值。内层 控制的比较次数,$i 当前最小值的位置, 需要参与比较的元素 for($i=0, $len=count($arr); $i<$len-1; $i++){ //先假设最小的值的位置 $p = $i; //$j 当前都需要和哪些元素比较,$i 后边的。 for($j=$i+1; $j<$len; $j++) { //$arr[$p] 是 当前已知的最小值 if($arr[$p] > $arr[$j]){ //比较,发现更小的,记录下最小值的位置;并且在下次比较时,应该采用已知的最小值进行比较。 $p = $j; } } //已经确定了当前的最小值的位置,保存到$p中。如果发现 最小值的位置与当前假设的位置$i不同,则位置互换即可。 if($p != $i){ $tmp = $arr[$p]; $arr[$p] = $arr[$i]; $arr[$i] = $tmp; } } return $arr; } print_r(selectSort($arr));插入排序每次将一个待排序的数据元素,插入到前面已经排好序的数列中的适当位置,使数列依然有序;直到待排序数据元素全部插入完为止。$arr = [8,1,10,9,5,7]; function insertSort($arr){ $count = count($arr); for($i=1; $i<$count; $i++){ $tmp = $arr[$i]; $j = $i - 1; while(isset($arr[$j]) && $arr[$j] > $tmp){ $arr[$j+1] = $arr[$j]; $arr[$j] = $tmp; $j--; } } return $arr; } print_r(insertSort($arr));希尔排序希尔排序(Shell Sort)是插入排序的一种,它是针对直接插入排序算法的改进。该方法又称缩小增量排序,因DL.Shell于1959年提出而得名。希尔排序实质上是一种分组插入方法。它的基本思想是:对于n个待排序的数列,取一个小于n的整数gap(gap被称为步长)将待排序元素分成若干个组子序列,所有距离为gap的倍数的记录放在同一个组中;然后,对各组内的元素进行直接插入排序。 这一趟排序完成之后,每一个组的元素都是有序的。然后减小gap的值,并重复执行上述的分组和排序。重复这样的操作,当gap=1时,整个数列就是有序的。$arr = [8,1,10,9,5,7]; function shellSort(&$arr){ if(!is_array($arr))return;$n=count($arr); for($gap=floor($n/2);$gap>0;$gap=floor($gap/=2)){ for($i=$gap;$i<$n;++$i){ for($j=$i-$gap;$j>=0&&$arr[$j+$gap]<$arr[$j];$j-=$gap){ $temp=$arr[$j]; $arr[$j]=$arr[$j+$gap]; $arr[$j+$gap]=$temp; } } } return $arr; } print_r(shellSort($arr));查找二分查找二分查找也称折半查找(Binary Search),它是一种效率较高的查找方法。但是,折半查找要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列。首先,假设表中元素是按升序排列,将表中间位置记录的关键字与查找关键字比较,如果两者相等,则查找成功;否则利用中间位置记录将表分成前、后两个子表,如果中间位置记录的关键字大于查找关键字,则进一步查找前一子表,否则进一步查找后一子表。重复以上过程,直到找到满足条件的记录,使查找成功,或直到子表不存在为止,此时查找不成功。/** * 二分查找(Binary Search)算法,也叫折半查找算法。二分查找的思想非常简单,有点类似分治的思想。 * 二分查找针对的是一个有序的数据集合,每次都通过跟区间的中间元素对比, * 将待查找的区间缩小为之前的一半,直到找到要查找的元素,或者区间被缩小为 0。 * * 循环写法 * @param array $array 待查找的数组 * @param int $findVal 要查找的值 * @return int 返回找到的数组键 */ function binarySearch($array, $findVal) { // 非数组或者数组为空,直接返回-1 if (!is_array($array) || empty($array)) { return -1; } // 查找区间,起点和终点 $start = 0; $end = count($array) - 1; while ($start <= $end) { // 以中间点作为参照点比较,取整数 $middle = intval(($start + $end) / 2); if ($array[$middle] > $findVal) { // 查找数比参照点小,则要查找的数在左半边 // 因为 $middle 已经比较过了,这里需要减1 $end = $middle - 1; } elseif ($array[$middle] < $findVal) { // 查找数比参照点大,则要查找的数在右半边 // 因为 $middle 已经比较过了,这里需要加1 $start = $middle + 1; } else { // 查找数与参照点相等,则找到返回 return $middle; } } // 未找到,返回-1 return -1; } // 调用 $array = [10,12,16,19,20,34,56,78,84,95,100]; echo binarySearch($array, 84); /** * 递归写法 * @param array $array 待查找的数组 * @param int $findVal 要查找的值 * @param int $start 查找区间,起点 * @param int $end 查找区间,终点 * @return int 返回找到的数组键 */ function binSearch($array, $findVal, $start, $end) { // 以中间点作为参照点比较,取整数 $middle = intval(($start + $end) / 2); if ($start > $end) { return -1; } if ($findVal > $array[$middle]) { // 查找数比参照点大,则要查找的数在右半边 return binSearch($array, $findVal, $middle + 1, $end); } elseif ($findVal < $array[$middle]) { // 查找数比参照点小,则要查找的数在左半边 return binSearch($array, $findVal, $start, $middle - 1); } else { return $middle; } } // 调用 $arr = [10,12,16,19,20,34,56,78,84,95,100]; var_dump(binSearch($arr, 95, 0, count($arr)-1));
2023年09月05日
15 阅读
0 评论
0 点赞
2023-09-05
PHP常用六大设计模式
PHP常用六大设计模式单例模式特点三私一公 :私有的静态变量(存放实例),私有的构造方法(防止创建实例),私有的克隆方法(防止克隆对象),公有的静态方法(对外界提供实例)应用场景程序应用中,涉及到数据库操作时,如果每次操作的时候连接数据库,会带来大量的资源消耗。可以通过单例模式,创建唯一的数据库连接对象。<?php class Singleton { private static $_instance; private function __construct(){} private function __clone(){} public static function getInstance() { if(self::$_instance instanceof Singleton){//instanceof 判断一个实例是否是某个类的对象 self::$_instance = new Singleton(); } return self::$_instance; } }工厂模式特点将调用对象与创建对象分离 ,调用者直接向工厂请求,减少代码的耦合,提高系统的可维护性与可扩展性。应用场景提供一种类,具有为您创建对象的某些方法,这样就可以使用工厂类创建对象,而不直接使用new。这样如果想更改创建的对象类型,只需更改该工厂即可。//假设3个待实例化的类 class Aclass { } class Bclass { } class Cclass { } class Factory { //定义每个类的类名 const ACLASS = 'Aclass'; const BCLASS = 'Bclass'; const CCLASS = 'Cclass'; public static function getInstance($newclass) { $class = $newclass;//真实项目中这里常常是用来解析路由,加载文件。 return new $class; } } //调用方法: Factory::getInstance(Factory::ACLASS);注册树模式特点注册树模式通过 将对象实例注册到一棵全局的对象树上,需要的时候从对象树上采摘 的模式设计方法。应用场景不管你是通过单例模式还是工厂模式还是二者结合生成的对象,都统统给我“插到”注册树上。我用某个对象的时候,直接从注册树上取一下就好。这和我们使用全局变量一样的方便实用。而且注册树模式还为其他模式提供了一种非常好的想法。 (如下实例是单例,工厂,注册树的联合使用)//创建单例 class Single{ public $hash; static protected $ins=null; final protected function __construct(){ $this->hash=rand(1,9999); } static public function getInstance(){ if (self::$ins instanceof self) { return self::$ins; } self::$ins=new self(); return self::$ins; } } //工厂模式 class RandFactory{ public static function factory(){ return Single::getInstance(); } } //注册树 class Register{ protected static $objects; public static function set($alias,$object){ self::$objects[$alias]=$object; } public static function get($alias){ return self::$objects[$alias]; } public static function _unset($alias){ unset(self::$objects[$alias]); } } //调用 Register::set('rand',RandFactory::factory()); $object=Register::get('rand'); print_r($object);策略模式定义定义一系列算法,将每一个算法封装起来,并让它们可以相互替换。策略模式让算法独立于使用它的客户而变化。特点策略模式提供了 管理相关的算法族 的办法策略模式提供了 可以替换继承关系 的办法使用策略模式可以 避免使用多重条件转移语句应用场景多个类只区别在表现行为不同,可以使用Strategy模式,在运行时动态选择具体要执行的行为。比如上学,有多种策略:走路,公交,地铁…abstract class Strategy { abstract function goSchoole(); } class Run extends Strategy { public function goSchoole() { // TODO: Implement goSchool() method. echo "Run to school <br/>"; } } class Subway extends Strategy { public function goSchoole() { // TODO: Implement goSchool() method. echo "Take the subway to school <br/>"; } } class Bike extends Strategy { public function goSchoole() { // TODO: Implement goSchool() method. echo "Go to school by bike <br/>"; } } class Context { protected $_stratege;//存储传过来的策略对象 public function goSchoole() { $this->_stratege->goSchoole(); } public function setBehavior(Strategy $behavior){//设置策略对象 $this->_stratege = $behavior; } } //调用: $contenx = new Context(); //坐地铁去学校 $contenx->setBehavior(new Subway()); $contenx->goSchoole(); //骑自行车去学校 $contenx->setBehavior(new Bike()); $contenx->goSchoole();适配器模式特点将各种截然不同的函数接口封装成统一的API。应用场景PHP中的数据库操作有MySQL,MySQLi,PDO三种,可以用适配器模式统一成一致,使不同的数据库操作,统一成一样的API。类似的场景还有cache适配器,可以将memcache,redis,file,apc等不同的缓存函数,统一成一致。abstract class Toy { public abstract function openMouth(); public abstract function closeMouth(); } class Dog extends Toy { public function openMouth() { echo "Dog open Mouth<br/>"; } public function closeMouth() { echo "Dog close Mouth<br/>"; } } class Cat extends Toy { public function openMouth() { echo "Cat open Mouth<br/>"; } public function closeMouth() { echo "Cat close Mouth<br/>"; } } //目标角色(红) interface RedTarget { public function doMouthOpen(); public function doMouthClose(); } //目标角色(绿) interface GreenTarget { public function operateMouth($type = 0); } //类适配器角色(红) class RedAdapter implements RedTarget { private $adaptee; function __construct(Toy $adaptee) { $this->adaptee = $adaptee; } //委派调用Adaptee的sampleMethod1方法 public function doMouthOpen() { $this->adaptee->openMouth(); } public function doMouthClose() { $this->adaptee->closeMouth(); } } //类适配器角色(绿) class GreenAdapter implements GreenTarget { private $adaptee; function __construct(Toy $adaptee) { $this->adaptee = $adaptee; } //委派调用Adaptee:GreenTarget的operateMouth方法 public function operateMouth($type = 0) { if ($type) { $this->adaptee->openMouth(); } else { $this->adaptee->closeMouth(); } } } class testDriver { public function run() { //实例化一只狗玩具 $adaptee_dog = new Dog(); echo "给狗套上红枣适配器<br/>"; $adapter_red = new RedAdapter($adaptee_dog); //张嘴 $adapter_red->doMouthOpen(); //闭嘴 $adapter_red->doMouthClose(); echo "给狗套上绿枣适配器<br/>"; $adapter_green = new GreenAdapter($adaptee_dog); //张嘴 $adapter_green->operateMouth(1); //闭嘴 $adapter_green->operateMouth(0); } } //调用 $test = new testDriver(); $test->run();观察者模式特点观察者模式(Observer), 当一个对象状态发生变化时,依赖它的对象全部会收到通知,并自动更新。 观察者模式实现了低耦合,非侵入式的通知与更新机制。应用场景一个事件发生后,要执行一连串更新操作。传统的编程方式,就是在事件的代码之后直接加入处理的逻辑。当更新的逻辑增多之后,代码会变得难以维护。这种方式是耦合的,侵入式的,增加新的逻辑需要修改事件的主体代码。// 主题接口 interface Subject{ public function register(Observer $observer); public function notify(); } // 观察者接口 interface Observer{ public function watch(); } // 主题 class Action implements Subject{ public $_observers=[]; public function register(Observer $observer){ $this->_observers[]=$observer; } public function notify(){ foreach ($this->_observers as $observer) { $observer->watch(); } } } // 观察者 class Cat1 implements Observer{ public function watch(){ echo "Cat1 watches TV<hr/>"; } } class Dog1 implements Observer{ public function watch(){ echo "Dog1 watches TV<hr/>"; } } class People implements Observer{ public function watch(){ echo "People watches TV<hr/>"; } } // 调用实例 $action=new Action(); $action->register(new Cat1()); $action->register(new People()); $action->register(new Dog1()); $action->notify();
2023年09月05日
9 阅读
0 评论
0 点赞
2023-08-28
PHP+Gtk实例(求24点)
PHP+Gtk实例(求24点)最近要安排我为BIT提供的《PHP高级应用--关于PHP你不知道的》一门课的讲课素材, 其中有部分涉及到PHP和Gtk2开发桌面应用的部分, 于是抽空就想写一了一个demo出来.这是一个经典的求24的算法的PHP实现, 加上了Gtk2的界面, 其实也没什么复杂的, 和MFC开发没什么太大的区别, 唯一的不爽, 就是要自己用代码来写布局。。。有兴趣的同学可以看看.后记: 这里有一个网页版的, 可以用来玩玩: http://www.laruence.com/stashes/compute.php完整源代码(PHP-Gtk example): <?php /** * A 24 maker * @version 1.0.0 * @author laruence<laruence at yahoo.com.cn> * @copyright (c) 2009 http://www.laruence.com */ class TwentyFourCal extends GtkWindow { private $chalkboard; private $inputs; public $needle = 24; public $precision = '1e-6'; function TwentyFourCal() { parent::__construct(); $this->draw(); $this->show(); } /** * 画窗体方法 */ public function draw() { $this->set_default_size(200, 200); $this->set_title("24计算器"); $mesg = new GtkLabel('Please input 4 integer(0-99):'); $this->chalkboard = new GtkLabel(); $this->inputs = $inputs = array( new GtkEntry(), new GtkEntry(), new GtkEntry(), new GtkEntry() ); /** * container */ $table = new GtkTable(4, 1, 0); $layout = array( 'left' => 0, 'right' => 1, 'top' => 0, 'bottom' => 1, ); $vBox = new GtkVBox(false, true); $vBox->pack_start($mesg); foreach ( $inputs as $input ) { $input->set_max_length(2); $table->attach($input, $layout['left'], $layout['right'], $layout['top']++, $layout['bottom']++); } $vBox->pack_start($table); $button = new GtkButton("Calculate"); $button->connect("clicked", array($this, "calculate")); $vBox->pack_start($this->chalkboard); $vBox->pack_start($button, true, false); $this->add($vBox); } public function show() { $this->show_all(); // 显示窗体 } private function notice($mesg) { $this->chalkboard->set_text($mesg); } /** * 取得用户输入方法 */ public function calculate() { $operants = array(); $inputs = $this->inputs; foreach ($inputs as $input) { $number = $input->get_text(); if (!preg_match('/^\s*\d+\s*$/', $number)) { $this->notice('pleas input for integer(0-99)'); return ; } array_push($operants, $number); } $length = count($operants); try { $this->search($operants, 4); } catch (Exception $e) { $this->notice($e->getMessage()); return; } $this->notice('can\'t compute!'); return; } /** * 求24点算法PHP实现 */ private function search($expressions, $level) { if ($level == 1) { $result = 'return ' . $expressions[0] . ';'; if ( abs(eval($result) - $this->needle) <= $this->precision) { throw new Exception($expressions[0]); } } for ($i=0;$i<$level;$i++) { for ($j=$i+1;$j<$level;$j++) { $expLeft = $expressions[$i]; $expRight = $expressions[$j]; $expressions[$j] = $expressions[$level - 1]; $expressions[$i] = '(' . $expLeft . ' + ' . $expRight . ')'; $this->search($expressions, $level - 1); $expressions[$i] = '(' . $expLeft . ' * ' . $expRight . ')'; $this->search($expressions, $level - 1); $expressions[$i] = '(' . $expLeft . ' - ' . $expRight . ')'; $this->search($expressions, $level - 1); $expressions[$i] = '(' . $expRight . ' - ' . $expLeft . ')'; $this->search($expressions, $level - 1); if ($expLeft != 0) { $expressions[$i] = '(' . $expRight . ' / ' . $expLeft . ')'; $this->search($expressions, $level - 1); } if ($expRight != 0) { $expressions[$i] = '(' . $expLeft . ' / ' . $expRight . ')'; $this->search($expressions, $level - 1); } $expressions[$i] = $expLeft; $expressions[$j] = $expRight; } } return false; } function __destruct() { Gtk::main_quit(); } } new TwentyFourCal(); Gtk::main(); //进入GTK主循环 ?>GTK1的API Reference : http://gtk.php.net/manual/en/gtk.gtkentry.phpGTK2的API Reference: 很不完整
2023年08月28日
13 阅读
0 评论
0 点赞
2023-08-28
一个巧妙的分页方法
一个巧妙的分页方法PHP是一个Web脚本语言,在Web应用中最常见的莫过于列表显示。所以页码生成也就犹为常用。 最近我索性写了一个,在生成思想上, 有一些技巧拿与大家分享:先说说需求: 显示的页码数是$size, 当前的页数是$page, 总数是$total, 每页显示的条数是$page_size 首先,要获取总页面数是多少:$total_page = ceil($total/$page_size);这样的写法是不是更简单一些呢?其次,我是这样想的, 这个需求最高的需求是要根据当前的页码,找出size个页码数来。那么就可以转化为: 根据当前的信息, 填充一个size个元素的数组。最终就可以简单的转化为:根据当前的信息,寻找出size个元素的数组的起始元素是什么?我们假设这个起始元素是:page_start;$page_start = 1; $half = intval($size/2); $page_start = max(1, $page - $half); $page_end = min($page_start + $size - 1, $total_page); $page_start = max(1, $page_end - $size + 1);这样写,是不是也很有技巧呢?最后就简单了, 根据起始页和结束页, 生成一个数组, 最后foreach这个数组,生成html代码:$page_numbers = range($page_start, $page_end); $nav_str = ""; foreach($page_numbers as $num){ //....... }源码:/** *A pagination generation class *@class : Pagination *@version: 1.0.0 *@author : huixinchen at baidu.com *@useage: * $pagi = new Pagination($url_prefix, $page_size, $mesgs_count, $pagination_size=10, array $conf); * $navigation_str = $pagi->generate($current_page_number); */ class Pagination{ private $page, $total_page, $total, $page_size, $size; private $prev_str = "<", $next_str = ">"; private $class, $selected_class = "selected", $prev_class="prev", $next_class="next", $de_prev_class="de_prev", $de_next_class="de_next"; private $url_prefix="", $split_char="?"; private $para_name = "page", $target = ""; public function Pagination($url_prefix, $page_size, $total, $size=10, $conf=array()){ $this->page = 1; $this->page_size = $page_size; $this->total = $total; $this->total_page = intval(ceil($total/$page_size)); $this->size = $size; if(!empty($conf)){ $configure = array("prev_str", "next_str", "class", "selected_class"); foreach($conf as $key => $val){ if(in_array($key, $configure)){ $this->$val = $val; } } } $this->url_prefix = $url_prefix; if(strstr($url_prefix, '?') !== false){ $this->url_prefix .= "&" . $this->para_name . "="; }else{ $this->url_prefix .= "?" . $this->para_name . "="; } } public function generate($page){ $this->page = $page; if(isset($this->page[$page])){ return $this->page_str[$page]; } $page_start = 1; $half = intval($this->size/2); $page_start = max(1, $page - $half); $page_end = min($page_start + $this->size - 1, $this->total_page); $page_start = max(1, $page_end - $this->size + 1); $this->page_str[$page] = $this->build_nav_str($page_start, $page_end); return $this->page_str[$page]; } private function build_nav_str($page_start, $page_end){ $page_nums = range($page_start, $page_end); $target = $this->target? " target=\"{$this->target}\"" : ""; if($this->page == 1){ $page_str = <<<html <span class="{$this->de_prev_class}"> {$this->prev_str} </span> HTML; }else{ $page = $this->page - 1; $page_str = <<<html <span class="{$this->prev_class}"> <a href="{$this->url_prefix}{$page}"{$this->target}>{$this->prev_str}</a></span> HTML; } foreach($page_nums as $p){ $page_str .= ($p == $this->page) ? <<<html <span class="{$this->selected_class}">{$p}</span> HTML : <<<html <span class="{$this->class}"><a href="{$this->url_prefix}{$p}"{$this->target}>{$p}</a></span> HTML; } if($this->page == $this->total_page){ $page_str .= <<<html <span class="{$this->de_next_class}"> {$this->next_str} </span> HTML; }else{ $page = $this->page + 1; $page_str .= <<<html <span class="{$this->next_class}"> <a href="{$this->url_prefix}{$page}"{$this->target}>{$this->next_str}</a></span> HTML; } return $page_str; } public function tidy_str(){ ;//void } public function __call($func_name, $arguments){ if(isset($this->$func_name)){ return $this->$func_name; } } public function __destruct(){ unset($this->page_str); unset($this); } }
2023年08月28日
8 阅读
0 评论
0 点赞
2023-08-12
PHP单文件路由类
PHP单文件路由类路由类Router.php<?phpclass Router { private $routes = []; private $routeCount = 0; public function addRoute($method, $url, $callback) { $this->routes[] = ['method' => $method, 'url' => $url, 'callback' => $callback]; $this->routeCount++; } public function doRouting() { $is_match=0; // I used PATH_INFO instead of REQUEST_URI, because the // application may not be in the root direcory // and we dont want stuff like ?var=value $reqUrl = parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH);//$_SERVER['PATH_INFO']; if ($reqUrl == null) { $reqUrl = ''; } $reqMet = $_SERVER['REQUEST_METHOD']; foreach ($this->routes as $route) { // convert urls like '/users/:uid/posts/:pid' to regular expression $patterns = array('/\[[a-zA-Z0-9\_\-\/]+\]/','/\[{[a-zA-Z0-9\_\-}]+\]/','/\[\/{[a-zA-Z0-9\_\-}]+\]/','/{[a-zA-Z0-9\_\-}]+/'); $replace = array('([a-zA-Z0-9\-\_\/]*)','([a-zA-Z0-9\-\_]*)','([a-zA-Z0-9\-\_\/]*)','([a-zA-Z0-9\-\_]+)'); // $pattern = "@^" . preg_replace('/\\\:[a-zA-Z0-9\_\-]+/', '([a-zA-Z0-9\-\_]+)', preg_quote($route['url'])) . "$@D"; $pattern = "@^" . preg_replace($patterns, $replace, $route['url']) . "$@D"; $matches = array(); // check if the current request matches the expression if (preg_match($pattern, $reqUrl, $matches)) { // remove the first match array_shift($matches); foreach ($matches as $key => $value) { if (empty($value)) { unset($matches[$key]); } } // call the callback with the matched positions as params if ($route['method'] !=='*' && $reqMet !=='HEAD' && ( !empty($route['method']) && !in_array($reqMet, explode(',', $route['method']))) ) { throw new Exception("405 Not Allowed"); } return call_user_func_array($route['callback'], $matches); } else { $is_match++; } } if ($is_match == $this->routeCount) { throw new Exception("404 Not Found"); } } } //autoload // spl_autoload_register(function ($class_name) { // require_once __DIR__ . '/' . str_replace('\\', '/', $class_name) . '.php'; // }); 路由配置文件config/route.php <?php return [ [ ['GET'], '/', [new App\Index, 'index'], ], [ ['GET'], '/search', [new App\Index, 'search'], ], [ ['GET'], '/tool-[id][/]', [new App\Index, 'tool'], ], [ ['GET'], '/tool-[id]', [new App\Index, 'tool'], ], [ ['GET'], '/category-[cid].html', [new App\Index, 'category'], ], [ ['PUT,GET'], '/hello', function () { echo 'Hello AmazePHP!'; }, ], [ ['GET'], '/hello2', 'callbackFunction', ], [ ['GET'], '/hello44.php', function () { include 'App/aaaaa.php'; }, ], [ ['GET'], '/hello3/[id]', [new App\Foo, 'bar'],////object, method ], [ ['GET'], '/a/[uid]/b[/pid]', ['App\myclass', 'say_hello'],//static method ], [ ['GET,POST'], '/users', function () { echo 'post AmazePHP'; }, ], [ ['*'], '/users/[uid]/posts/[pid]', function ($uid, $pid = 99) { var_dump($uid, $pid); }, ], ];使用方法index.php include 'lib/Router.php'; include 'config/route.php'; $router = new Router(); foreach (config('route') as $key => $value) { $router->addRoute($value[0][0], $value[1], $value[2]); } $router->doRouting();
2023年08月12日
16 阅读
0 评论
0 点赞
1
...
16
17
18
...
28