PHP中一些比较少见但有用的用法

in PHP with 0 comment

PHP中一些比较少见但有用的用法

匿名类

匿名类很有用,可以创建一次性的简单对象。 可以传递参数到匿名类的构造器,也可以扩展(extend)其他类、实现接口(implement interface),以及像其他普通的类一样使用 trait

public function notify($vin, $time, $action_type = 'add')
    {
        $body = [
            "vin" => $vin,
            "time" => $time,
            "group" => "kdj",
            "work_name" => "judge_accident_car",
            "action_type" => $action_type,
            "other_info" => []
        ];
     
        return $this->producer->publish( // 原生消息
            new class($body) implements \Serializable
            {
                protected $message;

                public function __construct(array $message = [])
                {
                    $this->message = $message;
                }

                public function serialize()
                {
                    return json_encode($this->message, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
                }

                public function unserialize($serialized)
                {
                    $this->message = json_decode($serialized, true);
                }
            }, 'example');
    }

Closure

用于代表 匿名函数的类.

有一些特殊需求可以使用Closure来实现,比如说修改某对象私有属性。对于一些第三方库有时候可以这么处理。

class A
{
    private $b = 1;
}

$a = new A();

$f = Closure::bind(function ($ins) {
    $ins->b = 22;
}, null, A::class);

$f($a);
var_dump($a);
/**
 * object(A)#1 (1) {
 * ["b":"A":private]=>
 * int(22)
 * }
 */
// composer autoload_static.php
public static function getInitializer(ClassLoader $loader)
    {
        return \Closure::bind(function () use ($loader) {
            $loader->prefixLengthsPsr4 = ComposerStaticInit70d454e12f0a82ac5e15c4820e279492::$prefixLengthsPsr4;
            $loader->prefixDirsPsr4 = ComposerStaticInit70d454e12f0a82ac5e15c4820e279492::$prefixDirsPsr4;
            $loader->prefixesPsr0 = ComposerStaticInit70d454e12f0a82ac5e15c4820e279492::$prefixesPsr0;
            $loader->classMap = ComposerStaticInit70d454e12f0a82ac5e15c4820e279492::$classMap;

        }, null, ClassLoader::class);
    }

ob系列函数

ob_start,ob_get_clean ,ob_end_clean
输出缓冲控制。有些时候我们对程序的输出,做一些处理的时候,ob系列函数就派上了用场。

1.动态网页转静态。直接第一次执行的收集好输出,存储成html

2.调试的时候前面有很多输出干扰了你想要看的输出,就可以在想要看到的输出前面来个ob_end_clean ,把前面的输出全部干掉。

clone

对象复制可以通过 clone 关键字来完成(如果可能,这将调用对象的 __clone() 方法);执行的是浅复制

 // /vendor/laravel/octane/src/Worker.php handle方法   /laravel-s / laravel-swoole
 // We will clone the application instance so that we have a clean copy to switch
 // back to once the request has been handled. This allows us to easily delete
 // certain instances that got resolved / mutated during a previous request.
 CurrentApplication::set($sandbox = clone $this->app);

array_reduce

用回调函数迭代地将数组简化为单一的值

实现管道/中间件-KDJ的定价流程等

// /vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php
public function then(Closure $destination)
    {
        $pipeline = array_reduce(
            array_reverse($this->pipes), $this->carry(), $this->prepareDestination($destination)
        );

        return $pipeline($this->passable);
    }

do while 替代if elseif

模板语法

<?php foreach($items as $item): ?>
<div><?= $item['name']?></div>
<?php endforeach; ?>

<?php if(true): ?>
<div>1111</div>
<?php else: ?>
<div>222</div>
<?php ?>

laravel tap函数

if (! function_exists('tap')) {
    /**
     * Call the given Closure with the given value then return the value.
     *
     * @param  mixed  $value
     * @param  callable|null  $callback
     * @return mixed
     */
    function tap($value, $callback = null)
    {
        if (is_null($callback)) {
            return new HigherOrderTapProxy($value);
        }

        $callback($value);

        return $value;
    }
}

结构好看/节省临时变量

public function pull($key, $default = null)
{
   $value = $this->get($key, $default);

   $this->forget($key) // returns a boolean;

   return $value;
}

public function pull($key, $default = null)
{
   return tap($this->get($key, $default), function ($value) use ($key) {
      $this->forget($key);
   });
}

转成链式调用

tap($user)->

macro

宏指令,用来动态扩展我们的基础类/核心类

/vendor/laravel/framework/src/Illuminate/Macroable/Traits/Macroable.php
  /**
     * Dynamically handle calls to the class.
     *
     * @param  string  $method
     * @param  array  $parameters
     * @return mixed
     *
     * @throws \BadMethodCallException
     */
    public function __call($method, $parameters)
    {
        if (! static::hasMacro($method)) {
            throw new BadMethodCallException(sprintf(
                'Method %s::%s does not exist.', static::class, $method
            ));
        }

        $macro = static::$macros[$method];

        if ($macro instanceof Closure) {
            $macro = $macro->bindTo($this, static::class);
        }

        return $macro(...$parameters);
    }

https://github.com/chastephp/laravel-wheres/
支持medoo语法

         /**
         * wheres
         * @param  $where array
         * @param  $method string where orWhere
         * @return static|\Illuminate\Database\Eloquent\Builder|\Illuminate\Database\Query\Builder
         */
        Builder::macro('wheres', function (array $where, $method = 'where') {
            // ...
            return $this;
        });
        
        // 用法
        User::query()->wheres([
            "email" => "foo@bar.com"
        ])->toSql();
        // select * from `users` where `email` = ?
        
        
        User::query()->wheres([
            "user_id[>=]" => 200
        ])->toSql();
        // select * from `users` where `user_id` >= ?
        
        
        User::query()->wheres([
            "user_id[!]" => 200,
        ])->toSql();
        // select * from `users` where `user_id` != ?
        
        
        User::query()->wheres([
            "age[<>]" => [20, 50]
        ])->toSql();
        // select * from `users` where `age` between ? and ?

token_get_all

将提供的源码按 PHP 标记进行分割

可以实现对PHP原代码的混淆(https://github.com/djunny/enphp)

https://3v4l.org/k5Hmu

Comments are closed.