php细嚼

2019-01-11  本文已影响0人  某言

语言只是工具,要的是思路,这里是一些常用又忽视的东西,后者有帮助的东西.

php

基础理解

经验

# base.php
    namespace app;
    use libs\classOne;
    use libs\classTwo;
    //自动加载
    spl_autoload_register(function($className){
        $className = str_replace('\\',DIRECTORY_SEPARATOR,$className);
        echo $className; # 得到的是`libs\classOne`,命名空间的路径会被附带
        include($className.'.php');
    });
    $one = new  classOne();
    $two = new classTwo();
# libs/classOne.php
    namespace libs;
    class classOne{
        function __construct(){
            echo "this is initial of fileOne";
            echo PHP_EOL;
        }
        function show(){
            echo "This is show function of classOne";
            echo PHP_EOL;
        }
    }
# libs/classTwo.php
    namespace libs;
    class classTwo{
        function __construct(){
            echo "this is initial of fileOne";
            echo PHP_EOL;
        }
        function show(){
            echo "This is show function of classOne";
            echo PHP_EOL;
        }
    }
# app.php
# 如果不用use也可以,但是调用就要写全名了
    use \app\utils as path; # 其中没有类,只有方法和变量,只可路径别名了;
    use \app\utils\ClassA as ClassAUse;# ClassA是类,可以别名;
    include("utils/a.php");
    include("utils/b.php");
    path\showB();
    \app\utils\showB();
    $obj = new ClassAUse();
    $obj->showA();
# a.php
    namespace app\utils;
    class ClassA{
        function showA(){
            echo "this is show in a ";
            echo PHP_EOL;
        }
    }
# b.php
    namespace app\utils;
    function showB(){
        echo "this is show in b ";
        echo PHP_EOL;
    }

一般命名空间以入口文件所在目录为基点,按照目录来写命名空间,在spl_autoload_register()设计时候很有遍历

define("NAME","fairy",true);
if(true){
    define("AGE",24);
}
# const user = 'me' #打开注释报错
class Test{
    const version = 1.2;
    # define("GOOD",'here in'); #打开注释报错
    function show(){
        define("GOOD",'here in');
        echo NAME;
        echo PHP_EOL;
        echo Test::version;
        echo PHP_EOL;
        echo GOOD;
        # if(true){ # 打开注释报错
        #   const variable = 'show';
        # }
    }
}
$test = new Test();
$test->show();
# do.php
<?php
    require("./helper.php");
    showHello();
    showHelloTwo();
# helper.php
<?php
    require('./helperTwo.php');
    echo "hello,I am helper";
    echo PHP_EOL;
    function showHello(){
        echo "I am showHello of helper";
        echo PHP_EOL;
    }
# helperTwo.php
<?php
    echo "hello,I am helperTwo";
    echo PHP_EOL;
    function showHelloTwo(){
        echo "I am showHello of helperTwo";
        echo PHP_EOL;
    }

时候,当我在命令行执行php do.php时候,不会报错,输出的是:

输出图片

由此可见,do.php引入helper.php,helper.php引入helperTwo.php,此时do.php也有了helperTwo.php的方法.由此可见,php的引入,实际可以理解为在哪里require/include,就相当于在哪里插入了这个文件里面的所有代码.还有一点可以证明:如果helper.php中规定一个和helperTwo.php中的showHelloTwo()方法时候,会报错说:

报错说重复声明方法

而在python的import,有点不同的情况,若有a.py,b.py,c.py在同一目录下,简单代码如下:

# a.py
import b
b.show()
print("I am base.py ")
#b.showTwo() # 这里打开注释报错,不能够应用c.py中方法
# b.py
import c
print("I am helper")
helperTwo.showTwo()
def show():
    print("I am show from helper's show()")
# c.py
print("I am helperTwo")
def showTwo():
    print("I am show from helperTwo's showTwo()")

