主要记录学习过程中一些容易遗忘的点

基础操作

  1. mb_strlen($str, ‘utf8’):在utf8下,显示中文的字符数,否则在utf-8中文字符是长度为3,gbk或gb2312中文字符长度为2,拓展阅读
  2. explode(demitter, $string)和implode(demitter, $array):前者是把字符串根据demitter拆开变成数组,后者是把数组根据demitter组合成新的字符串;
  3. 定义常量有两种方式:define(‘CONSTANT’, ‘helloworld’, true); 或者 const CONSTANT = ‘helloworld’; 后者常用在类中定义常量,php5只能接收标量类型,php7还能接收array类型;常量可以直接echo CONSTANT; 也可以constant(CONSTANT);
  4. get_defined_constants():可以用来检查所有系统常量;
  5. require()是强加载,报错的话不会继续执行,include()则会继续执行;
  6. 开启严格模式 ```php <?php declare(strint_types = 1) function show(int $num) { return $num; } var_dump(‘2’); // 此时报错 因为已开启严格模式

function show2(int …$nums): int { return array_sum($nums); } echo show2(1,2,3,4,5,5);

  1. 7. 变量的**作用域**:php的变量作用域和JS有很大的不同,函数内部无法访问外部/全局变量
  2. ```php
  3. <?php
  4. $name = 'gaohang';
  5. function show() {
  6. global $name; // 1.引入name
  7. echo $name;
  8. echo $GLOBALS['name']; // 2.超全局变量
  9. }
  10. function show(&$name) { echo $name; } // 3.使用传值的方式
  11. show();
  1. static关键字:使变量在函数内持久保留;
  2. 变量函数,由此可见函数名实际上是string,此外function_exists()可以检查某个函数是否存在

    1. <?php
    2. function sum() {
    3. echo 'sum function';
    4. }
    5. $name = 'sum';
    6. echo $name();

    数组操作

  3. list()方法在遇到关连数组时,要这么使用,下标=>变量名,变量名可以随意,同索引数组一样 ```php <?php $arr = [‘name’=>’gaohang’, “age”=>25, “height”=>178]; list(‘name’=>$name, “age”=>$age, “height”=>$height) = $arr; echo $name, $age, $height;

// php7下正常 $fruit = array(‘a’ => ‘apple’, ‘b’ => ‘banana’, ‘c’ => ‘cranberry’); while (list(‘key’=>$k, ‘value’=>$v) = each($fruit)) { echo “$k => $v\n”; }

  1. 10. 数组常用的api
  2. 1. array_key_exists($key, $array); 检查某个key是否存在于某个数组中;
  3. 1. in_array("Runoob", $sites); 某个值是否在某个数组中;
  4. 1. array_keys(); 返回包含数组所有键名的数组,等于提取了数组所有键名组成新数组,同样array_values()返回各项值组成的数组;
  5. 1. array_change_key_case($array, 1); 将数组所有key转换为大写;
  6. 1. array_walk($arr, function($value, $key, $type), CASE_UPPER):对数组中的每个元素应用自定义函数;
  7. 11. var_export($array); :以**合法的php语法**形式返回一个php变量,第二个参数为true则不执行,反而是赋给一个变量;
  8. 11. serialize/unserialize:序列化,把数组变成字符串;
  9. 11. foreach操作一定要记住,as后面只有一个参数时,指代的时value,两个参数时时$key=<$value
  10. <a name="I49W3"></a>
  11. # 日期操作
  12. 13. _date_default_timezone_set_('PRC');设置时区;
  13. 13. strtotime('2020-04-16'); 字符串时间转timestamp,再用date('Y-m-d H-i-s', 1586988000); 可以再转回字符串时间;echo _date_("Y-m-d", _strtotime_('+1 year')); 可以用灵活的时间关键字,如next friday等等;
  14. 13. time(); 返回10timestampDate("Y/m/d"); // 2020/04/16 用来把时间格式化成人看的时间;
  15. 13. _print_r_(_date_create_('2020-04-16')); 返回一个DateTime对象
  16. ```php
  17. <?php
  18. print_r(date_create('2020-04-16'));
  19. (
  20. [date] => 2020-04-16 00:00:00.000000
  21. [timezone_type] => 3
  22. [timezone] => Europe/Berlin
  23. )

截屏2020-04-16 下午11.34.21.png
截屏2020-04-16 下午11.38.40.png

  1. 双问好:双问号取后面的值,echo min($total, max(1, $_GET['page']??1)); 若page未定义为null,则直接取1;

    正则操作

  2. preg_match(‘/\d/‘, ‘qwdq333’); // 1 代表true

  3. preg_match(‘/[abc]/‘, ‘a’); // 1 [abc]表示原子表,即字符串只要满足表中任意一个字符即可;
  4. preg_match(‘/(abc)/‘, ‘abcd’); // 1 (abc)表示原子组,即必须满足完成的括号内的条件才可,也可以和或者搭配:”/.(baidu|sina)/“
  5. 原子组可以和捕获组的概念相结合,注意在PHP中\0指的是整个正则表达式整个

