# php-helper
提供常规基类、方法、函数集合

## ====== 常规基类 ======
### 1.单例模式
一个类无论如何只能被实例化一次
#### 定义
```
class SingleTonDemo extends SingleTon
{
    public function test()
    {
        var_dump(__CLASS__ . " - " . __FUNCTION__);
    }
}
```
#### 实例化
```
SingleTonDemo::getInstance()->test();
```
### 2.工厂模式
每个类只要调用获取实例，就会 new 一个新的实例。
#### 定义
```
class FactoryDemo extends Factory
{
    public function test()
    {
        var_dump(__CLASS__ . " - " . __FUNCTION__);
    }
}
```
#### 实例化
```
FactoryDemo::getInstance()->test();
```

### 3.基类
类文件的基类，基本所有的类都是这个类的子类
#### 定义
```php
class Demo extends Base
{
    public $age;
    private $_name;
    private $_sex;

    /**
     * @return string
     */
    public function getName()
    {
        return $this->_name;
    }

    /**
     * @param string $name
     */
    public function setName($name)
    {
        $this->_name = $name;
    }

    /**
     * @return mixed
     */
    public function getSex()
    {
        return $this->_sex;
    }

    /**
     * @param mixed $sex
     */
    public function setSex($sex)
    {
        $this->_sex = $sex;
    }
}
```
#### 使用示例
```php
        // Base类实例化
        $demo = new Demo();
        var_dump($demo);
        // 获取配置类
        $demo->configure([
            'name' => 'Qingbing',
            'age' => 18,
        ]);
        var_dump($demo);
        // 调用 setSex()
        $demo->sex = "男";
        // 调用getSex();
        var_dump($demo->sex);
        var_dump($demo);
        // 判断是否为可读属性
        var_dump($demo->canGetProperty("name"));
        // 判断是否为可写属性
        var_dump($demo->canSetProperty("name"));
        // 判断是否为拥有属性（读或写）
        var_dump($demo->hasProperty("xxx"));
```

## ====== 常用方法 ======
### 1. 功能集合
```php
        // 获取实例的反射类
        $reflection = Unit::getReflectionClass($this);
        var_dump($reflection);
        // 数组合并
        $result = Unit::mergeArray(
            [
                'a' => 'a',
                'b' => [1, 2, 'b' => 'bb']
            ], [
            'b' => ['ccc', 'b' => 'bc'],
            3], [3, 4]);
        var_dump($result);
        // 创建实例
        $instance = Unit::createObject([
            'class' => '\Test\ObjectDemo',
            'username' => 'demo',
        ]);
        var_dump($instance);
        // 判断是否是一个合法的日期构成
        $isDate = Unit::isValidDate(2018, 12, 30);
        var_dump($isDate);
        // 判断是否是一个合法的时间构成
        $isTime = Unit::isValidTime(23, 59, 59);
        var_dump($isTime);
        $timestamp = Unit::getTimestamp(23, 59, 59);
        var_dump($timestamp);
        // 判断是否是一个合法的时间构成
        $isTime = Unit::isValidTime(23, 59, 59);
        var_dump($isTime);
        // 判断是否是一个合法的时间构成
        $time = Unit::getFullYear(23);
        var_dump($time);

        // 内存单位转换显示
        var_dump(Unit::switchMemoryCapacity('1025b'));
        var_dump(Unit::switchMemoryCapacity('1075mb', 'gb'));
        var_dump(Unit::switchMemoryCapacity('1025', 'mb', 'kb'));
```