a.py引入b.py,b.py引入c.py,此时,a.py中可以使用b.py中方法,b.py可以使用c.py中方法,但是a.py中不可以使用c.py中方法,而c.py中的执行了的部分print('...')则在a.py中也会有.此时输入则是:

python a.py输出
# try{}catch(){}方法思路一览
function checkNum($val){
    if($val<1){
        throw new Exception("Data can not less than 1");
    }
}
try {
    checkNum(0);
    echo "Your number is ok";
    echo PHP_EOL;
} catch (Exception $e) {
    echo "error msg: ".$e->getMessage();
    echo PHP_EOL;
}
# 遇到error触发set_error_handler(),调用dealError函数进行处理
set_error_handler('dealError');
function dealError($errno,$errstr,$errfile,$errline){
    echo $errno."<br>";
    echo $errstr."<br>";
    echo $errfile."<br>";
    echo $errline."<br>";
    echo "this is dealing error";
}
# 主动触发set_error_handler函数
trigger_error("self define error");

常用语句效率

$times = 500000;
$start = microtime(true);
class Helper{
    public static function staticMethod(){
        $hello = "world";
        $good = "luck";
    }
    public function normalMethod(){
        $hello = "world";
        $good = "luck";
    }
}
for($i=0;$i<$times;$i++){
    // $good = new Helper();
    // $good->normalMethod();
    Helper::staticMethod();
}
$end = microtime(true);
$delta = $end-$start;
echo 'The code execute for '.$delta.' seconds';

结果:如果for循环内的部分如上,那么确实静态方法要高效些.如果for改一下如下:

$good = new Helper();
for($i=0;$i<$times;$i++){
    // $good->normalMethod();
    Helper::staticMethod();
}

实例化的过程在for外面,如此两者几乎没有什么太大的差别.

<?php

$times = 1000;
$start = microtime(true);

#include_once('/helper.php');
#include_once('/helperTwo.php');
include('/helper.php');
include('/helperTwo.php');
#include('./helper.php');
#include('./helperTwo.php');

$end = microtime(true);
$delta = $end-$start;
echo 'The code execute for '.$delta.' seconds';

相对路径会有一个遍历目录的过程;require_once()多了一个判断是否引入郭的过程.

//这的两个方法差别不是很大如果执行的次数较少,一般不容易遇到显示出差距的情况
$times = 1000000;
$start = microtime(true);

for($i=0;$i<$times;$i++){

    # str的""和''
    $inner = "ok";
    // $str = "this is test string {$inner}"; 
    $str = 'this is test string'.$inner; //比起上面较为高效
    
    //isset 和 strlen
    $foo = "dddd";
    $flag = null;
    #if(strlen($foo)<5){
    if(isset($foo{5})){  //比起上面较为高效
        $flag = true;
    } 
}
$end = microtime(true);
$delta = $end-$start;
echo 'The code execute for '.$delta.' seconds';
# 在blog时候就区别很大了,下面的语句,对于这个$str,没处理就存储的
# 最后大小可达60M+,而经过压缩的,大小不到200k,在网络上传输的时候,
# 差距可明显了
$times = 2500000;
$start = microtime(true);

$origin = "abcdefghijklmnopqrstuvwxyz";
$str = '';
for($i=0;$i<$times;$i++){
    #gzcompress和gzuncompress
    $str .= $origin;
}

# 压缩后在存储
$strDeal = gzcompress($str);
file_put_contents('db.txt', $strDeal);
$getStr = file_get_contents('db.txt');
$originStr = gzcompress($getStr);

# 直接存储
# file_put_contents('db.txt',$str);
# $originStr = file_get_contents('db.txt');

$end = microtime(true);
$delta = $end-$start;
echo 'The code execute for '.$delta.' seconds';

小工具

  1. 在命令行直接运行
php package.phar
  1. 引入程序和代码当外部库用
