PHP - 良好/高效coding实践 - 收集

1.应用场景/目的

主要用于简洁高效或者避免出现人为编写错误, 用法之前不知, 感觉很特别,同时可帮助理解PHP底层实现.

2.学习/操作

1.数组

1.array_values($arr);  获得数组的值    

//如果已经是索引数组,则无效果/,不过确实能保证一定为索引数组

备注: 如果原来的数组被unset()之后, 再添加元素, 则索引key会从曾经最大的数字索引+1;

<?php
$array = [1,2,3];
unset($array[count($array)-1]);
$array[] = 1;
var_export($array); //也算是一个小技巧用法.

out:

array (

        0 => 1,

        1 => 2,

        3 => 1,

)

重新索引

$array = array_values($array);

out:

array (

        0 => 1,

        1 => 2,

        2 => 1,

)

2.list($key,$value)=each($arr);

// 获得数组当前元素的键名和值[之前以为是框架的函数封装, 是php自带函数]

3.数组和变量之间的转换
extract($arr); // 从数组中将变量导入到当前的符号表,键名当作变量名,值作为变量值

注: 第二个参数很重要,可以看手册使用

<?php
/* 假定 $var_array 是 wddx_deserialize 返回的数组*/
$size = "large";
$var_array = array("color" => "blue",
                   "size"  => "medium",
                   "shape" => "sphere");
extract($var_array, EXTR_PREFIX_SAME, "wddx");  //如果有冲突,在变量名前加上前缀 prefix
echo "$color, $size, $shape, $wddx_size\n";
?>
以上例程会输出:
blue, large, sphere, medium

compact(var1,var2,var3); 用给定的变量名创建一个数组
echo implode([a,b,c]); //输入'abc';  //将数组拼接成为字符串  //20191118

4.数组的填充
array_pad($arr,5,'x');  //'将一个数组填补到制定长度 , laravel框架里见到

5.数组与栈
array_push($arr,"apple","pear");  //将一个或多个元素压入数组栈的末尾(入栈),返回入栈元素的个数
array_pop($arr);  //将数组栈的最后一个元素弹出(出栈)

6.数组与列队
array_shift($arr); //数组中的第一个元素移出并作为结果返回, 数组长度减1,其他元素向前移动一位,数字键名改为从零技术,文字键名不变.
array_unshift($arr,"a",array(1,2)); //在数组的开头插入一个或多个元素.

备注: 关于5和6 第一次,意识到PHP中数组并不是数据结构中的数组,而且对数据结构的再一次封装,猜测集成了'数组', '栈', '队列'等数据结构的功能/基本操作  TBD

7.array_map("function",$arr1,$arr2); 

//可以处理多个数组(当使用两个或更多数组时,他们的长度应该相同) //个人觉得这是判断php开发者技术高低的一个标准
<?php
$arr = [0,1,2];
$newData = [];
array_map(function($v) use(&$newData) {
    if(empty($v)) return;   //这里的return 相当于foreach 中的 continue
    $newData[] = $v;
},$arr);
print_r($newData);

输出:

Array
(
    [0] => 1
    [1] => 2
)

8.array_get()  //框架中常使用,原因未知
array_get方法使用”.“号从嵌套数组中获取值:

<?php
$array = ['products' => ['desk' => ['price' => 100]]];
$value = array_get($array, 'products.desk');

//等同于 $value = ['products' ]['desk'], 但是给人的格调不一样,膨胀了//有炫技痕迹

//array_get函数还接收一个默认值,如果指定键不存在的话则返回该默认值:
$value = array_get($array, 'names.john', 'default');


不适用场合:数组key中含有.的内容。

9.array_filter($arr,"function");  

//使用回调函数过滤数组中的每个元素,如果回调函数为TRUE,数组的当前元素会被包含在返回的结果数组中,数组的键名保留不变

<?php
$rows = array_filter($rows['log_list'], function($v) use($ids) {

   return in_array($v['id'], $ids);

});


array_filter:  利用回调函数来对数组进行过滤,一直都以为用回调函数才能处理,却没有发现手册下面还有一句,如果没有回调函数,那么默认就是删除数组中值为false的项目  //看手册要看清楚

10.array_reduce($arr,"function","*");  

//用回调函数迭代地将数组简化为单一的值, 即将数组转换为一个值.可能是整形, 字符串类型, 或者boolean

<?php
function sum($carry, $item)
{
    $carry += $item;
    return $carry;
}

function product($carry, $item)
{
    $carry *= $item;
    return $carry;
}

$a = array(1, 2, 3, 4, 5);
$x = array();