截屏2020-04-17 下午7.56.11.png

  1. preg_split(‘/[@#]/‘, $str); // 根据正则来拆分某个字符串成为数组;再用implode把数组变成字符串;
  2. preg_replace($reg, $replace, $source);
  3. 选择符:|

截屏2020-04-17 下午8.09.34.png

  1. 重复匹配:对应的符号跟在每个原子的后面:* - 任意个字符 + - 至少有一个 ? - 0个或者一个
  2. 指定具体数量:通过花括号:/^\d{3}$/ - 只能有两个数字 /^\d{2,6}$/ - 限定2~6个
  3. 注意 php中单引号不做转义或解析,双引号必须给特殊字符做转义才能被正确解析;

截屏2020-04-17 下午8.21.40.png

  1. 贪婪匹配,可以通过加?来取消贪婪匹配,还可以通过修饰符来取消贪婪模式,”#

    .<\/h1>#U”,更为方便 ```php <?php $str = “

    厦门

    天气晴热

    “; $reg = “#

    .<\/h1>#”; preg_match_all($reg, $str, $subject); print_r($subject); Array ( [0] => Array
    1. (
    2. [0] => <h1>厦门</h1><h1>天气晴热</h1>
    3. )

) // 取消贪婪匹配 $str = “

厦门

天气晴热

“; $reg = “#

.*?<\/h1>#”; preg_match_all($reg, $str, $subject); print_r($subject); Array ( [0] => Array ( [0] =>

厦门

[1] =>

天气晴热

)

)

  1. <a name="3E8Lt"></a>
  2. # 文件操作
  3. 1. 磁盘资源
  4. ```php
  5. <?php
  6. function space_total(int $total): string
  7. {
  8. $config = array(3=>'GB',2=>'MB',1=>'KB');
  9. foreach ($config as $num=>$unit) {
  10. if ($total > pow(1024, $num)) {
  11. return round($total / pow(1024, $num)) . $unit;
  12. }
  13. }
  14. return $total.'B';
  15. }
  16. echo space_total(disk_total_space('.')) . "<br/>";
  17. echo space_total(disk_free_space('.'));
  1. 打开文件:fopen($filename, $mode);,打开错误则返回FALSE并附带错误信息(@符可以隐藏),下面主要说说打开的各种模式:
    1. r:只读模式,指针在文首
    2. r+:读写模式,指针在文首
    3. w:写入,完全重写也就是会清除内容
    4. w+:读写模式,也就是返回文件内容,其余与w没有区别,照样是重写内容
    5. a:写入方式打开,从文末写入,更加符合直觉的一种操作
    6. a+:读写方式打开,通过将文件指针指向文件末尾进行写入来保存文件内容
    7. 读取二进制的时候要用rb
    8. x:创建一个新的文件并以写入方式打开,如果文件已存在则返回 FALSE 和一个错误,适合于新建文件的操作
    9. x+
  2. file_exists($name):是否存在
  3. 读取文件:fread($resource, length); 全部读取需要借助filesize($filename)来作为length;读取文件一定要记住此时的指针指向哪里,就从哪里开始读!
  4. 控制文件指针:fseek($resource, int offset); 说白了就是移动光标来获取某个内容;
  5. 写入文件:fwrite($resource, $string); 要写入内容,所以fopen的模式必须是r+,表示需要写入内容,注意此时默认光标是在第一位,所以会覆盖内容,要在尾部继续写需要用fseek($resource, filesize($filename));
  6. 关闭文件:fclose(); 关闭文件后指针又会跑到文档第一位;
  7. feof($handle); 返回当前文件指针是否到达末尾,经常配合while来循环读取所有文本;
  8. fgets($handle, length); 返回一行文本,前提是没有遇到换行符等等;
  9. fgetc($handle)l 返回一个字符,只接受一个文件资源参数;
  10. fgetcsv($handle, $seperator); 更具分割符返回成数组个十年;
  11. flock($handle, LOCK_SH); 共享锁,大家都可以读,限制写,上锁的代码执行完成后可以自动解锁,或者flock($handle, LOCK_UN); 手动解锁,如果是flock($handle, LOCK_EX); 则是独占锁定,即写入,同时排斥别人访问这个文件;
  12. $stat = flock($handle, LOCK_NB, $wouldblock); 锁不成功它不会等待也就是不会阻塞,返回false,而是解开继续向下执行。常用这个进行判断条件,为true则执行fwrite,为false则弹出文件被锁提示,第三个参数表示是否被锁定
  13. 文件权限:写入权限 - is_writable($filename); 读取权限 - is_readable($filename);
  14. 各种检测:is_dir(‘../79’); is_file($filename); file_exists($filename);
  15. 快速读取与写入文件:
    1. file_get_contents(path)
    2. file_put_contents(file, data, mode[FILE_APPEND | LOCK_EX]);
  16. filemtime() 函数返回文件内容的上次修改时间; filetime()经常用来判断缓存;
  17. 文件相关常量:
    1. FILE:完整路径带文件名
    2. DIR:只包含完整目录,不包含文件名;
    3. DIRECTION_SEPERTOR:文件分隔符;define(‘DS’, DIRECTION_SEPERTOR);
  18. basename(); 路径字符串中取文件名;dirname(); 取路径名;mkdir(‘test’, 0755, true); true表示递归的创建目录,也就是多层的创建目录;rmdir(‘test’); 删除目录; rename(‘hd.txt’, ‘a/hd.txt’); 重命名和移动两个特性;copy(‘a/hd.txt’, ‘./hd.txt’); unlink($file); 删除文件
  19. scandir(‘.’); 返回一个数组,即当前目录下所有文件; print_r(glob(“.“)); 返回数组
  20. 目录操作与递归 ```php <?php // 通过递归统计每个目录的文件大小 得出目录占用空间总大小

