在我们全新升级的课程《Laravel 9优雅实战入门（第三版）》里，我们在重构controller数据逻辑到Repository中时，使用了PHP 8的构造函数简化传参功能，这里我们就对此扩展一下，帮助学员更好理解和应用：class Point { public int $x; public function __construct( int $x = 0 ) { $this->x = $x; } }传统上，我们要想往构造函数里传参，并且将其赋值给这个对象或类，供后期使用，我们都得上面这么写。写多了，就感觉挺烦的，尤其是变量多的时候：class Point { public int $x; public int $y; public int $z; public function __construct( int $x = 0, int $y = 0, int $z = 0, ) { $this->x = $x; $this->y = $y; $this->z = $z; } }比如这种情况，每个变量名就得写四遍，所以在PHP 8.0开始，可以进一步简写如下：class Point { public function __construct( public int $x = 0, public int $y = 0, public int $z = 0, ) {} }不能用于抽象的构造函数中这种新写法，在非抽象的类或trait里，是可以的，也即可实例化的类里。但是在抽象的类或interface里，就不允许了，比如下面写法是不行的：abstract class Test { // Error: Abstract constructor. abstract public function __construct(private $x); } interface Test { // Error: Abstract constructor. public function __construct(private $x); }注意这个Abstract constructor的报错信息，将来遇到的时候知道是怎么回事。默认为空值时class Test { // Error: Using null default on non-nullable property public function __construct(public Type $prop = null) { } }比如，如果这么写，它会报错Error: Using null default on non-nullable property，抱怨你将不可为空的属性，设置为空的默认值。也即你既然说了$prop是特定的Type，那么它就不能是null，类型就对不上。但是如果我们明确地声明，这个特定Type，可以为空，是可以的，比如下面这样：class Test { // Correct: Make the type explicitly nullable instead public function __construct(public ?Type $prop = null) {} }所以这里也是，当显示报错说Error: Using null default on non-nullable property的时候，也要知道是怎么回事。Callable Type不被允许由于callable不是一个被允许的属性类型，所以下面这么写会报错：class Test { // Error: Callable type not supported for properties. public function __construct(public callable $callback) {} }
ColorSublime | 代码高亮主题管理插件，安装成功后需要照着文档配置两个地方；Blade Snippets | Blade 模板自动补全Laravel Blade Highlighter| Blade 语法高亮支持SyncedSideBar| 自动在左边文件夹树中定位当前文件ALign Argumentscommand + control + a 快速对齐
<?PHP /* * @author 小伍 */ echo " "; $proxy = array('url'=>'http://localhost:8087'); print_r(xCurl('http://www.cnblogs.com/picaso',true,array(),null,null,$proxy)); function xCurl($url,$return=true,$postData=array(),$cookiePath=null,$referer=null,$proxy=array(),$userAgent="Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)") { $ch = curl_init(); $optionArray = array( CURLOPT_AUTOREFERER => true, CURLOPT_URL => $url, //目标URL CURLOPT_HEADER => 0, CURLOPT_RETURNTRANSFER => 1, //不直接打印显示 CURLOPT_CONNECTTIMEOUT => 3, //连接超时3s CURLOPT_TIMEOUT => 12, //执行超时12s CURLOPT_SSL_VERIFYPEER => false, CURLOPT_SSL_VERIFYHOST => false //此处两个SSL相关参数是适应HTTPS网页 ); if(count($proxy) > 0){ //网页代理设置，代理，大家都懂的，可以做很多事 $optionArray[CURLOPT_HTTPPROXYTUNNEL] = true; //HTTP代理开关 if(!empty($proxy['type']) && $proxy['type'] == 'socket'){ $optionArray[CURLOPT_PROXYTYPE] = CURLPROXY_SOCKS5; //可以使用socket代理（×这里我没有测试socket代理） } $optionArray[CURLOPT_PROXY] = $proxy['url'];if (!empty($proxy['auth'])) { //代理验证 $optionArray[CURLOPT_PROXYAUTH] = false;$optionArray[CURLOPT_PROXYUSERPWD] = $proxy['auth']; //格式 username:password } } if(!empty($referer)) { //HTTP头部的referer $optionArray[CURLOPT_REFERER] = $referer; } if(!empty($userAgent)) { //HTTP头部的UserAgent $optionArray[CURLOPT_USERAGENT] = $userAgent; } if (!empty($cookiePath)) { //Cookie的保存与传递（cookiePath是一个cookie文件，自定义即可） $optionArray[CURLOPT_COOKIEFILE] = $cookiePath; //传递cookie $optionArray[CURLOPT_COOKIEJAR] = $cookiePath; //保存cookie } if(count($postData) > 0){ //post传值 $optionArray[CURLOPT_POST] = 1; $optionArray[CURLOPT_POSTFIELDS] = $postData; } curl_setopt_array($ch, $optionArray); $content = curl_exec($ch); if(!curl_errno($ch)){ $output = curl_getinfo($ch); } curl_close($ch); if($return) { $output['content'] = $content; return $output; } else { echo $content; } } ?>1.简介： 能够抓取HTTP和HTTPS页面； 能够记录、使用cookie； 能够使用HTTP代理（socket代理可以使用，效果未检测），支持代理验证； 可以自定义Referer、UserAgent； 检查链路信息，包含状态码等（返回结果数组详见curl_getinfo函数数据解释）2.用途： 换IP作业：邮件群发，注册帐号，发布软文等； 接口处理：API接口处理（可以精简本代码）； 网页采集：太不道德了3.扩展功能: CURL也可以伪造IP，别干坏事哦～～ curl_setopt($ch, CURLOPT_HTTPHEADER, array('X-FORWARDED-FOR:8.8.8.8', 'CLIENT-IP:8.8.8.8'));4.用法： 会调用函数就会使用，So easy～只是一函数而已，参数显得很乱，有兴趣可以改写成class类
目录一、总结二、php之static静态变量详解1、什么是static静态变量？（以下为在C语言中的理解）2、静态局部变量：3、静态全局变量4、PHP中代码实例三、测试题-简答题1、静态变量的存储位置在哪？2、静态局部变量是什么？3、函数体内如果在定义静态变量的同时进行了初始化，那么下次执行程序的时候还会初始化么？4、静态局部变量的初始化在函数中只执行一次，那么静态局部变量的赋初值也只执行一次么？5、静态局部变量和局部变量的区别？6、静态全局变量和全局变量的区别？7、静态局部变量适合多用么？回到顶部一、总结把局部变量改变为静态变量后是改变了它的存储方式，即改变了它的生存期。把全局变量改变为静态变量后是改变了它的作用域，限制了它的使用范围。回到顶部二、php之static静态变量详解1、什么是static静态变量？（以下为在C语言中的理解）静态变量 类型说明符是static。静态变量属于静态存储方式，其存储空间为内存中的静态数据区（在静态存储区内分配存储单元），该 区域中的数据在整个程序的运行期间一直占用这些存储空间（在程序整个运行期间都不释放），也可以认为是其内存地址不变，直到整个程序运行结束（相反，而 auto自动变量，即动态局部变量，属于动态存储类别，占动态存储空间，函数调用结束后即释放）。静态变量虽在程序的整个执行过程中始终存在，但是在它作 用域之外不能使用。另外，属于静态存储方式的变量不一定就是静态变量。 例如：外部变量(在PHP中指全局变量)虽属于静态存储方式，但不一定是静态变量，必须由 static加以定义后才能成为静态外部变量，或称静态全局变量。所有的全局变量都是静态变量，而局部变量只有定义时加上类型修饰符static，才为局部静态变量。静态变量可以在任何可以申请的地方申请，一旦申请成功后，它将不再接受其他的同样申请。静态变量并不是说其就不能改变值，不能改变值的量叫常量。 其拥有的值是可变的 ，而且它会保持最新的值。说其静态，是因为它不会随着函数的调用和退出而发生变化。即上次调用函数的时候，如果我们给静态变量赋予某个值的话，下次函数调用时，这个值保持不变。2、静态局部变量：1、static类型的内部变量同auto自动变量（即未加 static 声明的局部变量）一样，是某个特定函数的局部变量，即只能在定义该变量的函数内使用该变量，两者作用域相同；两者的不同在于：auto自动变量会随着函数被调用和退出而存在和消失，而static类局部变量不会，它不管其所在的函数是否被调用，都将一直存在；不过，尽管该变量还继续存在，但不能使用它。倘若再次调用定义它的函数时，它又可继续使用，而且保存了前次被调用后留下的值。换言之，static类型的内部变量是一种只能在某个特定函数中使用，但一直占据存储空间的变量。2、函数体内如果在定义静态变量的同时进行了初始化，则以后程序不再进行初始化操作（出现在函数内部的基本类型的的静态变量初始化语句只有在第一次调用才执行）。而对自动变量赋初值是在函数调用时进行，每调用一次函数重新给一次初值，相当于执行一次赋值语句。3、静态局部变量的初始化表达式必须是一个常量或者常量表达式。即使局部静态变量定义时没有赋初值，系统会自动赋初值0（对数值型变量）或空字符（对字符变量）；静态变量的初始值为0。而对自动变量auto来说，如果不赋初值则它的值将是个不确定的值。4、当多次调用一个函数且要求在调用之间保留某些变量的值时，可考虑采用静态局部变量。虽然用全局变量也可以达到上述目的，但全局变量有时会造成意外的副作用（主要是变量的作用域造问题成的），因此仍以采用局部静态变量为宜。注：局部静态变量占用内存时间较长，并且可读性差，因此，除非必要，尽量避免使用局部静态变量。3、静态全局变量全局变量(外部变量)的声明之前再冠以static 就构成了静态的全局变量。全局变量本身就是静态存储方式，静态全局变量当然也是静态存储方式。这两者在存储方式上并无不同。这两者的区别虽在于：1、非静态全局变量的作用域是整个源程序，当一个源程序由多个源文件组成时，非静态的全局变量在各个源文件中都是有效的。2、静态全局变量则限制了其作用域， 即只在定义该变量的源文件内有效，在同一源程序的其它源文件中不能使用它。从以上分析可以看出————把局部变量改变为静态变量后是改变了它的存储方式，即改变了它的生存期。把全局变量改变为静态变量后是改变了它的作用域，限制了它的使用范围。static静态变量会被放在程序的全局存储区中（即在程序的全局数据区，而不是在堆栈中分配，所以不会导致堆栈溢出），这样可以在下一次调用的时候还可以保持原来的赋值。这一点是它与堆栈变量和堆变量的区别。4、PHP中代码实例<?php //--------------如何理解static静态变量----------- /** 普通局部变量 */ function local() { $loc = 0; //这样，如果直接不给初值0是错误的。 ++$loc; echo $loc . ' '; } local(); //1 local(); //1 local(); //1 echo '=================================== '; /** static静态局部变量 */ function static_local() { static $local = 0 ; //此处可以不赋0值 $local++; echo $local . ' '; } static_local(); //1 static_local(); //2 static_local(); //3 //echo $local; 注意虽然静态变量，但是它仍然是局部的，在外不能直接访问的。 echo '======================================= '; /** static静态全局变量(实际上:全局变量本身就是静态存储方式,所有的全局变量都是静态变量) */ function static_global() { global $glo; //此处，可以不赋值0，当然赋值0，后每次调用时其值都为0，每次调用函数得到的值都会是1，但是不能想当然的写上"static"加以修饰，那样是错误的. $glo++; echo $glo . ' '; } static_global(); //1 static_global(); //2 static_global(); //3 ?> 回到顶部三、测试题-简答题1、静态变量的存储位置在哪？解答：static静态变量会被放在程序的全局存储区中（即在程序的全局数据区，而不是在堆栈中分配，所以不会导致堆栈溢出）2、静态局部变量是什么？解答：局部变量用static关键词修饰，储存到全局数据区，static类型的内部变量是一种只能在某个特定函数中使用，但一直占据存储空间的变量。3、函数体内如果在定义静态变量的同时进行了初始化，那么下次执行程序的时候还会初始化么？解答：函数体内如果在定义静态变量的同时进行了初始化，则以后程序不再进行初始化操作（出现在函数内部的基本类型的的静态变量初始化语句只有在第一次调用才执行）。而对自动变量赋初值是在函数调用时进行，每调用一次函数重新给一次初值，相当于执行一次赋值语句。4、静态局部变量的初始化在函数中只执行一次，那么静态局部变量的赋初值也只执行一次么？解答：静态变量的赋初值会调用一次函数执行一次，一般会执行很多次，和静态函数的初始化不同。5、静态局部变量和局部变量的区别？解答：把局部变量改变为静态变量后是改变了它的存储方式，即改变了它的生存期。作用域还相同。6、静态全局变量和全局变量的区别？解答：把全局变量改变为静态变量后是改变了它的作用域，限制了它的使用范围。静态全局变量则限制了其作用域， 即只在定义该变量的源文件内有效。非静态全局变量的作用域是整个源程序，当一个源程序由多个源文件组成时，非静态的全局变量在各个源文件中都是有效的。7、静态局部变量适合多用么？解答：局部静态变量占用内存时间较长，并且可读性差，因此，除非必要，尽量避免使用局部静态变量。
php获取从百度搜索进入网站的关键词的详细代码
<?php function search_word_from() { $referer = isset($_SERVER['HTTP_REFERER'])?$_SERVER['HTTP_REFERER']:''; if(strstr( $referer, 'baidu.com')){ //百度 preg_match( "|baidu.+wo?r?d=([^\\&]*)|is", $referer, $tmp ); $keyword = urldecode( $tmp[1] ); $from = 'baidu'; }elseif(strstr( $referer, 'google.com') or strstr( $referer, 'google.cn')){ //谷歌 preg_match( "|google.+q=([^\\&]*)|is", $referer, $tmp ); $keyword = urldecode( $tmp[1] ); $from = 'google'; }elseif(strstr( $referer, 'so.com')){ //360搜索 preg_match( "|so.+q=([^\\&]*)|is", $referer, $tmp ); $keyword = urldecode( $tmp[1] ); $from = '360'; }elseif(strstr( $referer, 'sogou.com')){ //搜狗 preg_match( "|sogou.com.+query=([^\\&]*)|is", $referer, $tmp ); $keyword = urldecode( $tmp[1] ); $from = 'sogou'; }elseif(strstr( $referer, 'soso.com')){ //搜搜 preg_match( "|soso.com.+w=([^\\&]*)|is", $referer, $tmp ); $keyword = urldecode( $tmp[1] ); $from = 'soso'; }else { $keyword =''; $from = ''; } return array('keyword'=>$keyword,'from'=>$from); } //以下为测试 //在搜索引擎搜索个关键词，进入网站 $word = search_word_from(); if(!empty($word['keyword'])){ echo '关键字：'.$word['keyword'].' 来自：'.$word['from']; } ?>
html表单代码： 名称： 电话： 留言： index.php代码为：<?php //接收表单提交的数据 $name = $_POST['name']; $tel = $_POST['tel']; $des= $_POST['des']; $url = $_POST['url']; $ip = $_POST['ip']; if($name!=""&&$tel!=""){//判断name、tel是否为空 require_once ('send.php'); //########################################## $smtpserver = "";//SMTP服务器 $smtpserverport =25;//SMTP服务器端口 $smtpusermail = "";//SMTP服务器的用户邮箱 $smtpemailto = "";//发送给谁 $smtpuser = "";//SMTP服务器的用户帐号 $smtppass = "";//SMTP服务器的用户密码 $mailsubject = "预约提醒";//邮件主题 $mailbody = " 在线预约提醒 姓名：".$name." 联系方式：".$tel." 留言：".$des." 提交URL：".$url." 提交时间：".date('Y-m-d H:i:s',time())." IP地址：".$ip." (仅供参考)";//邮件内容 $mailtype = "HTML";//邮件格式（HTML/TXT）,TXT为文本邮件 //########################################## $smtp = new smtp($smtpserver,$smtpserverport,true,$smtpuser,$smtppass); $smtp->debug = false;//是否显示发送的调试信息 $smtp->sendmail($smtpemailto, $smtpusermail, $mailsubject, $mailbody, $mailtype); echo " "; } echo " "; ?>send.php代码为：<? class smtp { /* Public Variables */ public $smtp_port; public $time_out; public $host_name; public $log_file; public $relay_host; public $debug; public $auth; public $user; public $pass; /* Private Variables */ private $sock; /* Constractor */ function smtp($relay_host = "", $smtp_port = 25,$auth = false,$user,$pass) { $this->debug = FALSE; $this->smtp_port = $smtp_port; $this->relay_host = $relay_host; $this->time_out = 30; //is used in fsockopen() # $this->auth = $auth;//auth $this->user = $user; $this->pass = $pass; # $this->host_name = "localhost"; //is used in HELO command $this->log_file =""; $this->sock = FALSE; } /* Main Function */ function sendmail($to, $from, $subject = "", $body = "", $mailtype, $cc = "", $bcc = "", $additional_headers = "") { $mail_from = $this->get_address($this->strip_comment($from)); $body = preg_replace("/(^|(\r\n))(\\.)/", "\\1.\\3", $body); $header .= "MIME-Version:1.0\r\n"; if($mailtype=="HTML"){ $header .= "Content-Type:text/html;charset=gb2312\r\n"; } $header .= "To: ".$to."\r\n"; if ($cc != "") { $header .= "Cc: ".$cc."\r\n"; } $header .= "From: $from<".$from.">\r\n"; $header .= "Subject: ".$subject."\r\n"; $header .= $additional_headers; $header .= "Date: ".date("r")."\r\n"; $header .= "X-Mailer:By Redhat (PHP/".phpversion().")\r\n"; list($msec, $sec) = explode(" ", microtime()); $header .= "Message-ID: <".date("YmdHis", $sec).".".($msec*1000000).".".$mail_from.">\r\n"; $TO = explode(",", $this->strip_comment($to)); if ($cc != "") { $TO = array_merge($TO, explode(",", $this->strip_comment($cc))); } if ($bcc != "") { $TO = array_merge($TO, explode(",", $this->strip_comment($bcc))); } $sent = TRUE; foreach ($TO as $rcpt_to) { $rcpt_to = $this->get_address($rcpt_to); if (!$this->smtp_sockopen($rcpt_to)) { $this->log_write("Error: Cannot send email to ".$rcpt_to."\n"); $sent = FALSE; continue; } if ($this->smtp_send($this->host_name, $mail_from, $rcpt_to, $header, $body)) { $this->log_write("E-mail has been sent to <".$rcpt_to.">\n"); } else { $this->log_write("Error: Cannot send email to <".$rcpt_to.">\n"); $sent = FALSE; } fclose($this->sock); $this->log_write("Disconnected from remote host\n"); } //echo " "; //echo $header; return $sent; } /* Private Functions */ function smtp_send($helo, $from, $to, $header, $body = "") { if (!$this->smtp_putcmd("HELO", $helo)) { return $this->smtp_error("sending HELO command"); } #auth if($this->auth){ if (!$this->smtp_putcmd("AUTH LOGIN", base64_encode($this->user))) { return $this->smtp_error("sending HELO command"); } if (!$this->smtp_putcmd("", base64_encode($this->pass))) { return $this->smtp_error("sending HELO command"); } } # if (!$this->smtp_putcmd("MAIL", "FROM:<".$from.">")) { return $this->smtp_error("sending MAIL FROM command"); } if (!$this->smtp_putcmd("RCPT", "TO:<".$to.">")) { return $this->smtp_error("sending RCPT TO command"); } if (!$this->smtp_putcmd("DATA")) { return $this->smtp_error("sending DATA command"); } if (!$this->smtp_message($header, $body)) { return $this->smtp_error("sending message"); } if (!$this->smtp_eom()) { return $this->smtp_error("sending <CR><LF>.<CR><LF> [EOM]"); } if (!$this->smtp_putcmd("QUIT")) { return $this->smtp_error("sending QUIT command"); } return TRUE; } function smtp_sockopen($address) { if ($this->relay_host == "") { return $this->smtp_sockopen_mx($address); } else { return $this->smtp_sockopen_relay(); } } function smtp_sockopen_relay() { $this->log_write("Trying to ".$this->relay_host.":".$this->smtp_port."\n"); $this->sock = @fsockopen($this->relay_host, $this->smtp_port, $errno, $errstr, $this->time_out); if (!($this->sock && $this->smtp_ok())) { $this->log_write("Error: Cannot connenct to relay host ".$this->relay_host."\n"); $this->log_write("Error: ".$errstr." (".$errno.")\n"); return FALSE; } $this->log_write("Connected to relay host ".$this->relay_host."\n"); return TRUE;; } function smtp_sockopen_mx($address) { $domain = preg_replace("/^.+@([^@]+)$/", "\\1", $address); if (!@getmxrr($domain, $MXHOSTS)) { $this->log_write("Error: Cannot resolve MX \"".$domain."\"\n"); return FALSE; } foreach ($MXHOSTS as $host) { $this->log_write("Trying to ".$host.":".$this->smtp_port."\n"); $this->sock = @fsockopen($host, $this->smtp_port, $errno, $errstr, $this->time_out); if (!($this->sock && $this->smtp_ok())) { $this->log_write("Warning: Cannot connect to mx host ".$host."\n"); $this->log_write("Error: ".$errstr." (".$errno.")\n"); continue; } $this->log_write("Connected to mx host ".$host."\n"); return TRUE; } $this->log_write("Error: Cannot connect to any mx hosts (".implode(", ", $MXHOSTS).")\n"); return FALSE; } function smtp_message($header, $body) { fputs($this->sock, $header."\r\n".$body); $this->smtp_debug("> ".str_replace("\r\n", "\n"."> ", $header."\n> ".$body."\n> ")); return TRUE; } function smtp_eom() { fputs($this->sock, "\r\n.\r\n"); $this->smtp_debug(". [EOM]\n"); return $this->smtp_ok(); } function smtp_ok() { $response = str_replace("\r\n", "", fgets($this->sock, 512)); $this->smtp_debug($response."\n"); if (!preg_match("/^[23]/", $response)) { fputs($this->sock, "QUIT\r\n"); fgets($this->sock, 512); $this->log_write("Error: Remote host returned \"".$response."\"\n"); return FALSE; } return TRUE; } function smtp_putcmd($cmd, $arg = "") { if ($arg != "") { if($cmd=="") $cmd = $arg; else $cmd = $cmd." ".$arg; } fputs($this->sock, $cmd."\r\n"); $this->smtp_debug("> ".$cmd."\n"); return $this->smtp_ok(); } function smtp_error($string) { $this->log_write("Error: Error occurred while ".$string.".\n"); return FALSE; } function log_write($message) { $this->smtp_debug($message); if ($this->log_file == "") { return TRUE; } $message = date("M d H:i:s ").get_current_user()."[".getmypid()."]: ".$message; if (!@file_exists($this->log_file) || !($fp = @fopen($this->log_file, "a"))) { $this->smtp_debug("Warning: Cannot open log file \"".$this->log_file."\"\n"); return FALSE; } flock($fp, LOCK_EX); fputs($fp, $message); fclose($fp); return TRUE; } function strip_comment($address) { $comment = "/\\([^()]*\\)/"; while (preg_match($comment, $address)) { $address = preg_replace($comment, "", $address); } return $address; } function get_address($address) { $address = preg_replace("/([ \t\r\n])+/", "", $address); $address = preg_replace("/^.*<(.+)>.*$/", "\\1", $address); return $address; } function smtp_debug($message) { if ($this->debug) { echo $message." "; } } function get_attach_type($image_tag) { // $filedata = array(); $img_file_con=fopen($image_tag,"r"); unset($image_data); while ($tem_buffer=AddSlashes(fread($img_file_con,filesize($image_tag)))) $image_data.=$tem_buffer; fclose($img_file_con); $filedata['context'] = $image_data; $filedata['filename']= basename($image_tag); $extension=substr($image_tag,strrpos($image_tag,"."),strlen($image_tag)-strrpos($image_tag,".")); switch($extension){ case ".gif": $filedata['type'] = "image/gif"; break; case ".gz": $filedata['type'] = "application/x-gzip"; break; case ".htm": $filedata['type'] = "text/html"; break; case ".html": $filedata['type'] = "text/html"; break; case ".jpg": $filedata['type'] = "image/jpeg"; break; case ".tar": $filedata['type'] = "application/x-tar"; break; case ".txt": $filedata['type'] = "text/plain"; break; case ".zip": $filedata['type'] = "application/zip"; break; default: $filedata['type'] = "application/octet-stream"; break; } return $filedata; } } ?>
第一种方法：用header()函数；header ( "Location: http://www.xaheimi.com/aaa.php" ); 或：header ( "Location: aaa.php" ); 第二种方法:在服务器端执行:即在服务器端PHP文件解析的时候执行,使用include(),require()函数将文件引入include("thatday.php"); 然后调用thatday.php中的主函数第三种方法：在客户端执行:此方法的效果等同于iframe,即会产对所执行文件的一次访问.