### 2. 编码 \Helper\Coding
```php

        $sourceString = "This is a coding-test.";
        $sourceArray = [
            "homepage" => "http://www.phpcorner.net",
            "authors" => [
                "name" => "qingbing",
                "email" => "780042175@qq.com",
                "description" => "中文描述"
            ],
        ];
        var_dump($sourceString);
        var_dump($sourceArray);
        // base64 编码
        var_dump("=== base64 : 只能针对字符串 ===");
        $codingString = \Helper\Coding::base64_encode($sourceString);
        $decodingString = \Helper\Coding::base64_decode($codingString);
        var_dump($codingString);
        var_dump($decodingString);

        // secure
        var_dump("=== secure ：可以是任意变量，其实也是base64 ===");
        $codingString = \Helper\Coding::secure_encode($sourceArray);
        $decodingString = \Helper\Coding::secure_decode($codingString);
        var_dump($codingString);
        var_dump($decodingString);

        // json
        var_dump("=== json : 系统函数 ===");
        $codingString = \Helper\Coding::json_encode($sourceArray);
        $decodingString = \Helper\Coding::json_decode($codingString);
        var_dump($codingString);
        var_dump($decodingString);

        var_dump("=== json : 自定义函数 ===");
        $codingString = \Helper\Coding::json_encode($sourceArray, true);
        $decodingString = \Helper\Coding::json_decode($codingString);
        var_dump($codingString);
        var_dump($decodingString);
```

### 3. 格式化 \Helper\Format
```php
        // 数组取值
        var_dump(Format::dataValue('name', ['name' => 'qingbing', 'sex' => 'nan']));
        // 日期格式化
        var_dump(\Helper\Format::date());
        // 时间格式化
        var_dump(\Helper\Format::datetime());
```

### 4. 文件操作管理
```php
        // 如果文件存在，删除文件
        $status = \Helper\File::getInstance()
            ->setFilePath("./runtime/delete.txt")
            ->unlink();
        var_dump($status);
        // 获取文件属性，文件不一定存在
        $pathinfo = \Helper\File::getInstance()
            ->setFilePath("./runtime/dd.txt")
            ->pathinfo();
        var_dump($pathinfo);
        // 获取文件内容
        $content = \Helper\File::getInstance()
            ->setFilePath("runtime/get.txt")
            ->get();
        var_dump($content);
        // 清空文件并追加
        $status = \Helper\File::getInstance()
            ->setFilePath("runtime/append.txt")
            ->setEmpty()
            ->append("Hello, my dear phper 1.")
            ->append("Hello, my dear phper 2.", true)
            ->flush();
        var_dump($status);
```

### 5. ObBuffer 缓冲操作
```php
        ObBuffer::start();
        var_dump(111);
        $output = ObBuffer::end();
        
        // 页面输出
        var_dump(222);
        // 将缓冲内容输出
        echo $output;
```

### 6. List 列表操作
```php
        // 实例化列表
        $list = new CList();
        // 添加列表
        $list->push(['id' => '1', 'name' => 'aa']);
        $list->push(['id' => '2', 'name' => 'bb']);
        $list->push(['id' => '3', 'name' => 'cc']);
        $list->push(['id' => '4', 'name' => 'dd']);
        $list->push(['id' => '5', 'name' => 'ee']);
        $list->unshift(['id' => '6', 'name' => 'ee']);
        // 遍历列表
        foreach ($list as $k => $v) {
            var_dump($v);
        }
        // 统计列表包含元素个数
        var_dump(count($list));
        var_dump($list);
        // 移除最后的元素
        var_dump($list->shift());
        var_dump($list);

        // 移除最后的元素
        var_dump($list->pop());
        var_dump($list);
```

### 7. map 操作
```php
        // 数组创建 map
        $map1 = new CMap([
            'name' => 'xx',
            'sex' => 'male',
        ]);
        $map2 = new CMap([
            'name' => 'php',
            'age' => '10',
        ]);
        // map 创建 map
        $map = new CMap($map1);
        // 合并 map
        $map->mergeWith($map2);
        // 添加
        $map->add('height', 80);
        $map->add('function', function () {
            var_dump('function-method');
        });
        // 直接调用
        call_user_func($map->get('function'));

        // 删除
        $map->remove('function');
        var_dump($map->count);

        // 迭代遍历
        foreach ($map as $key => $value) {
            if (is_callable($value)) {
                var_dump("==={$key}===");
                call_user_func($value);
            } else {
                var_dump("==={$key} : {$value}===");
            }
        }
        var_dump($map);
```