var_dump(array_reduce($a, "sum")); // int(15)
var_dump(array_reduce($a, "product", 10)); // int(1200), because: 10*1*2*3*4*5
var_dump(array_reduce($x, "sum", "No data to reduce")); // string(17) "No data to reduce"

更多: PHP - 数组函数 - 收集_穿素白衫的少年的博客-CSDN博客

11. count(); //PHP手册还是多读, 才行.

count ( mixed $array_or_countable [, int $mode = COUNT_NORMAL ] ) : int

count — 计算数组中的单元数目,或对象中的属性个数

手册: PHP: count - Manual

备注:

1.统计数组或者 Countable 对象。 

The Countable interfacea

(PHP 5 >= 5.1.0, PHP 7)
类实现 Countable 可被用于 count() 函数.

Countable {

/* 方法 */

abstract public count ( void ) : int

}

//Countable::count — 统计一个对象的元素个数

<?php
//Example One, BAD :(

class CountMe
{

    protected $_myCount = 3;

    public function count()
    {
        return $this->_myCount;
    }

}

$countable = new CountMe();
echo count($countable); //result is "1", not as expected

//Example Two, GOOD :)

class CountMe implements Countable
{

    protected $_myCount = 3;

    public function count()
    {
        return $this->_myCount;
    }
}

$countable = new CountMe();
echo count($countable); //result is "3" as expected
?>

具体参见: PHP: Countable - Manual

2.返回值
返回 array_or_countable 中的单元数目。 如果参数既不是数组,也不是实现 Countable 接口的对象, [如: int, string , boolean] 将返回 1。

有个例外:如果 array_or_countable 是 NULL 则结果是 0。 

3. mode
如果可选的 mode 参数设为 COUNT_RECURSIVE(或 1),count() 将递归地对数组计数。

对计算多维数组的所有单元尤其有用。//具体应用场景TBD

4.count() 能检测递归来避免无限循环,但每次出现时会产生 E_WARNING 错误

(如果 array 不止一次包含了自身)并返回大于预期的统计数字。

2.函数/方法调用

 1.函数参数传引用   20191119

//这种方式,可以达到,函数/方法有时可不用返回值,或者return 一个值,但是实际上是多个值, 最重要一点: 传值和传引用的区别, [深拷贝与浅拷贝], 当参数数据比较大时, 可以节省资源[时间与空间].

<?php

date_default_timezone_set('Asia/Shanghai');

error_reporting(E_ALL);


//传引用方式一  常用
function c($c){
    d($c);
    return $c;
}

function d(&$d){
    $d++;
}

echo c(1);//期望值:2


//传引用方式二  刚学习到  从数据结构书中看到c语言写法,想到PHP, 毕竟PHP是用c语言编写的.
echo PHP_EOL
function a($a, $b){
    echo $b.'1';//b1
    return b($b);//return之后的代码是不会执行的, 即echo不会执行[显示不出来], 但是$b已经有值
    echo $b.'2';//b2
}

function b(&$b){
    return true;
}

$result = a('a','b');
echo PHP_EOL.$result;//1

2.类型约束   20191122

<?php

function bubble_sort(Array $array = []){ //前面一个Array是类型约束, 保证只能传递数组参数, 后一个是默认值 这下知道区别和用途
    var_dump($array);
    echo $count = count($array); //如果参数是字符串, 会输出 1; 
}

//bubble_sort('test');//会致命错误Fatal error [Uncaught TypeError]
bubble_sort();//会报错

3.PHP 中的函数/方法 变长参数

PHP 函数也支持变长参数,在 PHP 5.5 及更早版本中,可以在定义函数时设置参数为空,然后在函数体中通过 func_num_args()func_get_arg() 以及 func_get_args() 之类的函数获取参数数量及参数值:

function sum()
{
    $sum = 0;
    $numbers = func_get_args();
    foreach ($numbers as $number) {
        $sum += $number;
    }
    printf("The num of the arguments are %d\n", func_num_args());
    printf("The sum of the numbers are %d\n", $sum);
}

sum(1, 2, 3, 4, 5);

从 PHP 5.6 开始,变长参数的定义和其他语言的风格保持一致: //其实也可以使用传递参数为数组来处理

function sum(...$numbers)   // 官方文档的例子, PHP: 函数的参数 - Manual
{
    $sum = 0;
    foreach ($numbers as $number) {
        $sum += $number;
    }
    printf("The num of the arguments are %d\n", func_num_args());
    printf("The sum of these numbers are %d\n", $sum);
}

sum(1, 2, 3, 4, 5);

跟Go语言相同~~ 参考对比使用

