├── .gitignore ├── tmp ├── array.png ├── object.png ├── string.png └── function.png ├── composer.json ├── src ├── render │ ├── DumpString.php │ ├── DumpArray.php │ ├── DumpObject.php │ └── AbstractDump.php ├── decorator │ ├── P.php │ ├── Div.php │ ├── Span.php │ └── DecoratorComponent.php ├── conf │ ├── css.php │ └── decorator.php └── Dump.php ├── README.md └── example.php /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | /vendor/ 3 | -------------------------------------------------------------------------------- /tmp/array.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nineyang/dd/HEAD/tmp/array.png -------------------------------------------------------------------------------- /tmp/object.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nineyang/dd/HEAD/tmp/object.png -------------------------------------------------------------------------------- /tmp/string.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nineyang/dd/HEAD/tmp/string.png -------------------------------------------------------------------------------- /tmp/function.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nineyang/dd/HEAD/tmp/function.png -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "nine/dd", 3 | "authors": [ 4 | { 5 | "name": "nine", 6 | "email": "nine@segmentfault.com" 7 | } 8 | ], 9 | "require": {}, 10 | "autoload": { 11 | "psr-4": { "dd\\": "src/" } 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/render/DumpString.php: -------------------------------------------------------------------------------- 1 | display($this->value , 'span' , ['nine-span']); 22 | } 23 | } -------------------------------------------------------------------------------- /src/decorator/P.php: -------------------------------------------------------------------------------- 1 | value = $this->noWrap($this->value); 23 | return $this; 24 | } 25 | 26 | /** 27 | * 28 | */ 29 | public function display() 30 | { 31 | echo $this->value; 32 | } 33 | } -------------------------------------------------------------------------------- /src/decorator/Div.php: -------------------------------------------------------------------------------- 1 | value = $this->noWrap($this->value); 23 | return $this; 24 | } 25 | 26 | /** 27 | * 28 | */ 29 | public function display() 30 | { 31 | echo $this->value; 32 | } 33 | } -------------------------------------------------------------------------------- /src/render/DumpArray.php: -------------------------------------------------------------------------------- 1 | display($this->parseArr($this->value)); 36 | } 37 | } -------------------------------------------------------------------------------- /src/conf/css.php: -------------------------------------------------------------------------------- 1 | "color:#df5000;font-size:14px;font-family:monospace;", 12 | '.black-color' => "color:#333333", 13 | '.gray-color' => "color:#ccc", 14 | '.font-12' => 'font-size:12px', 15 | '.font-15' => 'font-size:15px', 16 | '.depth-0' => 'margin-left:0px', 17 | '.depth-1' => 'margin-left:1rem', 18 | '.depth-2' => 'margin-left:2rem', 19 | '.depth-3' => 'margin-left:3rem', 20 | '.depth-4' => 'margin-left:4rem', 21 | '.depth-5' => 'margin-left:5rem', 22 | '.nine-div' => 'margin-left:10px;margin-top:10px;' 23 | ]; -------------------------------------------------------------------------------- /src/decorator/Span.php: -------------------------------------------------------------------------------- 1 | value = (array_key_exists('withQuota', $params) && !$params['withQuota']) ? $this->noWrap($this->value) : $this->withQuota($this->noWrap($this->value)); 25 | return $this; 26 | } 27 | 28 | /** 29 | * 30 | */ 31 | public function display() 32 | { 33 | echo $this->value; 34 | } 35 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## 介绍 2 | `Laravel`有一个非常方便的`dd`函数可以帮助我们更好的展示信息,不过输出对象时,没办法显示具体的类文件,也没有展示其方法。 3 | 但是`Laravel`的`dd`函数设计的毕竟复杂,所以我就自己写了一个这样的包。 4 | 5 | ## 安装 6 | 1. composer 安装 7 | ``` 8 | composer require nine/dd 9 | ``` 10 | 11 | 2. 直接下载 12 | clone 下来即可。 13 | 14 | ## 使用 15 | 16 | 1. 如我在[exapmle.php](/example.php)中所写,我们既可以直接使用: 17 | ```php 18 | \dd\Dump::dump('hello,nine'); 19 | ``` 20 | 同时也可以自己封装一个`dd`函数: 21 | ```php 22 | function dd($value) 23 | { 24 | \dd\Dump::dump($value); 25 | } 26 | 27 | dd("hello,nine"); 28 | ``` 29 | 30 | 不管是哪种方式,他都会自动的识别我们的类型来予以不同的展示效果。 31 | 32 | 2. `decorator`是一个装饰器层,用来装饰我们的效果。他可以实现一层一层的包装,就像我们用`div`标签来包裹住`span`标签一样。 33 | 34 | 3. 此外,如果需要自己单独配置样式和新增装饰符号,可以在[conf](/src/conf)目录下根据所给的注释予以添加。 35 | 36 | 37 | ## 效果 38 | 1. string 39 | 40 | ![Aaron Swartz](/tmp/string.png) 41 | 42 | 2. array 43 | 44 | ![Aaron Swartz](/tmp/array.png) 45 | 46 | 3. function 47 | 48 | ![Aaron Swartz](/tmp/function.png) 49 | 50 | 4. object 51 | 52 | ![Aaron Swartz](/tmp/object.png) 53 | 54 | ## todo 55 | ~~1. object~~ 56 | 57 | 2. 点击小三角的特效 58 | -------------------------------------------------------------------------------- /example.php: -------------------------------------------------------------------------------- 1 | ['aa' , 'bb' => ['cc' , 'dd']]]); 17 | 18 | //function 19 | //\dd\Dump::dump(function ($name = 'nine' , Closure $closure) { 20 | // echo $name; 21 | //}); 22 | 23 | //object 24 | //\dd\Dump::dump(new stdClass()); 25 | 26 | class Student 27 | { 28 | public $name = 'seven'; 29 | protected $age; 30 | private $sex = 'male'; 31 | 32 | /** 33 | * @return string 34 | */ 35 | public function getName() 36 | { 37 | return $this->name; 38 | } 39 | 40 | /** 41 | * @param string $name 42 | */ 43 | public function setName($name) 44 | { 45 | $this->name = $name; 46 | } 47 | 48 | /** 49 | * @param $age 50 | */ 51 | public function setAge($age) 52 | { 53 | $this->age = $age; 54 | } 55 | } 56 | 57 | 58 | function dd($value) 59 | { 60 | \dd\Dump::dump($value); 61 | } 62 | 63 | //dd("hello,nine"); 64 | 65 | //dd(function ($a = 'nine'){ 66 | // echo $a; 67 | //}); 68 | 69 | $student = new Student(); 70 | $student->name = 'nine'; 71 | $student->setAge(10); 72 | dd($student); 73 | -------------------------------------------------------------------------------- /src/Dump.php: -------------------------------------------------------------------------------- 1 | _namespace . $this->_head . ucfirst(gettype($value)); 52 | if (!class_exists($class)) { 53 | throw new Exception("$class is not exists"); 54 | } 55 | $flectionClass = new ReflectionClass($class); 56 | if (!$flectionClass->isSubclassOf($this->_namespace . $this->_abstract)) { 57 | throw new Exception("$class must extends $this->_namespace" . $this->_abstract); 58 | } 59 | if (!$flectionClass->hasMethod($this->_method)) { 60 | throw new Exception("$class must has method render"); 61 | } 62 | // todo 如果方法以后有不同的参数的需求,可以调用getParameters()来判断获取参数 63 | $flectionMethod = new ReflectionMethod($class, $this->_method); 64 | $flectionMethod->invokeArgs($flectionClass->newInstance($value), []); 65 | } 66 | 67 | /** 68 | * @param $value 69 | */ 70 | static public function dump($value) 71 | { 72 | if (is_null(static::$_instance)) { 73 | static::$_instance = new static(); 74 | } 75 | static::$_instance->parse($value); 76 | } 77 | } -------------------------------------------------------------------------------- /src/conf/decorator.php: -------------------------------------------------------------------------------- 1 | key来获取 5 | * value 代表他最终呈现的形式 6 | * type 代表他的标签 默认是span 7 | * style 使用什么样式,在css.php中配置,可以为[] 8 | * params 在用到具体的type所对应的decorator时所需要的参数,这里可以为[] 9 | * User: Nine 10 | * Date: 2017/9/9 11 | * Time: 下午10:22 12 | */ 13 | 14 | return [ 15 | '_leftBracket' => [ 16 | 'value' => "[", 17 | 'type' => 'span', 18 | 'style' => ['nine-span', 'black-color'], 19 | 'params' => ['withQuota' => false] 20 | ], 21 | '_rightBracket' => [ 22 | 'value' => "]", 23 | 'type' => 'span', 24 | 'style' => ['nine-span', 'black-color'], 25 | 'params' => ['withQuota' => false] 26 | ], 27 | '_triangle' => [ 28 | 'value' => "▶", 29 | 'type' => 'span', 30 | 'style' => ['nine-span', 'gray-color', 'font-12'], 31 | 'params' => ['withQuota' => false] 32 | ], 33 | '_needle' => [ 34 | 'value' => "=>", 35 | 'type' => 'span', 36 | 'style' => ['nine-span', 'black-color'], 37 | 'params' => ['withQuota' => false] 38 | ], 39 | '_leftBraces' => [ 40 | 'value' => "{", 41 | 'type' => 'span', 42 | 'style' => ['nine-span', 'black-color'], 43 | 'params' => ['withQuota' => false] 44 | ], 45 | '_rightBraces' => [ 46 | 'value' => "}", 47 | 'type' => 'span', 48 | 'style' => ['nine-span', 'black-color'], 49 | 'params' => ['withQuota' => false] 50 | ], 51 | '_spaceZero' => [ 52 | 'value' => "", 53 | 'type' => 'span', 54 | 'style' => ['nine-span', 'depth-0'], 55 | 'params' => ['withQuota' => false] 56 | ], 57 | '_spaceOne' => [ 58 | 'value' => "", 59 | 'type' => 'span', 60 | 'style' => ['nine-span', 'depth-1'], 61 | 'params' => ['withQuota' => false] 62 | ], 63 | '_spaceTwo' => [ 64 | 'value' => "", 65 | 'type' => 'span', 66 | 'style' => ['nine-span', 'depth-2'], 67 | 'params' => ['withQuota' => false] 68 | ], 69 | '_spaceThree' => [ 70 | 'value' => "", 71 | 'type' => 'span', 72 | 'style' => ['nine-span', 'depth-3'], 73 | 'params' => ['withQuota' => false] 74 | ], 75 | '_spaceFour' => [ 76 | 'value' => "", 77 | 'type' => 'span', 78 | 'style' => ['nine-span', 'depth-4'], 79 | 'params' => ['withQuota' => false] 80 | ], 81 | '_spaceFive' => [ 82 | 'value' => "", 83 | 'type' => 'span', 84 | 'style' => ['nine-span', 'depth-5'], 85 | 'params' => ['withQuota' => false] 86 | ], 87 | ]; -------------------------------------------------------------------------------- /src/decorator/DecoratorComponent.php: -------------------------------------------------------------------------------- 1 | value = $value; 45 | $this->initStyle(); 46 | } 47 | 48 | /** 49 | * 初始化css 50 | */ 51 | protected function initStyle() 52 | { 53 | $config = require_once __DIR__ . '/../conf/css.php'; 54 | // 防止重复加载 55 | if ($config === true) return; 56 | $styleStr = ""; 62 | } 63 | echo $styleStr; 64 | } 65 | 66 | /** 67 | * 添加样式 68 | * @param $className 69 | * @return $this 70 | */ 71 | public function addClass($className) 72 | { 73 | array_push($this->classList, $className); 74 | return $this; 75 | } 76 | 77 | /** 78 | * 清除已经存在的样式列表 79 | * @return $this 80 | */ 81 | public function clearClass() 82 | { 83 | $this->classList = []; 84 | return $this; 85 | } 86 | 87 | /** 88 | * 添加css并转发给wrap 89 | * @return mixed 90 | */ 91 | public function addDecorator() 92 | { 93 | // 设置tag 94 | $parts = explode("\\", static::class); 95 | $class = strtolower(array_pop($parts)); 96 | // 设置class 97 | $classStr = implode(' ', $this->classList); 98 | $this->_head = "<" . $class . " class='$classStr'>"; 99 | $this->_tail = ""; 100 | // 清空样式 101 | $this->clearClass(); 102 | return static::wrap(func_get_args()); 103 | } 104 | 105 | /** 106 | * 用引号包裹 107 | * @param $value 108 | * @return string 109 | */ 110 | public function withQuota($value) 111 | { 112 | return '"' . $value . '"'; 113 | } 114 | 115 | /** 116 | * 用中括号包裹 117 | * @param $value 118 | */ 119 | public function withBracket($value) 120 | { 121 | // todo 这里后面看看是否需要单独提炼出来 122 | } 123 | 124 | /** 125 | * @param $name 126 | * @param $value 127 | */ 128 | public function __set($name, $value) 129 | { 130 | $this->$name = $value; 131 | } 132 | 133 | /** 134 | * 没有包裹的标签 135 | * @param $value 136 | * @return string 137 | */ 138 | public function noWrap($value) 139 | { 140 | return $this->_head . $value . $this->_tail; 141 | } 142 | 143 | /** 144 | * @return mixed 145 | */ 146 | abstract public function display(); 147 | } -------------------------------------------------------------------------------- /src/render/DumpObject.php: -------------------------------------------------------------------------------- 1 | value instanceof Closure) { 33 | $this->renderClosure(); 34 | } else { 35 | $this->renderObject(); 36 | } 37 | } 38 | 39 | /** 40 | * render 函数 41 | */ 42 | protected function renderClosure() 43 | { 44 | $this->display($this->getFunc()); 45 | } 46 | 47 | /** 48 | * 共同的闭包组件 49 | * @param string $value 50 | * @param string $title 51 | * @param int $depth 52 | * @return array 53 | */ 54 | protected function getFunc($value = '', $title = 'Closure', $depth = 0) 55 | { 56 | $reflectionFunc = new ReflectionFunction($value ?: $this->value); 57 | $renderParams = $this->parseArr( 58 | $this->parseParams( 59 | $reflectionFunc->getParameters() 60 | ), 61 | 5 62 | ); 63 | $title = $this->returnValue($title, 'span', ['nine-span'], ['withQuota' => false]); 64 | return [ 65 | $title, 66 | $this->_leftBraces . "
", 67 | $this->_spaceOne, 68 | $this->{"_space" . $this->_numMap[$depth]} . $this->returnValue('params', 'span', ['nine-span'], ['withQuota' => false]), 69 | $this->_needle, 70 | implode('', $renderParams) . "
", 71 | $this->{"_space" . $this->_numMap[$depth]} . $this->_rightBraces 72 | ]; 73 | } 74 | 75 | /** 76 | * render 对象 77 | */ 78 | protected function renderObject() 79 | { 80 | $reflectionObject = new ReflectionObject($this->value); 81 | $defaultProperties = $reflectionObject->getDefaultProperties(); 82 | $properties = $reflectionObject->getProperties(); 83 | $renderProperties = []; 84 | // 属性 85 | if (!empty($properties)) { 86 | foreach ($properties as $property) { 87 | $scope = $this->returnValue( 88 | ($property->isPublic() ? "+" : ($property->isProtected() ? "#" : "-")), 89 | 'span', 90 | ['nine-span', 'depth-1'], 91 | ['withQuota' => false] 92 | ); 93 | $name = $scope . $this->returnValue($property->name, 'span', ['nine-span', 'font-15'], ['withQuota' => false]); 94 | // 先获取设置的值 95 | $property->setAccessible(true); 96 | if ($currValue = $property->getValue($this->value)) { 97 | $default = $currValue; 98 | // 再获取默认值 99 | } elseif (isset($defaultProperties[$property->name])) { 100 | $default = $defaultProperties[$property->name]; 101 | } else { 102 | $default = ''; 103 | } 104 | $default = $this->_spaceOne . 105 | $this->returnValue( 106 | $default, 107 | 'span', 108 | ['nine-span', 'gray-color'], 109 | ['withQuota' => false] 110 | ); 111 | $renderProperties[] = $name . $default . "
"; 112 | } 113 | } 114 | // 方法 115 | $methods = $reflectionObject->getMethods(); 116 | $renderMethods = []; 117 | if (!empty($methods)) { 118 | foreach ($methods as $method) { 119 | $scope = $this->returnValue( 120 | ($method->isPublic() ? "+" : ($method->isProtected() ? "#" : "-")), 121 | 'span', 122 | ['nine-span', 'depth-1'], 123 | ['withQuota' => false] 124 | ); 125 | // 获取一个闭包,来使用共同的getFunc组件 126 | $renderMethods[] = $scope . implode('', $this->getFunc($method->getClosure($this->value), $method->name, 1)) . "
"; 127 | } 128 | } 129 | $this->display( 130 | [ 131 | $this->returnValue($reflectionObject->name, 'span', ['nine-span'], ['withQuota' => false]), 132 | $this->_leftBraces . "
", 133 | implode("", array_merge($renderProperties, $renderMethods)), 134 | $this->_rightBraces 135 | ] 136 | ); 137 | } 138 | 139 | 140 | } -------------------------------------------------------------------------------- /src/render/AbstractDump.php: -------------------------------------------------------------------------------- 1 | value = $value; 28 | $this->init(); 29 | } 30 | 31 | /** 32 | * 初始化一些需要展示的内容 33 | */ 34 | protected function init() 35 | { 36 | $config = require_once __DIR__ . '/../conf/decorator.php'; 37 | if ($config === true) return; 38 | 39 | if (!empty($config)) { 40 | foreach ($config as $key => $value) { 41 | if (!array_key_exists('value', $value)) continue; 42 | if (!array_key_exists('type', $value)) $value['type'] = 'span'; 43 | if (!array_key_exists('style', $value)) { 44 | $value['style'] = []; 45 | } elseif (!is_array($value['style'])) { 46 | $value['style'] = []; 47 | } 48 | if (!array_key_exists('params', $value)) { 49 | $value['params'] = []; 50 | } elseif (!is_array($value['params'])) { 51 | $value['params'] = []; 52 | } 53 | // invoke 54 | $this->$key = $this->returnValue($value['value'], $value['type'], $value['style'], $value['params']); 55 | } 56 | } 57 | } 58 | 59 | /** 60 | * @var array 61 | */ 62 | protected $_decorator = []; 63 | 64 | /** 65 | * @param $type 66 | * @param array $classArr 67 | * @param array $params 68 | * @param string $value 69 | * @return mixed 70 | */ 71 | public function returnValue($value = '', $type = 'span', $classArr = ['nine-span'], $params = ['withQuota' => true]) 72 | { 73 | if (is_array($value)) { 74 | return implode('', $value); 75 | } 76 | return ($this->returnDecorator($type, $classArr, $value, $params))->value; 77 | } 78 | 79 | /** 80 | * @param $type 81 | * @param array $classArr 82 | * @param array $params 83 | * @param string $value 84 | * @return mixed 85 | */ 86 | protected function returnDecorator($type, $classArr = [], $value = '', $params = []) 87 | { 88 | $decorator = $this->{$type}($value ?: $this->value); 89 | if (!empty($classArr)) { 90 | foreach ($classArr as $class) { 91 | $decorator->addClass($class); 92 | } 93 | } 94 | // 因为是单例,所以这里的value需要重新修改一下 95 | $decorator->value = $value; 96 | return $decorator->addDecorator($params); 97 | } 98 | 99 | /** 100 | * @param $value 101 | * @param null $type 102 | * @param array $classArr 103 | * @param array $params 104 | */ 105 | public function display($value = '', $type = null, $classArr = [], $params = []) 106 | { 107 | if (is_array($value)) { 108 | $value = implode('', $value); 109 | } elseif ($value == '') { 110 | $value = $this->value; 111 | } 112 | 113 | // 此时为空代表已经拼接好 114 | // 拼接一个div包裹起来 115 | if (is_null($type)) { 116 | $divDecorator = $this->returnDecorator('div', ['nine-div'], $value); 117 | } else { 118 | $typeDecorator = $this->returnDecorator($type, $classArr, $value, $params); 119 | 120 | $divDecorator = $this->returnDecorator('div', ['nine-div'], $typeDecorator->value); 121 | } 122 | 123 | $divDecorator->display(); 124 | die(); 125 | } 126 | 127 | /** 128 | * @param array $arr 129 | * @param int $depth 130 | * @return array 131 | */ 132 | protected function parseArr(array $arr, $depth = 1) 133 | { 134 | if (empty($arr)) { 135 | return []; 136 | } 137 | // 首先导入array 138 | $returnArr = []; 139 | $returnArr[] = $this->returnValue("array:" . count($arr), 'span', ['nine-span'], ['withQuota' => false]); 140 | // 导入一个[ 141 | $returnArr[] = $this->_leftBracket; 142 | // 导入一个▶ 143 | $returnArr[] = $this->_triangle; 144 | $pushValue = ""; 145 | 146 | foreach ($arr as $key => $value) { 147 | // 拼接key和value 148 | $key = $this->returnValue($key, 'span', ['nine-span'], ['withQuota' => is_int($key) ? false : true]); 149 | if (is_array($value)) { 150 | $value = $this->returnValue(self::parseArr($value, $depth + 1)); 151 | } else { 152 | $value = $this->returnValue($value); 153 | } 154 | $pushValue .= $key . $this->_needle . $value . "
"; 155 | } 156 | // 外层包裹一个p 157 | $returnArr[] = $this->returnValue($pushValue, 'p', ["depth-" . $depth]); 158 | $devideSpan = $this->returnValue("", 'span', ["depth-" . ($depth - 1)], ['withQuota' => false]); 159 | 160 | $returnArr[] = $devideSpan . $this->_rightBracket; 161 | return $returnArr; 162 | } 163 | 164 | /** 165 | * 反射解析函数的参数 166 | * @param array $params 167 | * @return array 168 | */ 169 | protected function parseParams(Array $params) 170 | { 171 | $renderParams = []; 172 | if (!empty($params)) { 173 | foreach ($params as $param) { 174 | $name = $this->returnValue($param->name, 'span', ['nine-span', 'font-15'], ['withQuota' => false]); 175 | if ($param->isDefaultValueAvailable()) { 176 | $default = $this->_spaceOne . 177 | $this->returnValue( 178 | $param->getDefaultValue(), 179 | 'span', 180 | ['nine-span', 'gray-color'], 181 | ['withQuota' => false] 182 | ); 183 | } else { 184 | $default = ''; 185 | } 186 | $renderParams[] = $name . $default; 187 | } 188 | } 189 | return $renderParams; 190 | } 191 | 192 | /** 193 | * @param $decorator 194 | * @return \dd\decorator\DecoratorComponent 195 | */ 196 | public function __get($decorator) 197 | { 198 | array_key_exists($decorator, $this->_decorator) ?: $this->_decorator[$decorator] = $this->withObject("dd\\decorator\\" . ucfirst($decorator), $this->value); 199 | return $this->_decorator[$decorator]; 200 | } 201 | 202 | /** 203 | * 为方便层层包裹 204 | * @param $decorator 205 | * @param $arguments 206 | * @return \dd\decorator\DecoratorComponent 207 | */ 208 | public function __call($decorator, $arguments) 209 | { 210 | array_key_exists($decorator, $this->_decorator) ?: $this->_decorator[$decorator] = $this->withObject("dd\\decorator\\" . ucfirst($decorator), array_pop($arguments)); 211 | return $this->_decorator[$decorator]; 212 | } 213 | 214 | /** 215 | * @param $class 216 | * @param null $arguments 217 | * @return mixed 218 | */ 219 | protected function withObject($class, $arguments = null) 220 | { 221 | return is_null($arguments) ? new $class : new $class($arguments); 222 | } 223 | 224 | abstract public function render(); 225 | } --------------------------------------------------------------------------------