### 8. event 的使用
#### 8.1 event 类的编写
```php
class DemoBase extends Base
{
    /**
     * @throws \Helper\Exception
     */
    public function login()
    {
        if ($this->hasEventHandler('beforeLogin')) {
            $this->onBeforeLogin(new Event($this));
        }
        var_dump('login');
        if ($this->hasEventHandler('afterLogin')) {
            $this->onAfterLogin(new Event($this, ['name' => 'qingbing']));
        }
    }

    /**
     * 调用及触发 beforeLogin 事件
     * @param Event $event
     * @throws \Helper\Exception
     */
    public function onBeforeLogin($event)
    {
        $this->raiseEvent('beforeLogin', $event);
    }

    /**
     * 调用及触发 afterLogin 事件
     * @param Event $event
     * @throws \Helper\Exception
     */
    public function onAfterLogin($event)
    {
        $this->raiseEvent('afterLogin', $event);
    }
}
```
#### 8.2 event 类的使用
```php
        // Base类实例化
        $demo = new DemoBase();
        // 判断事件名称是否存在
        var_dump($demo->hasEvent('end'));
        var_dump($demo->hasEvent('login'));

        // 添加事件句柄
        $demo->attachEventHandler('beforeLogin', function ($event) {
            var_dump('before login');
        });
        $demo->attachEventHandler('afterLogin', function ($event) {
            var_dump('after login1');
        });
        $handler = function ($event) { // 定义事件句柄
            var_dump('after login2');
            var_dump($event);
        };
        $demo->attachEventHandler('afterLogin', $handler);
        // 移除事件句柄
        $demo->detachEventHandler('afterLogin', $handler);

        // 调用函数，触发事件句柄
        $demo->login();
```
#### 9. FileManager 的使用
```php
        // 通过文件名获取文件的 mime-type （常用）
        $mimeType = FileManager::getMimeType('bootstrap.php');
        var_dump($mimeType);

        // 通过文件的后缀获取文件的 mime-type
        $mimeType = FileManager::getMimeTypeByExtension('gg.png');
        var_dump($mimeType);

        // 创建文件（递归）
        $status = FileManager::mkdir('upload/good/xx/dd', null, true);
        var_dump($status);

        // 删除文件(递归)
        $status = FileManager::rmdir('upload/good', true);
        var_dump($status);

        // 获取文件后缀
        $ext = FileManager::getExtension('xxx.php');
        var_dump($ext);

        // 拷贝文件目录
        $rootPath = dirname(dirname(__DIR__));
        $status = FileManager::copyDir($rootPath . "/test", $rootPath . "/vendor/dddd");
        var_dump($status);

        // 拷贝文件
        $status = FileManager::copyFile($rootPath . "/test/bootstrap.php", $rootPath . "/vendor/xxxx.php");
        var_dump($status);

        // 查找文件目录中的文件
        $list = FileManager::findFiles($rootPath . "/test", [
            'absolutePaths' => false,
        ]);
        var_dump($list);
```

#### 10. AsciiConvert (进制数之间的转换)的使用
```php
$str = "php工作角";
var_dump("string : " . $str);
$ascii = AsciiConvert::str2Binary($str);
var_dump("str2Binary ： " . $ascii);

$str = AsciiConvert::binary2Str($ascii);
var_dump("binary2Str ： " . $str);

$hex = AsciiConvert::str2Hex($str);
var_dump("str2Hex ： " . $hex);

$ascii = AsciiConvert::hex2Str($hex);
var_dump("hex2Str ： " . $ascii);

var_dump("-----------------------------------------");

$str = "http://phpcroner.net";
var_dump("string : " . $str);
$ascii = AsciiConvert::str2Binary($str);
var_dump("str2Binary ： " . $ascii);

$str = AsciiConvert::binary2Str($ascii);
var_dump("binary2Str ： " . $str);

$hex = AsciiConvert::str2Hex($str);
var_dump("str2Hex ： " . $hex);

$ascii = AsciiConvert::hex2Str($hex);
var_dump("hex2Str ： " . $ascii);

```

