分类 PHP 下的文章

PSR编码规范简述

PSR

psr-0 自动加载

psr-1 基本代码规范

  • 文件内只出现 <?php<?= 标签 (必须)
  • 只是用utf-8 没有BOM头的php代码 (必须)
  • 声明新的类型符,不产生副作用
  • 命名空间遵循autoload自动加载psr-0/4规范(必须)
  • 类名驼峰(必须)
  • 类中的常量下划线_分隔(必须)
  • 方法驼峰(必须)

psr-2 代码样式

  • 必须遵循psr-1
  • 四个空格,而非tab
  • 限制每行长度 80或者更少
  • namespace 和 use 必须空格
  • 类的括号必须独立一行
  • 类的方法也一样
  • 所有的属性和方法必须在修饰符之前,static在之后
  • 关键词之后必须有空格
  • 代码流程控制,{ 在一行,}独立一行
  • {之后没有空格,}之前没有空格

psr-3 日志接口

  • 错误级别RFC 5424 (debug, info, notice, warning, error, critical, alert,
    emergency)

psr-4 自动加载

相比于 psr-0 规范比较干净 PSR-0规范中下划线_会被转化成为目录分割线
上面有详细的介绍,这里就不再重复

psr-6 缓存接口

psr-7 http消息接口

psr-11 容器接口

psr-13 超媒体链接

psr-15 http句柄

psr-16 简单缓存

  • 前言

    首先这种问题一般不会出现, 但是这个代码是别人写的, 里面相关的情况不是很清除, 网上的答案有很多,  包括在 `config/app.php` 里面在启动的时候被注册了导致的, 我顺着这个放心也查了很久, 最后找到原因, 答案不是这个
  • 错误源以及错误表现

    执行 `composer install -vvv` 到最后一步时就报错, 错误内容为代码报错, 代码内容大概是服务间登录, 获取token, 然后在配置不存在或者配置的地址不能联网的情况下, 执行这个服务间登录的代码, 就会取不到数据, 那段代码直接去返回的数组的键值, 然后出现了报错
    简单来说, 那个服务间的类被实例化就会出错, 因为实例化的时候调用了服务间登录的方法
  • 检查方向

    1. 网上的答案有很多,包括在 `config/app.php` 里面在启动的时候被注册了导致的, 我顺着这个放心也查了很久
    2. 然后我就把检索了所有的代码文件, 看看哪些地方使用了这个类, 后来发现在 `\App\Console\Commands\FixData.php` 中发现了可以的地方, 这个目录下的文件显然是一个自定义命令文件, 在执行laravel的方法时, 所有的命令都会被预加载, 预加载就以为命令中的 `__construct()` 方法, 这个方法体执行了实例化了那个服务间的类文件
  • 测试 (证明猜想)

    1. 我把那个文件中实例化这个服务间的类给注释掉, 再加一行var_dump([6666]), 重新执行 `composer install` 后不再报错了, 同时打印我调试的值, 正常运行完成
    2. 我把那个自定义命令文件的类后面的 `extends Command` 的前面加上注释, 重新执行了测试, 不在被执行这个类了, 我看了下这个自定义类的代码,是用于数据库迁移用途的,所以就这样注释下简单的解决了每次启动服务都实例化的问题
  • 总结

    laravel中的需要注意, 自定义命令在执行composer install的时候会被扫描, 其中的 所有命令文件中的 `__construct()` 方法都会被实例化

  • in_array 踩坑
如果写法 in_array('*',$arr);  这种写法是错误的, 如果 $arr=[0]; 该判断就为true了
正确写法 !empty(array_instract(["*"],$arr)); 通过判断交集是否为空来判断更准确, 避免数组中包含 0 时导致字符串in_array都为true的情况 

  • 创建php文件并执行测试 vi mailtest.php
<?php
function getHost($host)
{  //解析域名
    $getHost = gethostbyname($host);
    echo "尝试连接 $host ...<br>\r\n ";
    if (!$getHost) {
        echo "解析失败 (1)<HR>";
    } elseif ($getHost == $host) {
        echo "解析失败 (2): 可能是一个无效的主机名<HR>";
    } else {
        echo "域名解析为 $getHost ...<br>\r\n";
        openHost($host);
    }
}

function openHost($host)
{  //连接主机

    if (function_exists('fsockopen')) {
        $fp = fsockopen($host, 25, $errno, $errstr, 60);
    } elseif (function_exists('pfsockopen')) {
        echo "服务器不支持Fsockopen,尝试pFsockopen函数 ...<br>\r\n";
        $fp = pfsockopen($host, 25, $errno, $errstr, 60);
    } else
        exit('服务器不支持Fsockopen函数');

    if (!$fp) {
        echo "代号:$errno,<br>\n错误原因:$errstr<HR>";
    } else {
        echo "SMTP服务器连接ok!<br>\r\n";
        fwrite($fp, "");
        $out0 = fgets($fp, 128);
#echo $out0;
        foreach (["220"] as $port) {
            if (strncmp($out0, $port, 3) == 0) { // 判断三位字符内容
                echo $port . ' SMTP服务端响应正常<HR>';
            } else {
                echo $port . '服务器端错误<HR>';
            }
        }
    }
}

//SMTP服务器地址

foreach (["smtp.163.com", "smtp.sina.cn", "smtp.sina.com", "smtp.qq.com", "smtp.126.com", "smtp.gmail.com"] as $host) {
    echo getHost($host) . "\n\n\n";
}

if (function_exists('mail')) {
    echo 'mail方法正常';
}

如果以上正常,那么就检查是否邮箱帐号的问题

  • 查看是否开启openssl
php -r 'echo !extension_loaded('openssl')?"Not Available":"Available";';
执行结果
PHP Warning:  Use of undefined constant openssl - assumed 'openssl' (this will throw an Error in a future version of PHP) in Command line code on line 1
后来发现把内容写入到php文件中执行正常的
  • 未配置CA证书的情况
先查询配置文件路径
bash-4.4# php -i | grep cafile
openssl.cafile => no value => no value

创建ca文件, 把下载的CA文件的内容粘贴进去 [下载最新的CA cert文件](https://curl.haxx.se/ca/cacert.pem)
vi /etc/ssl/cacert.pem

修改php配置文件, 添加下面的内容
bash-4.4# vi /etc/php7/php.ini
openssl.cafile = /etc/ssl/cacert.pem
curl.cainfo = /etc/ssl/cacert.pem

判断是否开启openssl
php -m | grep openssl
如果没有开启,搜索php.ini下面内容, 把前面的;删除
extension=openssl


再次确认配置是否生效
bash-4.4# php -i | grep cafile
openssl.cafile => /etc/ssl/cacert.pem => /etc/ssl/cacert.pem
  • 最终还是查到了原因, 配置的域名邮箱的域名解析的关联mx值丢失导致的
MX记录
未设置或暂未生效

参考链接: https://github.com/PHPMailer/PHPMailer/wiki/Troubleshooting