4. isset() // 20210529 周六 家里

可以同时判断多个变量是否有定义

<?php
$test = 123;
// $tst = 123;
if(isset($test, $tst)){
    echo 123;
}

echo 234;

仅仅输出:

234

3.字符串

 1.realpath  20191126

realpath() 扩展所有的符号连接并且处理输入的 path 中的 '/./', '/../' 以及多余的 '/' 并返回规范化后的绝对路径名。返回的路径中没有符号连接,'/./' 或 '/../' 成分。

PHP: realpath - Manual

2.sprintf用法

<?php
$id = 12;
$sub = $id % 100;
var_dump(sprintf('%s_%02d', 'testDao', $sub));

输出:

string(10) "testDao_12"

3. 字符串原样输出,特别是用于SQL语句 // 20210715 周四 公司

<?php

$sql = <<<SQL
    SELECT ALL
        c1, -- For result indexing
        c1, c2
    FROM (
        VALUES
            ROW('ID-1', 'Value 1'),
            ROW('ID-2', 'Value 2a'),
            ROW('ID-2', 'Value 2b'),
            ROW('ID-3', 'Value 3')
    ) AS t (c1, c2);
   
SQL;

$result = $pdo->query($sql);
print_r($result->fetchAll(PDO::FETCH_UNIQUE));

/*
Gives :
ID-1 => [c1 => ID-1,  c2 => Value 1]
ID-2 => [c1 => ID-2b, c2 => Value 2b]
ID-3 => [c1 => ID-3,  c2 => Value 3]
*/

?>

4.对象

1.定义私有/受保护的属性, 使用_开头  / /虽然PSR只推荐私有属性使用,个人还是推荐受保护属性也可使用.

更多参考: Yii 2 编码规范/风格[亦是PSR]_穿素白衫的少年的博客-CSDN博客

2.对象转换为字符串  20191227 

$feed = new Feed();
$feed = (string)$feed;

为什么有项目中能这么写? TBD

在线执行环境测试, 出现报错.错误信息如下:

Catchable fatal error: Object of class Test could not be converted to string in /usercode/file.php on line 13
 

3.构造函数使用protected修饰时, 则不能使用new实例化.

5.整型

TBD

6.布尔型

TBD

7.变量

1.变量/类属性伪注解 

方式一 [laravel中的写法]

详情: 服务容器 | 核心架构 | Laravel 5.8 中文文档

/**
     * The user repository implementation.
     *
     * @var UserRepository
     */
    protected $users;

类方法参数

 /**
     * 用户仓库实例
     */
    protected $users;

    /**
     * 创建一个控制器实例
     *
     * @param  UserRepository  $users
     * @return void
     */
    public function __construct(UserRepository $users)
    {
        $this->users = $users;
    }

方法二 [其他]

/* @var $apiService MapiService */请注意:@var前是需要空格隔开的。

$apiService = Factory::create ( 'MapiService' );

$orderInfo = $apiService->getOrderInfo($orderSn);

2. 条件语句中的变量赋值

if($name = false !== is_bool(false) ){ //最后就是一个赋值操作 [先判断, 后赋值]
    var_dump($name);
}

输出:

备注:有时候并不会这么写,了解一下

3.return中赋值

class Test
{
    public $data;
    
    public function index($name = 'test')
    {
        return $this->data['env'] = $name; //返回的是字符串 string(9) "test name"
    }
}

$test = new Test;
$testArr = $test->index('test name');
var_dump($testArr); //string(9) "test name"

输出:

8.函数/方法

1.php闭包函数(Closure)  //多实践

PHP 闭包函数(Closure)_穿素白衫的少年的博客-CSDN博客

2. 闭包简单用法

<?php

class ReturnClass
{
    //如何没有构造函数,则使用跟类名相同的方法,会被认为是构造函数[构造函数不能为静态方法
    //[这里不区分大小写, 因为是Windows系统缘故]的方法] 可以是受保护的.
    public function __construct()
    {
        echo '__construct';
    }
    
    static public function returnClass()
    {
        // exit('stop');
        //返回的是闭包,可以继续调用
        return function($table){
            // $table->tinyInteger('advertisement_status_code'); //使用这种方式,编写微服务 返回数据表字段
            return [$table];
        };
    }
}

// $obj = new ReturnClass();
$obj = ReturnClass::returnClass();
var_dump($obj);
var_dump($obj('123')); //可以继续调用
exit;
// var_export($obj);

输出:

object(Closure)#1 (1) { ["parameter"]=> array(1) { ["$table"]=> string(10) "" } } array(1) { [0]=> string(3) "123" }