#### 11. Crypt (可逆双钥加密算法)的使用
```php

$crypt = Crypt::getInstance();
$crypt->setPrivateKey('private_key_001');
$str = $crypt->encode('11', 'public_key_001');
var_dump($str);
$str = $crypt->decode($str, 'public_key_001');
var_dump($str);

$crypt->setPrivateKey('private_key_002');
$str = $crypt->encode('测试中文加密', 'public_key_002');
var_dump($str);
$str = $crypt->decode($str, 'public_key_002');
var_dump($str);
```

## ====== 函数集合 ======
### 1. array_cover() 
覆盖模式的数组，最后一个数组可以为bool,而且为false时，表示不追加
```php
        // 数组覆盖
        $a = [
            "name" => "qingbing",
            "qq" => "10000",
            "mail" => "10000@qq.com",
        ];
        $ab = [
            "xx" => "xx",
            "name" => "xx",
        ];
        $cc = array_cover($a, $ab);
        var_dump($cc);
        $cc = array_cover($a, $ab, false);
        var_dump($cc);
```
### 2. str_eval($coding, $return = true)
执行字符串类型的代码并返回
```php
        $result = str_eval("5+3*6");
        var_dump($result);
        $result = str_eval('new \Helper\Coding()');
        var_dump($result);
```
### 3. str_cover($message, $params = []) 
字符串关键字替换
```php
        $str = "Hello, {yourName}. I am {myName}";
        var_dump($str);
        $RStr = str_cover($str, [
            "{yourName}" => 'Balala',
            "{myName}" => 'Qingbing',
        ]);
        var_dump($RStr);
```
### 4. str_explode($str, $delimiter = ',') 
字符串分割,自带空格去除功能
```php
        $a = str_explode(' username , password , sex');
        var_dump($a);
        $a = str_explode(' username| password | sex', '|');
        var_dump($a);
        $a = str_explode(' username| password | sex');
        var_dump($a);
```

### 5. str_explode_by_upper($str, $delimiter = [])
根据大写字母和指定列表进行字符串分割，并全部转换成小写
```php
        $a = str_explode_by_upper('goodProductInfo', ['nf']);
        var_dump($a);
        $a = str_explode_by_upper('goodProductInfo', ['u', 'c']);
        var_dump($a);
```

### 6. array_sort($array = array(), $recursive = false)
数组排序（根据键递归升序）
```php

// 数组排序
$arr = ['b' => 'b', 'a' => 'a', 'c' => 'c'];
$arr2 = array_sort($arr);
var_dump($arr2);
// 数组递归排序
$arr = ['b' => 'b', 'a' => [
    'dd' => 'dd',
    'cc' => 'cc',
    'ee' => 'ee',
], 'c' => 'c'];
$arr2 = array_sort($arr, true);
var_dump($arr2);
```




## ====== 异常代码集合 ======

异常代码格式：1001 - XXX - XX （组件编号 - 文件编号 - 代码内异常）
```  
 - 100100101 : 覆盖源必须为数组
 - 100100102 : 覆盖数组参数必须为数组
  
 - 100100201 : 尝试读取write-only属性
 - 100100202 : 尝试读取不存在的属性
 - 100100203 : 尝试写入read-only属性
 - 100100204 : 尝试写入不存在的属性
 - 100100205 : 尝试删除read-only属性
 - 100100206 : 事件"{class}.{event}"未定义
 - 100100207 : 事件"{class}.{event}"包含了无效的事件句柄"{handler}"
 
 - 100100301 : 清空文件失败
 - 100100302 : 文件写入失败+
 
 - 100100401 : 创建类实例配置中必须包含"class"元素
 
 - 100100501 : 实例化列表参数必须是数组或可遍历的对象
 - 100100502 : 列表合并参数必须是数组或可遍历的对象
 - 100100503 : 只读list，不允许执行插入操作
 - 100100504 : List索引"{index}"已超出范围
 - 100100505 : 只读list，不允许执行移除操作
 - 100100506 : List索引"{index}"已超出范围
 - 100100507 : List索引"{index}"已超出范围
 
 - 100100601 : 实例化列表参数必须是数组或可遍历的对象
 - 100100602 : 合并map参数必须是数组或可遍历的对象
 - 100100603 : 只读map，不允许执行添加操作
 - 100100604 : 只读map，不允许执行删除操作
```
