首页
归档
朋友
关于我
留言
【Wiki知识库】
Search
1
虚拟机无法ping不通百度,并无法访问浏览器
4,586 阅读
2
mysql使用or条件使索引失效
3,618 阅读
3
mysql如何在一对多查询时选取时间最近的一条记录
2,972 阅读
4
根据MySQL获取当天,昨天,本周,本月,上周,上月,本月的起始时间
2,433 阅读
5
git常用命令大全
1,600 阅读
PHP
面向对象
设计模式
知识汇总
常用函数
PHP框架知识
数据库
MySQL
服务器
Docker
虚拟机
Nginx
缓存相关
Redis
前端
中间件
RabbitMQ
网络编程
HTTP相关
Swoole
Workerman
工具软件
Git
Typecho
杂乱无章
面试指南
PHP相关
MySQL面试汇总
中间件相关
开发技巧 | 优化
Search
标签搜索
php
mysql
代码片段
linux
Thinkphp
Redis
nginx
mysql优化
docker
面试指南
面向对象
git
Laravel框架
http协议
RabbitMQ
Redis性能优化
设计模式
linux命令
编译安装
PhpSpreadsheet
黎明强
累计撰写
70
篇文章
累计收到
58
条评论
首页
栏目
PHP
面向对象
设计模式
知识汇总
常用函数
PHP框架知识
数据库
MySQL
服务器
Docker
虚拟机
Nginx
缓存相关
Redis
前端
中间件
RabbitMQ
网络编程
HTTP相关
Swoole
Workerman
工具软件
Git
Typecho
杂乱无章
面试指南
PHP相关
MySQL面试汇总
中间件相关
开发技巧 | 优化
页面
归档
朋友
关于我
留言
搜索到
10
篇与
代码片段
的结果
2020-11-11
array_filter()、array_map()、array_walk()三者的用法和区别
用法 array_filter() 重点在于过滤(而不是新增)某个元素,当你处理到一个元素时,返回过滤后的数组 array_map() 重点在于遍历一个数组或多个数组的元素,返回一个新的数组 array_walk() 重点在于遍历数组进行某种操作区别array_filter() 和 array_walk()对一个数组进行操作,数组参数在前,函数参数在后array_map() 可以处理多个数组,因此函数参数在前,数组参数在后,可以根据实际情况放入多个数组参数array_filter() 该函数把输入数组中的每个键值传给回调函数。如果回调函数返回 true,则把输入数组中的当前键值返回结果数组中。数组键名保持不变。【如果没callback 就默认过滤false,空字符串空数组等】//没有回调函数的情况下,可以过滤false、空等数组 $arr =[1,2,false,0,'',3,4]; $new_arr = array_filter($arr); var_dump($arr); /*array(4) { [0]=> int(1) [1]=> int(2) [5]=> int(3) [6]=> int(4) }*/ $arr = ['a','b',1,2,3]; $new_arr = array_filter($arr,function($val){ return is_numeric($val); }); var_dump($new_arr); //返回结果 //array (size=3) // 2 => int 1 // 3 => int 2 // 4 => int 3array_map()该函数将用户自定义函数作用到数组中的每个值上,并返回用户自定义函数作用后的带有新值的数组。可以传递多个数组,回调函数接受的参数数目应该和传递给 array_map() 函数的数组数目一致。$arr1 = [1,2,3,4,5]; $arr2 = [6,7,8,9,10]; //函数写前面,数组参数写后面 (callback后面可以传入多个数组....) $new_arr = array_map(function($val1,$val2){ return $val1 + $val2; },$arr1,$arr2); var_dump($new_arr); //返回结果 //array (size=5) // 0 => int 7 // 1 => int 9 // 2 => int 11 // 3 => int 13 // 4 => int 15array_walk()对数组中的每个元素应用用户自定义函数//将数组中的元素用于某种操作 $arr = ['a','b','c']; array_walk($arr,function($val,$key){ echo "{$key} is {$val} <br/>"; }); //返回结果 //0 is a //1 is b //2 is c //改变数组中的值,传参的时候使用引用 array_walk($arr,function(&$val,$key){ $val .= $val; }); var_dump($arr); //array (size=3) // 0 => string 'aa' (length=2) // 1 => string 'bb' (length=2) // 2 => string 'cc' (length=2)
2020年11月11日
1,307 阅读
0 评论
0 点赞
2020-11-10
php替换富文本内容的所有img的链接或者其他内容
第一种 :img标签 追加绝对路径$httpUlr = 'http://www.xxx.com/'; $str = '<p>放假啊少打飞机啊速度开了个家里卡圣诞节</p> <p> </p> <p><img src="/uploads/20190326/cad4dcb78fca9e98cf1c45553f0a1a99.jpg" alt="" width="100" height="100" /></p>'; preg_replace('/src="\//', 'src="'."$httpUlr".'/', $str);替换src的内容以及链接$text = '内容<img src="http://www.test.com/test1.jpg">内容'; $replaceSrc = 'http://www.test.com/test2.jpg';//要替换的src echo preg_replace('#<img(.+?)src="([^"]+?)"([^>]*?)>#',"<img$1src=\"$replaceSrc\"$3>",$text); //内容<img src="http://www.test.com/test2.jpg">内容
2020年11月10日
770 阅读
0 评论
0 点赞
2020-11-10
PHP设置脚本最大执行时间的三种方法
php.ini 中缺省的最长执行时间是 30 秒,这是由 php.ini 中的 max_execution_time 变量指定,如果脚本需要跑很长时间,例如要大量发送电子邮件,或者分析统计大量数据,服务器会在 30 秒后强行中止正在执行的程序,这种情况就要更改php脚本最大执行时间。PHP设置脚本最大执行时间的三种方法在php.ini里面设置max_execution_time = 120;通过PHP的ini_set函数设置ini_set("max_execution_time", "120"); 设置120秒的意思通过set_time_limit 函数设置set_time_limit(120);以上几个数字设置为0则无限制,脚本会一直执行下去,直到执行结束。所以,需要长时间执行的脚本,一般在php代码开头处添加如下代码就可以了 set_time_limit(0);注意:方法一主要适用于网站已经做好了,后期维护人员对代码结构不熟悉,方法二和三适用于写代码时候,不过不推荐使用方法二,因为要注意ini_set函数是否会被禁用
2020年11月10日
1,288 阅读
0 评论
0 点赞
2020-11-10
PHP用户名用星号(*)处理或者手机号隐藏某一段
手机号星号屏蔽(简单版)//函数 【替换字符串的子串】 $phone = '15625599765'; //从第三位截取5个变成* $phone = substr_replace($phone,'***',3,5); echo $phone; //输出 : 156***765 //函数 【返回字符串的子串】 $mobile = '13912345678'; $newMobile1 = substr($mobile, 0, 5).'****'.substr($mobile, 9); echo $newMobile1; //13912****78 //正则 $mobile = '15625599765'; //d1 :首位长度 ,d2 尾部长度 $newMobile3 = preg_replace('/(\d{3})\d{4}(\d{2})/', '$1****$2', $mobile); echo $newMobile3; //156****9765用户名字星号屏蔽(支持UFT-8跟GB2312)// UTF-8中文正则:"/[\x{4e00}-\x{9fa5}]+/u" // GB2312中文正则:"/[".chr(0xa1)."-".chr(0xff)."]+/" $str = '黎明强'; //输出黎*强 $str ='黎明'; //黎* //判断是否包含中文字符 if(preg_match("/[\x{4e00}-\x{9fa5}]+/u", $str)) { //按照中文字符计算长度 $len = mb_strlen($str, 'UTF-8'); //echo '中文'; if($len >= 3){ //三个字符或三个字符以上掐头取尾,中间用*代替 $str = mb_substr($str, 0, 1, 'UTF-8') . '*' . mb_substr($str, -1, 1, 'UTF-8'); } elseif($len == 2) { //两个字符 $str = mb_substr($str, 0, 1, 'UTF-8') . '*'; } } else { //按照英文字串计算长度 $len = strlen($str); //echo 'English'; if($len >= 3) { //三个字符或三个字符以上掐头取尾,中间用*代替 $str = substr($str, 0, 1) . '*' . substr($str, -1); } elseif($len == 2) { //两个字符 $str = substr($str2, 0, 1) . '*'; } } echo $str;
2020年11月10日
1,524 阅读
0 评论
1 点赞
2020-11-08
PHP生成随机字符串
当我们需要生成一个随机名字,临时密码等字符串时可以用到下面的函数:代码如下function generateRandomString($length = 10) { $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; $randomString = ''; for ($i = 0; $i < $length; $i++) { $randomString .= $characters[rand(0, strlen($characters) - 1)]; } return $randomString; }使用方法echo generateRandomString(20);生成随机字符串/** * 随机生成字符串 * @param int $length * @return null|string */ private static function getRandChar($length = 8){ $str = null; $strPol = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghijklmnopqrstuvwxyz"; $max = strlen($strPol)-1; for($i=0;$i<$length;$i++){ $str.=$strPol[rand(0,$max)]; //rand($min,$max)生成介于min和max两个数之间的一个随机整数 } return $str; }
2020年11月08日
1,033 阅读
1 评论
0 点赞
2020-11-07
令人困惑的strtotime
经常会有人被strtotime结合-1 month, +1 month, next month的时候搞得很困惑, 然后就会觉得这个函数有点不那么靠谱, 动不动就出问题. 用的时候就会很慌…这不, 刚刚就有人在微博上又问我:鸟哥,今天是2018-07-31 执行代码:date("Y-m-d",strtotime("-1 month")) 怎么输出是2018-07-01?好的吧, 虽然这个问题看起来很迷惑, 但从内部逻辑上来说呢, 其实是”对”的, 你先别着急哈, 让我慢慢讲:我们来模拟下date内部的对于这种事情的处理逻辑:先做-1 month, 那么当前是07-31, 减去一以后就是06-31.再做日期规范化, 因为6月没有31号, 所以就好像2点60等于3点一样, 6月31就等于了7月1是不是逻辑很”清晰”呢? 我们也可以手动验证第二个步骤, 比如:var_dump(date("Y-m-d", strtotime("2017-06-31"))); //输出2017-07-01也就是说, 只要涉及到大小月的最后一天, 都可能会有这个迷惑, 我们也可以很轻松的验证类似的其他月份, 印证这个结论:var_dump(date("Y-m-d", strtotime("-1 month", strtotime("2017-03-31")))); //输出2017-03-03 var_dump(date("Y-m-d", strtotime("+1 month", strtotime("2017-08-31")))); //输出2017-10-01 var_dump(date("Y-m-d", strtotime("next month", strtotime("2017-01-31")))); //输出2017-03-03 var_dump(date("Y-m-d", strtotime("last month", strtotime("2017-03-31")))); //输出2017-03-03那怎么办呢?从PHP5.3开始呢, date新增了一系列修正短语, 来明确这个问题, 那就是”first day of” 和 “last day of”, 也就是你可以限定好不要让date自动”规范化”:var_dump(date("Y-m-d", strtotime("last day of -1 month", strtotime("2017-03-31")))); //输出2017-02-28 var_dump(date("Y-m-d", strtotime("first day of +1 month", strtotime("2017-08-31")))); ////输出2017-09-01 var_dump(date("Y-m-d", strtotime("first day of next month", strtotime("2017-01-31")))); ////输出2017-02-01 var_dump(date("Y-m-d", strtotime("last day of last month", strtotime("2017-03-31")))); ////输出2017-02-28那如果是5.3之前的版本(还有人用么?), 你可以使用mktime之类的, 把所有的日子忽略掉, 比如都限定为每月1号就可以了, 只不过就不如直接用first day来的更加优雅.现在, 搞清楚了内部原理, 是不是就不慌了?
2020年11月07日
785 阅读
2 评论
0 点赞
2020-11-07
理解依赖注入(DI)和控制反转(IOC) 、容器
简介依赖注入 Dependency Injection 简称 DI,目的是让代码耦合度降低,模块化程度高,让代码更易测试什么是依赖为什么会有依赖?因为我们为了模块化,把各种小功能都做成了一个模块,模块之间相互调用,这样就产生了依赖。耦合一个好的代码结构设计一定是松耦合的,这也是很多通用设计模式的宗旨,就是把分散在各处的同一个功能的代码汇聚到一起,形成一个模块,然后在不同模块之间通过一些细小的、明确的渠道进行沟通。在实践中,不同功能和模块之间的互相依赖是不可避免的,而如何处理好这些依赖之间的关系则是代码结构能否变得美好的关键。没有用依赖注入的情况传统的思路是应用程序用到一个User 类,就会创建User 类并调用User 类的方法,假如这个方法内需要一个Notify 类,就会创建Notify 类并调用Notify 类的方法,而这个方法内需要一个Email 类,就会创建Email 类,接着做些其它工作。//用户类 class User{ public function register($user) { echo "用户注册 | "; // 注册操作 // 发送确认邮件 $notify = new Notify(); $notify->sendEmail('register', $user); } } //通知类 class Notify{ public function sendEmail($type, $data) { echo "发送通知 | "; switch ($type) { case 'register': // 发送注册确认邮件 $email = new Email($type); $email->send($data); } } } //邮箱类 class Email{ public function send($data) { echo "发送邮件 | "; // 发送邮件 } } $user = new User(); $user->register('用户:黎明强'); // 用户注册 | 发送通知 | 发送邮件 |上述代码中,三个类之间逐层依赖,三个类实例化的顺序是 User -> Notify -> Email 。也就是说我先实例化User类,可能执行了一些代码之后再去实例化我需要的其他类,比如Notify,以此类推。这种依赖会让我们不得不为了得到需要的依赖而去做的一些准备工作,有时候可能一个new操作还不够。而这部分工作就是所说的耦合,他会让一个独立功能的类不得不去关心一些和自己的主体功能没什么关系的操作。如何解除一个类对其他类的依赖?要解决这个问题也很简单,我可以先实例化好Email类,然后再实例化Notify,然后把Email对象作为参数传给Notify,最后实例化User类,然后把Notify传进去。这就是所谓的依赖注入,可以看到这个过程中类实例化的顺序完全反过来了,先实例化被依赖的对象,而不是先实例化最终需要的对象,这是控制反转。使用依赖注入可以通过构造函数来注入需要的依赖,也可以用一些其他的方法。代码如下//用户类 class User{ protected $notify; public function __construct(Notify $notify) { $this->notify = $notify; } public function register($user) { echo "用户注册 | "; $this->notify->sendEmail('register',$user); } } //通知类 class Notify{ protected $email ; public function __construct(Email $email) { $this->email = $email; } public function sendEmail($type, $data) { echo "发送通知 | "; switch ($type) { case 'register': // 发送注册确认邮件 $this->email->send($data); } } } //邮箱类 class Email{ public function send($data) { echo '发送邮件 | '; // 发送邮件 } } //调用------- $email = new Email(); $notify = new Notify($email); $user = new User($notify); $user->register('liming'); // 用户注册 | 发送通知 | 发送邮件 |使用依赖注入的好处是显而易见的,我们通过参数了,让 email对象通过参数传到了 noitfy 类中,而不是在 noitfy 类中的方法中 实例化 email 类,从而将 email类和 noitfy 类解耦 。使用依赖注入容器来管理依赖那又有新的问题,例子中只有三个类还好,那如果这个User类依赖Notify来发邮件,依赖Model来存数据库,依赖redis来缓存,这样固然把依赖关系转移到了类的外部,但还是会导致我只想实例化一下User的时候,却要手动做很多的准备工作,会让代码混乱。所以这个时候需要一个容器。而这个容器的作用就是替我来管理这些依赖。1 、 定义容器类 这段代码使用了魔术方法,在给不可访问属性赋值时,__set() 会被调用。读取不可访问属性的值时,__get() 会被调用。// 容器 class Container { private $s = array(); function __set($k, $c) { $this->s[$k] = $c; } function __get($k) { return $this->s[$k]($this); } }在程序启动的时候,我们可以在一个地方统一的注册好一系列的基础服务。$c = new Container(); $c->email = function () { return new Email(); }; $c->notify = function ($c) { return new Notify($c->email); }; $c->user = function ($c) { return new User($c->notify); }; // 从容器中取得user $foo = $c->user; $foo->register('liming'); // 用户注册 | 发送通知 | 发送邮件 | 这段代码使用了匿名函数总之容器负责实例化,注入依赖,处理依赖关系等工作。再来一段简单的代码演示一下,容器代码class IoC { protected static $registry = []; public static function bind($name, Callable $resolver) { static::$registry[$name] = $resolver; } public static function make($name) { if (isset(static::$registry[$name])) { $resolver = static::$registry[$name]; return $resolver(); } throw new Exception('Alias does not exist in the IoC registry.'); } } IoC::bind('email', function () { return new Email(); }); IoC::bind('noitfy', function () { return new Notify(IoC::make('email')); }); IoC::bind('user', function () { return new User(IoC::make('noitfy')); }); echo "<pre>"; // 从容器中取得User $foo = IoC::make('user'); $foo->register('liming'); // 用户注册 | 发送通知 | 发送邮件 | 这段代码使用了后期静态绑定依赖注入容器 (dependency injection container) 高级功能 (难点)自动绑定(Autowiring)或 自动解析(Automatic Resolution)注释解析器(Annotations)延迟注入(Lazy injection)//用户类 class User{ protected $notify; public function __construct(Notify $notify) { $this->notify = $notify; } public function register($user) { echo "用户注册 | "; $this->notify->sendEmail('register',$user); } } //通知类 class Notify{ protected $email ; public function __construct(Email $email) { $this->email = $email; } public function sendEmail($type, $data) { echo "发送通知 | "; switch ($type) { case 'register': // 发送注册确认邮件 $this->email->send($data); } } } //邮箱类 class Email{ public function send($data) { echo '发送邮件 | '; // 发送邮件 } } class Container { private $s = array(); public function __set($k, $c) { $this->s[$k] = $c; } public function __get($k) { // return $this->s[$k]($this); return $this->build($this->s[$k]); } /** * 自动绑定(Autowiring)自动解析(Automatic Resolution) * * @param string $className * @return object * @throws Exception */ public function build($className) { // 如果是匿名函数(Anonymous functions),也叫闭包函数(closures) if ($className instanceof Closure) { // 执行闭包函数,并将结果 return $className($this); } /** @var ReflectionClass $reflector */ $reflector = new ReflectionClass($className); // 检查类是否可实例化, 排除抽象类abstract和对象接口interface if (!$reflector->isInstantiable()) { throw new Exception("Can't instantiate this."); } /** @var ReflectionMethod $constructor 获取类的构造函数 */ $constructor = $reflector->getConstructor(); // 若无构造函数,直接实例化并返回 if (is_null($constructor)) { return new $className; } // 取构造函数参数,通过 ReflectionParameter 数组返回参数列表 $parameters = $constructor->getParameters(); // 递归解析构造函数的参数 $dependencies = $this->getDependencies($parameters); // 创建一个类的新实例,给出的参数将传递到类的构造函数。 return $reflector->newInstanceArgs($dependencies); } /** * @param array $parameters * @return array * @throws Exception */ public function getDependencies($parameters) { $dependencies = []; /** @var ReflectionParameter $parameter */ foreach ($parameters as $parameter) { /** @var ReflectionClass $dependency */ $dependency = $parameter->getClass(); if (is_null($dependency)) { // 是变量,有默认值则设置默认值 $dependencies[] = $this->resolveNonClass($parameter); } else { // 是一个类,递归解析 $dependencies[] = $this->build($dependency->name); } } return $dependencies; } /** * @param ReflectionParameter $parameter * @return mixed * @throws Exception */ public function resolveNonClass($parameter) { // 有默认值则返回默认值 if ($parameter->isDefaultValueAvailable()) { return $parameter->getDefaultValue(); } throw new Exception('I have no idea what to do here.'); } } // ---- $c = new Container(); $c->noitfy = 'Notify'; $c->user = function ($c) { return new User($c->noitfy); }; // 从容器中取得Foo $foo = $c->user; $foo->register('liming'); // 用户注册 | 发送通知 | 发送邮件 | // ---- $di = new Container(); $di->user = 'User'; /** @var Foo $user */ $user = $di->user; echo "<pre>"; print_r($user); /* User Object ( [notify:protected] => Notify Object ( [email:protected] => Email Object ( ) ) ) */ $user->register('liming'); // 用户注册 | 发送通知 | 发送邮件 |以上代码的原理参考PHP官方文档:反射,PHP 5 具有完整的反射 API,添加了对类、接口、函数、方法和扩展进行反向工程的能力。 此外,反射 API 提供了方法来取出函数、类和方法中的文档注释。若想进一步提供一个数组访问接口,如di->user可以写成di−>user可以写成di['user'],则需用到ArrayAccess(数组式访问)接口 。一些复杂的容器会有许多特性,下面列出一些相关的github项目,欢迎补充。参考代码Twitteesimple di containerPimplePHP-DIDing推荐阅读PHP程序员如何理解IoC/DIPHP之道PHP最佳实践
2020年11月07日
854 阅读
0 评论
0 点赞
2020-11-07
php中call_user_func 与 call_user_func_array的使用
说明 call_user_func() 是利用回调函数处理字符串,call_user_func_array 是利用回调函数处理数组。代码例子// 1、 调用自定义函数 function test($a, $b) { echo $a + $b; } // 字符串传参 call_user_func('test', 1, 2); // 3 // 数组式传参 call_user_func_array('test', [1, 2]); // 3 // 2、 调用匿名函数 call_user_func(function($a, $b){ echo $a + $b ;}, 1, 2); // 3 call_user_func_array(function($a, $b){ echo $a + $b ;}, [1, 2]); // 3 // 3、 调用系统函数 echo call_user_func('strtoupper', 'abc'); // ABC echo call_user_func_array('strtoupper', ['abc']); // ABC // 4、 调用类中的函数 class Test { static public function demo($a, $b) { echo $a + $b; } public function show($a, $b) { echo $a + $b; } } // 调用类中的静态方法 // 类名方法名以数据形式 call_user_func(['Test', 'demo'], 1, 2); // 3 call_user_func_array(['Test', 'demo'], [1, 2]); // 3 // 类名方法名以字符串形式 call_user_func('Test::demo', 1, 2); // 3 call_user_func_array('Test::demo', [1, 2]); // 3 // 调用类中的动态方法,对象和方法必须通过数组形式传递 call_user_func([new Test, 'show'], 1, 2); // 3 call_user_func_array([new Test, 'show'], [1, 2]); // 3总结call_user_func 和 call_user_func_array不同在于传参方式,前者是字符串形式,后者是数组形式。二者皆可调用自定义函数、匿名函数、系统函数以及类中的静态动态方法。如在TP5.1中运用Facade门面类作为静态代理类,使用静态方式调用动态类中的动态方法,即让类无需实例化而直接进行静态方式的调用,带来了更好的可测试性和扩展性。在 thinkFacade类的最后有具体体现:
2020年11月07日
660 阅读
1 评论
0 点赞
1
2