9.类

1.trait的用法

TBD

10. 进程

1. pcntl_fork 

在当前进程当前位置产生分支(子进程)

详细查看: PHP: pcntl_fork - Manual  

11. TBD

TBD

12. 正则

PHP - 正则表达式 - 学习_穿素白衫的少年的博客-CSDN博客

PHP: PCRE - Manual  // php PCRE库提供的正则, 也是PHP 5.3以后推荐使用

备注: 

php 正则有两套正则函数, preg 与 ereg.

前者是由PCRE库提供的函数, 以'preg_'为前缀命名.

PCRE(Perl Compatible Regular Expression, 兼容Perl的正则表达式) 由Philip Hazel 于1997年开发.

现在的编程语言和软件中一般都使用PCRE库.

后者由POSIX 扩展提供的函数, 以'ereg_'为前缀命名. 

POSIX(Portable System Interface of Unix, Unix 可移植操作系统的接口)

1. preg_replace

(PHP 4, PHP 5, PHP 7)

preg_replace — 执行一个正则表达式的搜索和替换

PHP: preg_replace - Manual

2. preg_replace_callback  //高级用法

(PHP 4 >= 4.0.5, PHP 5, PHP 7)

preg_replace_callback — 执行一个正则表达式搜索并且使用一个回调进行替换

...

13. 控制台[如: laravel 4.2]

app\commands\PurgeLogs.php  //借鉴

<?php

use Illuminate\Console\Command;

use Symfony\Component\Console\Input\InputOption;

use Symfony\Component\Console\Input\InputArgument;

class PurgeLogs extends Command {

    /**

     * The console command name.

     *

     * @var string

     */

    protected $name = 'logs:purge';

    /**

     * The console command description.

     *

     * @var string

     */

    protected $description = 'Purge Logs in storage folder.';

    /**

     * Create a new command instance.

     *

     * @return void

     */

    public function __construct()

    {

        parent::__construct();

    }

    /**

     * Execute the console command.

     *

     * @return mixed

     */

    public function fire()

    {

        $older_than = str_replace('older-than=', '', $this->argument('older-than'));

        $time_limit = strtotime($older_than);

        $files = glob(storage_path()."/logs/*");

        

        echo "Purging logs.";

        ob_flush();

        

        foreach ($files as $file) {

            if (is_file($file)) {

                

                if ($time_limit >= filemtime($file)) {

                    unlink($file);

                }

            }

            echo ".";

            ob_flush();

        }

        

        echo " Done.\n";

    }

    /**

     * Get the console command arguments.

     *

     * @return array

     */

    protected function getArguments()

    {

        return array(

            array('older-than', InputArgument::REQUIRED, 'purge log files older than'),

        );

    }

}

14. 流程控制语句

 1. if语句判断相等 ( == )时,习惯把常量写前面   //简单讲, 降低人为编码出错的概率[无执行性能上的差异]

这样写会与赋值语句的书写形式区分开,降低出错的可能性;

然后如果我们实在脑子短路写成if(1=$x)的话,程序会报错(赋值语句等号前面必须为变量,语法错误)

2. switch语句, 完全可以替换if else语句 //case 分支不止可以进行值判等, 也是可以使用表达式的   我刚刚知道, 手册确实没有认真过一遍

<?php

$score = 100;
switch($score) {
    case $score >= 90:
        echo ("Grade: A");
        break;
    case $score >= 80 && $score < 90:
        echo ("Grade: B");
        break;
    case $score >= 70 && $score < 80:
        echo ("Grade: C");
        break;
    case $score >= 60 && $score < 70:
        echo ("Grade: D");
        break;
    default:
        echo ("Grade: F");
        break;
}

输出:

Golang也是  //最近在学Go

15.常量

defined('APP_BASE_PATH') or define('APP_BASE_PATH', realpath('./'));

defined('CORE') or define('CORE', APP_BASE_PATH . '/core');

defined('APP') or define('APP', APP_BASE_PATH . '/app');

defined('PUBLIC_PATH') or define('PUBLIC_PATH', APP_BASE_PATH . '/public');  //是否合适TBD

defined('MODULE') or define('MODULE', 'app');

后续补充

...

3.问题/补充

TBD

4.参考

PHP: sprintf - Manual  //sprintf 用法

PHP: pcntl_fork - Manual  //创建子进程

https://www.php.net/manual/zh/ref.regex.php  //正则表达函数

https://blog.csdn.net/wccczxm/article/details/89379134  //为什么if语句判断相等(==)时,习惯把常量写前面

后续补充

...

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值