<?php
    # 下面两行include不能并存,重复声明了如果并存就
    # 直接引入,包括打包在里面的方法也一并引入
    include('user.phar');
    # 仅仅引入打包于其中的一个库
    include("phar://user.phar/User.class.php");
    /* 
    # 相对路径写法
    include('../user.phar');
    include("phar://../user.phar/User.class.php");
    */


    # 无论存在那个include,都可执行
    $user = new User();
    $user->introduce();
phar.readonly = 0

后重启服务器和命令行才行。

$phar = new Phar('build.phar');
// 添加project里面的所有文件到yunke.phar归档文件
$phar->buildFromDirectory(dirname(__FILE__));
$phar->compressFiles(Phar::GZ);
//设置执行phar时的源文件的入口文件,第一个入口用于命令行,第二个入口用于浏览器访问,这里都设置为index.php
$phar->setDefaultStub('index.php', 'index.php');

如上假设是个网页应用,则仅仅适合单入口文件的打包,多入口,目前不太知道如何多个入口。

# 初始化,生成一个composer.json文件
composer init  
# 更具composer.json和composer.lock文件,下载更新当前库
composer install
# 表明库版本的文件
composer.lock
# 安装某个库
composer require libraryName
# 创建项目
composer create-project
# 查看全局设定
composer config -gl
# 将镜像设定为中国的这个链接,比较快
composer config -g repo.packagist comoser https://packagist.phpcomposer.com
# 查看已存在的库
composer show -i
# 移除某个库
composer remove libraryName

凡是composer require安装的库,都会到vendor目录下,而vendor目录下有一个 文件:
autoload.php
如果想要运用vendor里面的所有库,只需要引入autoload.php即可使用下载的所有库了.比如最简单的日志模块monolog的使用:

# 必须引入这个才能够使用vendor中的库,引入后相当于暴露了相应的方法
include("vendor/autoload.php");
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
$log = new Logger('Kuroba');
$log->pushHandler(new StreamHandler('helper/your.log', Logger::WARNING));
// add records to the log
$log->warning('There are some errors');
$log->error('There are some mistakes');
php -S localhost:8888
system("command string","stdout string");
system("command string", [std , out , arr] , status[int])

像那些通过web来登陆控制台的就是利用这样的方法了吧.

  1. 下载相关版本和平台的.dll文件放在php的拓展目录【注意,要选择对应xdebug的版本才行,否则无效】,检测的链接是:请点击,之后,在本地跳出phpinfo的界面,将界面上的所有内容粘贴到提示框内,然后确定,就会得知是和的版本,之后再下载即可,或者执行phpinfo();来查看php的版本信息来对应下载相关的xdebug的版本,如下图:
    php版本信息
    如上图几个地方标注,对应下载的xdebug的后缀应该:
    php_xdebug-{xdebugVersion}-7.2-vc15-nts-x86_64.dll
  1. php.ini所增加配置:
# 注意我使用的是wamp集成环境,这个地方我的直接从文件夹打开php.ini加下列配置无效;
#而且我从wamp进去的php.ini和从文件里面打开的不是一个,虽然可能不是共性的问题,但是还是值得记录
# 遇到问题时候有个参照
[xdebug]
zend_extension ="D:/path/php5.6.25/ext/php_xdebug-2.2.5-5.6-vc11-x86_64.dll"
xdebug.auto_trace = On
xdebug.show_exception_trace = On
xdebug.remote_autostart = On
xdebug.remote_enable = On
xdebug.collect_vars = On
xdebug.collect_return = On
xdebug.collect_params = On
xdebug.trace_output_dir="D:/path/php5.6.25/xDebugLog"
xdebug.profiler_output_dir="D:/path/php5.6.25/xDebugLog"
xdebug.profiler_enable=On
xdebug.remote_host=localhost
xdebug.remote_port=9000
xdebug.remote_handler=dbgp
  1. 使用eclipese for phpvscode或者配置sublime即可以断点试调

上一篇下一篇

猜你喜欢

热点阅读