```

  1. 关于文件的访问,创建和最后修改时间的函数

    1. fileatime()函数返回filename最后访问的时间
    2. filectime()函数返回filename最后改变的时间,指的是存放档案及目录的基本信息包含时间、档名、使用者及群组
    3. filemtime()函数返回filename最后修改的时间,指的是内容的改变时间

      面向对象

  2. 静态属性:static声明一个变量为静态变量,只能被类本身调用,无法被类new出来的实例调用,写在class中经常用来表示公用的变量;此外,php在类中提供了关键字self来指代当前class:self::$static_value;

  3. 静态方法:同上,只能用类来调用,所以内部不能用$this对象;
  4. 类常量:他的作用域在类的内部,也是必须使用类来调用类常量,方法内部使用self调用,适用场景在于类的使用过程中不会改变的数据;
  5. 继承了方法后,就可以直接用$this->调用继承的类方法。
  6. Final:子类可以重写父类的方法,可以在父类中用final关键字,防止某个方法在子类中被重写。如果父类中的方法被声明为 final,则子类无法覆盖该方法。如果一个类被声明为 final,则不能被继承。
  7. 抽象类:通过abstract把一个类定义为抽象类,然后再定义一个抽象方法:abstract public function content ();注意这个方法不用去实现,这样子类继承的时候必须在子类中实现父类中定义的抽象类,保证程序的健壮性!
  8. 接口就是规定统一实现的某个动作的方法名,接口只是定义规范但不做任何实现:public function set($name, $vaslue, #expire);规定接口后,我们在写类的时候就要去class Mysql implements Cache { … } 实现某个接口;
  9. 调用父类的方法:有时候我们想调用父类的方法,但这个方法在子类中被重写了,此时需要用parent::message();来调用;
  10. 变相实现多重继承,父类用trait取代class进行声明:trait Log { … }; trait Comment { … };,要继承的子类内部use Comment, Log;,我们要把user理解为继承!
  11. 如果子类调用了继承类和trait类中都有的同名方法,则trait类优先!
  12. 如何解决trait冲突呢?引用了同时use的两个trait类都有的同名方法,此时会报错,可以用如下的方法来解决,即用Log类的save方法取代comment类,想用comment时再给其内部的save方法取一个别名!image.png
  13. 访问控制:声明为protected的方法在外部子类是无法调用的,理解为被保护的类,只能在类的内部访问,不需要提供到外部image.png
  14. private关键字也能达到protected的效果,但区别在于继承,也就是说父类中定义了protected修饰的方法,可以在子类内部中$this->调用(注意哦,不能被new出来的子类实例调用),而private也不允许这样的操作,也就是父类方法不让子类用,就父类自己能用!
  15. trait类也可以继承trait类;
  16. 注意!静态方法既可以通过实例化的对象调用(->符号),也可以通过类直接调用(::符号);
  17. 析构函数:当函数不用的时候需要卸载的时候,统一的执行某个操作,与__construct的执行时机相反;
  18. 当调用一个不存在方法时,就会自动调用public function __call() { … }; 方法。
  19. __callStatic(); 魔术方法在你调用一个无权访问或不存在的静态方法时被自动调用;image.png