├── .varci.yml ├── LICENSE ├── README.md ├── algorithm ├── fibonacci.php ├── other.php ├── sort │ ├── bubble.php │ ├── heap.php │ ├── insert.php │ ├── merge.php │ ├── quick.php │ ├── radix.php │ ├── select.php │ └── shell.php └── test.php ├── data-structure └── data-structure.md ├── linux └── command.md ├── mysql ├── index.md ├── lock.md └── sql.md ├── network ├── http.md ├── internet-protocol.md └── nginx.md ├── patterns ├── adapter │ ├── Adapter.php │ ├── AdvanceMp4Player.php │ ├── AdvanceWmaPlayer.php │ ├── AudioPlayer.php │ ├── MediaAdvanceInterface.php │ ├── MediaInterface.php │ └── test.php ├── bridge │ ├── EatByChopsticks.php │ ├── EatByFork.php │ ├── EatInterface.php │ ├── PersonAbstract.php │ ├── PersonMale.php │ └── test.php ├── builder │ ├── BuilderInterface.php │ ├── Hardware.php │ ├── HardwareCamera.php │ ├── HardwareCpu.php │ ├── HardwareRam.php │ ├── HardwareScreen.php │ ├── HardwareStorage.php │ ├── Mp3Builder.php │ ├── PhoneBuilder.php │ ├── Software.php │ ├── SoftwareOs.php │ └── test.php ├── chainOfResponsibility │ ├── Handler.php │ ├── HandlerAccessToken.php │ ├── HandlerArguments.php │ ├── HandlerAuthority.php │ ├── HandlerFrequent.php │ ├── HandlerSign.php │ ├── Request.php │ └── test.php ├── command │ ├── Console.php │ ├── Order.php │ ├── OrderCreate.php │ ├── OrderSave.php │ ├── OrderWrite.php │ ├── Text.php │ └── test.php ├── composite │ ├── CompositeInterface.php │ ├── File.php │ ├── Folder.php │ └── test.php ├── decorator │ ├── BasicPulisher.php │ ├── Decorator.php │ ├── DecoratorBrand.php │ ├── MoviePulisher.php │ ├── MusicPublisher.php │ ├── PulisherDerector.php │ ├── PulisherInterface.php │ ├── ShoesInterface.php │ ├── ShoesSkateboard.php │ ├── ShoesSport.php │ ├── test.php │ └── testpulish.php ├── facade │ ├── AnimalInterface.php │ ├── AnimalMaker.php │ ├── Chicken.php │ ├── Pig.php │ └── test.php ├── factory │ ├── AnimalInterface.php │ ├── Chicken.php │ ├── Factory.php │ ├── Farm.php │ ├── Pig.php │ ├── SampleFactory.php │ ├── Zoo.php │ └── test.php ├── factoryAbstract │ ├── AnimalFactory.php │ ├── Factory.php │ ├── FarmInterface.php │ ├── Income.php │ ├── PandaZoo.php │ ├── PeonyZoo.php │ ├── PigFarm.php │ ├── PlantFactory.php │ ├── RiceFarm.php │ ├── ZooInterface.php │ └── test.php ├── filter │ ├── FilterGender.php │ ├── FilterInterface.php │ ├── FilterSportType.php │ ├── SportsPerson.php │ └── test.php ├── flyweight │ ├── AnimalInterface.php │ ├── Chicken.php │ ├── Farm.php │ ├── Pig.php │ └── test.php ├── interpreter │ ├── SqlInterpreter.php │ └── test.php ├── iterator │ ├── Iterator.php │ ├── School.php │ ├── SchoolExperimental.php │ ├── TeacherIterator.php │ └── test.php ├── mediator │ ├── HouseMediator.php │ ├── Landlord.php │ ├── Person.php │ ├── Tenant.php │ └── test.php ├── memento │ ├── Editor.php │ ├── Memento.php │ └── test.php ├── nullObject │ ├── NullPerson.php │ ├── Person.php │ ├── Student.php │ ├── Teacher.php │ └── test.php ├── observer │ ├── Observable.php │ ├── ObservableInterface.php │ ├── ObserverExampleOne.php │ ├── ObserverExampleTwo.php │ ├── ObserverInterface.php │ ├── spl │ │ ├── Observable.php │ │ ├── ObserverExampleOne.php │ │ ├── ObserverExampleTwo.php │ │ └── test.php │ └── test.php ├── prototype │ ├── Prototype.php │ ├── PrototypeAbstract.php │ └── test.php ├── proxy │ ├── Proxy.php │ ├── ShoesInterface.php │ ├── ShoesSkateboard.php │ ├── ShoesSport.php │ ├── common │ │ ├── Proxy.php │ │ ├── RealSubject.php │ │ ├── Subject.php │ │ └── test.php │ ├── dynamic │ │ ├── InvocationHandler.php │ │ ├── Proxy.php │ │ ├── RealSubject.php │ │ ├── Subject.php │ │ ├── SubjectIH.php │ │ └── test.php │ ├── enforce │ │ ├── Proxy.php │ │ ├── RealSubject.php │ │ ├── Subject.php │ │ └── test.php │ ├── ext │ │ ├── IProxy.php │ │ ├── Proxy.php │ │ ├── RealSubject.php │ │ ├── Subject.php │ │ └── test.php │ ├── test.php │ └── virtual │ │ ├── Proxy.php │ │ ├── RealSubject.php │ │ ├── Subject.php │ │ └── test.php ├── singleton │ ├── Singleton.php │ └── test.php ├── state │ ├── Farm.php │ ├── FarmAutumn.php │ ├── FarmSpring.php │ ├── FarmSummer.php │ ├── FarmWinter.php │ ├── Farmer.php │ └── test.php ├── strategy │ ├── StrategyExampleOne.php │ ├── StrategyExampleTwo.php │ ├── StrategyInterface.php │ ├── Substance.php │ └── test.php ├── template │ ├── Sms.php │ ├── SmsCompanyOne.php │ ├── SmsCompanyTwo.php │ └── test.php ├── thought.md └── visitor │ ├── AnimailInterface.php │ ├── Person.php │ ├── VisitorAmerica.php │ ├── VisitorAsia.php │ ├── VisitorInterface.php │ └── test.php ├── php ├── artisan.md ├── magic-function │ ├── __call.php │ ├── __callStatic.php │ ├── __construct.php │ ├── __get.php │ ├── __set.php │ ├── analysis │ ├── function.php │ ├── logs │ │ ├── __callStatic_magic_php.log │ │ ├── __callStatic_magic_php5.log │ │ ├── __callStatic_no_magic_php.log │ │ ├── __callStatic_no_magic_php5.log │ │ ├── __call_magic_php.log │ │ ├── __call_magic_php5.log │ │ ├── __call_no_magic_php.log │ │ ├── __call_no_magic_php5.log │ │ ├── __construct_magic_php.log │ │ ├── __construct_magic_php5.log │ │ ├── __construct_no_magic_php.log │ │ ├── __construct_no_magic_php5.log │ │ ├── __get_magic_php.log │ │ ├── __get_magic_php5.log │ │ ├── __get_no_magic_php.log │ │ ├── __get_no_magic_php5.log │ │ ├── __set_magic_php.log │ │ ├── __set_magic_php5.log │ │ ├── __set_no_magic_php.log │ │ └── __set_no_magic_php5.log │ └── test ├── standard.md └── standard.php ├── pit.md └── redis ├── cache.php ├── optimistic-lock.php ├── pessmistic-lock.php ├── queue.php ├── subscribe-publish ├── publish.php └── subscribe.php └── test.php /.varci.yml: -------------------------------------------------------------------------------- 1 | ruleset: 2 | 3 | respond_to_me: 4 | 5 | name: Respond to me when I comment mentioning @VarCI-bot 6 | events: [ issue_comment ] 7 | when: 8 | - action = "created" 9 | - user.login = "TIGERB" 10 | - body contains "@VarCI-bot" 11 | comment: | 12 | Perfect @{{ user.login }} - now replace the first two rules with your own! 13 | 14 | If you wish to keep the third rule, you can merge by starting a comment with "LGTM". 15 | 16 | Please see the following resources if you get stuck - best of luck! 17 | 18 | - [Documentation](https://var.ci/docs) 19 | - [Support](https://var.ci/support) 20 | 21 | merge_for_me: 22 | 23 | name: Merge pull requests for me when I start a comment with "LGTM" 24 | events: [ issue_comment ] 25 | when: 26 | - action = "created" 27 | - user.login = "TIGERB" 28 | - body matches "/^LGTM/" 29 | merge: true 30 | 31 | welcome_me: 32 | 33 | name: Introduce me to VarCI when I open a pull request 34 | events: [ pull_request ] 35 | when: 36 | - action = "opened" 37 | - user.login = "TIGERB" 38 | comment: | 39 | Welcome to VarCI @{{ user.login }}! 40 | 41 | Continue pushing changes to the config in this branch and I'll validate the changes. 42 | 43 | You can also test out new rules in your pull requests before merging them. 44 | 45 | For example, try triggering the second rule by mentioning me (@VarCI-bot) right now! 46 | 47 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 TIGERB 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /algorithm/fibonacci.php: -------------------------------------------------------------------------------- 1 | 8 | */ 9 | 10 | /** 11 | * for循环斐波纳耶 12 | * 13 | * @param integer $n 数列长度 14 | * @return array 15 | */ 16 | function forcycle($n = 0) 17 | { 18 | $res = []; 19 | for ($i = 0; $i < $n; $i++) { 20 | if ($i === 0) { 21 | $res[] = 0; 22 | continue; 23 | } 24 | if ($i === 1) { 25 | $res[] = 1; 26 | continue; 27 | } 28 | $res[] = $res[$i - 1] + $res[$i - 2]; 29 | } 30 | return $res; 31 | } 32 | 33 | /** 34 | * 递归循环斐波纳耶 35 | * 36 | * @param integer $n 数列长度 37 | * @param integer $i 当前位置 38 | * @param integer $res 数列 39 | * @return array 40 | */ 41 | function recursion($n = 0, $i = 0, $res = []) 42 | { 43 | if ($i >= $n) { 44 | return $res; 45 | } 46 | if ($i === 0) { 47 | $res[] = 0; 48 | } elseif ($i === 1) { 49 | $res[] = 1; 50 | } else { 51 | $res[] = $res[$i - 1] + $res[$i - 2]; 52 | } 53 | return recursion($n, ++$i, $res); 54 | } 55 | -------------------------------------------------------------------------------- /algorithm/other.php: -------------------------------------------------------------------------------- 1 | = 0; --$i) { 18 | $res += $str[$i]*(2**($length-$i)); 19 | } 20 | return $res; 21 | } 22 | -------------------------------------------------------------------------------- /algorithm/sort/bubble.php: -------------------------------------------------------------------------------- 1 | 8 | */ 9 | 10 | /** 11 | * 冒泡排序 12 | * 13 | * @param array $value 待排序数组 14 | * @return array 15 | */ 16 | function bubble($value = []) 17 | { 18 | $length = count($value) - 1; 19 | // 外循环 20 | for ($j = 0; $j < $length; ++$j) { 21 | // 内循环 22 | for ($i = 0; $i < $length; ++$i) { 23 | // 如果后一个值小于前一个值,则互换位置 24 | if ($value[$i + 1] < $value[$i]) { 25 | $tmp = $value[$i + 1]; 26 | $value[$i + 1] = $value[$i]; 27 | $value[$i] = $tmp; 28 | } 29 | } 30 | } 31 | 32 | return $value; 33 | } 34 | 35 | /** 36 | * 优化冒泡排序 37 | * 38 | * @param array $value 待排序数组 39 | * @return array 40 | */ 41 | function bubble_better($value = []) 42 | { 43 | $flag = true; // 标示 排序未完成 44 | $length = count($value)-1; // 数组长度 45 | $index = $length; // 最后一次交换的索引位置 初始值为最后一位 46 | while ($flag) { 47 | $flag = false; // 假设排序已完成 48 | for ($i=0; $i < $index; $i++) { 49 | if ($value[$i] > $value[$i+1]) { 50 | $flag = true; // 如果还有交换发生 则排序未完成 51 | $last = $i; // 记录最后一次发生交换的索引位置 52 | $tmp = $value[$i]; 53 | $value[$i] = $value[$i+1]; 54 | $value[$i+1] = $tmp; 55 | } 56 | } 57 | $index = $last; 58 | } 59 | 60 | return $value; 61 | } 62 | -------------------------------------------------------------------------------- /algorithm/sort/heap.php: -------------------------------------------------------------------------------- 1 | 8 | */ 9 | 10 | /** 11 | * 堆排序. 12 | * 13 | * @param array $value 待排序数组 14 | * 15 | * @return array 16 | */ 17 | function heap(&$values = []) 18 | { 19 | //堆化数组 20 | $heap = []; 21 | foreach ($values as $i=>$v) { 22 | $heap[$i] = $v; 23 | $heap = minHeapFixUp($heap, $i); 24 | } 25 | $values = $heap; 26 | 27 | //堆排序 28 | $n = count($values); 29 | for ($i = $n-1; $i>=1; $i--) { 30 | swap($values[$i], $values[0]); 31 | minHeapFixDown($values, 0, $i); 32 | } 33 | return $values; 34 | } 35 | 36 | function swap(&$a, &$b) { 37 | $temp = $a; 38 | $a= $b; 39 | $b = $temp; 40 | } 41 | 42 | /** 43 | * 堆插入数据 44 | * @param $values 45 | * @param $i 46 | * @return mixed 47 | */ 48 | function minHeapFixUp($values, $i) { 49 | 50 | $j = ($i-1)/2; 51 | $temp = $values[$i]; 52 | 53 | while($j >= 0 && $i != 0) { 54 | 55 | if($values[$j] <= $temp) { 56 | break; 57 | } 58 | $values[$i] = $values[$j]; 59 | $i = $j; 60 | $j = ($i-1)/2; 61 | } 62 | $values[$i] = $temp; 63 | return $values; 64 | } 65 | 66 | /** 67 | * 调整堆,可用于删除堆节点 68 | * @param $heap 69 | * @param $i 70 | * @param $n 71 | */ 72 | function minHeapFixDown(&$heap, $i, $n) { 73 | $j = 2*$i + 1; 74 | $temp = $heap[$i]; 75 | 76 | while ($j < $n) { 77 | if($j+1 <$n && $heap[$j+1] < $heap[$j]) { 78 | $j++; 79 | } 80 | if($heap[$j] >= $temp) { 81 | break; 82 | } 83 | $heap[$i] = $heap[$j]; 84 | $i = $j; 85 | $j = 2*$i + 1; 86 | } 87 | $heap[$i] = $temp; 88 | } 89 | -------------------------------------------------------------------------------- /algorithm/sort/insert.php: -------------------------------------------------------------------------------- 1 | 8 | */ 9 | 10 | /** 11 | * 插入排序. 12 | * 13 | * @param array $value 待排序数组 14 | * @param integer $point 起始位置 15 | * 16 | * @return array 17 | */ 18 | function insert(&$value=[], $point=0) 19 | { 20 | if ($point >= count($value) - 1) { 21 | return; 22 | } 23 | $next = $value[$point + 1]; // 下一个待插入值 24 | // 从后向前遍历已排序数组 25 | for ($i=$point; $i >= 0; --$i) { 26 | // 如果当前已排序值大于 待插入值 27 | // 把当前值后往后移动一位 28 | // 继续向前遍历 29 | if ($value[$i] > $next) { 30 | $value[$i+1] = $value[$i]; 31 | // 如果到开头,自动到插入头位 32 | if ($i === 0) { 33 | $value[$i] = $next; 34 | break; 35 | } 36 | continue; 37 | } 38 | // 如果,当前已排序值小于或等于 待插入值 39 | // 则,在当前值后插入 当前待插入值 40 | // 特殊:如果末尾值小于或等于待插入值 则当前值后插入本身 41 | $value[$i+1] = $next; 42 | break; 43 | } 44 | $point += 1;// 已排序末尾位置 45 | 46 | // 递归 47 | insert($value, $point); 48 | 49 | return $value; 50 | } 51 | 52 | /** 53 | * 插入排序 for循环版 54 | * 55 | * @param array $value 待排序数组 56 | * 57 | * @return array 58 | */ 59 | function insert_for($arr=array()) 60 | { 61 | $len = count($arr); 62 | for($i = 1; $i < $len; $i++) { 63 | $base = $arr[$i]; 64 | for($j = $i - 1; $j >= 0; $j--) { 65 | if ($base < $arr[$j]) { 66 | $arr[$j + 1] = $arr[$j]; 67 | if ($j === 0) { 68 | $arr[$j] = $base; 69 | break; 70 | } 71 | continue; 72 | } 73 | $arr[$j + 1] = $base; 74 | break; 75 | } 76 | } 77 | return $arr; 78 | } 79 | -------------------------------------------------------------------------------- /algorithm/sort/merge.php: -------------------------------------------------------------------------------- 1 | 8 | */ 9 | 10 | /** 11 | * 合并两个有序数组为一个有序数组 12 | * 13 | * @param array $value 待排序数组 14 | * 15 | * @return array 16 | */ 17 | function merge_array($arr_1, $arr_2) 18 | { 19 | $length_1 = count($arr_1); 20 | $length_2 = count($arr_2); 21 | // 归并算法 22 | // arr_1[$i]和arr_2[$j]比较 23 | // <= 则 arr_3[$k] = arr_1[$i] 且 ++$i ++$k 24 | // >= 则 arr_3[$k] = arr_2[$j] 且 ++$j ++$k 25 | // 直到 $i >= $length_1 或 $j >= $length_2 26 | // 27 | // 接着,如果先$i >= $length_1 28 | // 则, $arr_2[$j~$length_2] 放到 $arr_3后 29 | // 如果先$j >= $length_2 30 | // 则, $arr_1[$i~$length_1] 放到 $arr_3后 31 | $arr_3 = []; 32 | $i = 0; 33 | $j = 0; 34 | $k = 0; 35 | while ($i < $length_1 && $j < $length_2) { 36 | if ($arr_1[$i] <= $arr_2[$j]) { 37 | $arr_3[$k] = $arr_1[$i]; 38 | ++$i; 39 | ++$k; 40 | continue; 41 | } 42 | $arr_3[$k] = $arr_2[$j]; 43 | ++$j; 44 | ++$k; 45 | } 46 | if ($i === $length_1) { 47 | for ($s=$j; $s < $length_2; $s++) { 48 | $arr_3[] = $arr_2[$s]; 49 | } 50 | } 51 | if ($j === $length_2) { 52 | for ($w=$i; $w < $length_1; $w++) { 53 | $arr_3[$k] = $arr_1[$w]; 54 | } 55 | } 56 | return $arr_3; 57 | } 58 | 59 | 60 | /** 61 | * 归并排序. 62 | * 将序列每相邻的两个数字进行归并操作 63 | * 64 | * @param array $value 待排序数组 65 | * 66 | * @return array 67 | */ 68 | function merge(&$value=[]) 69 | { 70 | $length = count($value); 71 | if ($length === 1) { 72 | return; 73 | } 74 | $arr = []; 75 | for ($i=0; $i < $length; $i++) { 76 | if ($i%2 === 0) { 77 | // 合并每两个元素 78 | // 判断值类型 integer 直接比大小 合并 79 | if (is_int($value[$i]) || is_string($value[$i])) { 80 | if (isset($value[$i+1])) { 81 | if ($value[$i] < $value[$i+1]) { 82 | $arr[floor($i/2)][] = $value[$i]; 83 | $arr[floor($i/2)][] = $value[$i+1]; 84 | continue; 85 | } 86 | $arr[floor($i/2)][] = $value[$i+1]; 87 | $arr[floor($i/2)][] = $value[$i]; 88 | continue; 89 | } 90 | $arr[floor($i/2)][] = $value[$i]; 91 | continue; 92 | } 93 | // 判断值类型 array 遍历元素比大小 合并 94 | // 把两个有序数组合并成一个有序数组 95 | // 归并算法详情请看 merge-array 96 | if (is_array($value[$i])) { 97 | if (isset($value[$i+1])) { 98 | $length_arr = count($value[$i]); 99 | $length_arr_last = count($value[$i+1]); 100 | $arr_tmp = []; 101 | $s = 0; 102 | $w = 0; 103 | $k = 0; 104 | while ($s < $length_arr && $w < $length_arr_last) { 105 | if ($value[$i][$s] <= $value[$i+1][$w]) { 106 | $arr_tmp[$k] = $value[$i][$s]; 107 | ++$s; 108 | ++$k; 109 | continue; 110 | } 111 | $arr_tmp[$k] = $value[$i+1][$w]; 112 | ++$w; 113 | ++$k; 114 | continue; 115 | } 116 | if ($s === $length_arr) { 117 | for ($j=$w; $j < $length_arr_last; $j++) { 118 | $arr_tmp[$k] = $value[$i+1][$j]; 119 | ++$k; 120 | } 121 | } 122 | unset($j); 123 | if ($w === $length_arr_last) { 124 | for ($j=$s; $j < $length_arr; $j++) { 125 | $arr_tmp[$k] = $value[$i][$j]; 126 | ++$k; 127 | } 128 | } 129 | unset($j); 130 | $arr[floor($i/2)] = $arr_tmp; 131 | continue; 132 | } 133 | $arr[floor($i/2)] = $value[$i]; 134 | continue; 135 | } 136 | } 137 | } 138 | $value = $arr; 139 | merge($value); 140 | 141 | return $value[0]; 142 | } 143 | 144 | 145 | /* ----------------- 归并写法二 ------------------ */ 146 | 147 | $mergeFirst = function ($arr=array()) 148 | { 149 | $len = count($arr); 150 | $res = []; 151 | for ($i = 0; $i < $len; $i += 2) { 152 | $j = floor($i/2); 153 | if (!isset($arr[$i + 1])) { 154 | $res[$j][] = $arr[$i]; 155 | continue; 156 | } 157 | if ($arr[$i] < $arr[$i + 1]) { 158 | $res[$j][] = $arr[$i]; 159 | $res[$j][] = $arr[$i + 1]; 160 | continue; 161 | } 162 | $res[$j][] = $arr[$i + 1]; 163 | $res[$j][] = $arr[$i]; 164 | } 165 | return $res; 166 | }; 167 | 168 | $mergeArray = function ($arr1, $arr2) 169 | { 170 | $len1 = count($arr1); 171 | $len2 = count($arr2); 172 | $arr3 = []; 173 | $a = 0; 174 | $b = 0; 175 | $k = 0; 176 | while ($a < $len1 && $b < $len2) { 177 | if ($arr1[$a] < $arr2[$b]) { 178 | $arr3[$k] = $arr1[$a]; 179 | $a++; 180 | $k++; 181 | continue; 182 | } 183 | $arr3[$k] = $arr2[$b]; 184 | $b++; 185 | $k++; 186 | } 187 | if ($a === $len1) { 188 | for ($i = $b; $i < $len2; $i++) { 189 | $arr3[] = $arr2[$i]; 190 | } 191 | } 192 | unset($i); 193 | if ($b === $len2) { 194 | for ($i = $a; $i < $len1; $i++) { 195 | $arr3[] = $arr1[$i]; 196 | } 197 | } 198 | return $arr3; 199 | }; 200 | 201 | function sorta($arr=array(), $mergeFirst, $mergeArray) 202 | { 203 | if (count($arr) === 1) { 204 | return $arr[0]; 205 | } 206 | if (!is_array($arr[0])) { 207 | $arr = $mergeFirst($arr); 208 | } 209 | $len = count($arr); 210 | $arrNew = []; 211 | for ($i=0; $i < $len; $i += 2) { 212 | $j = floor($i/2); 213 | if (!isset($arr[$i + 1])) { 214 | $arrNew[$j] = $arr[$i]; 215 | continue; 216 | } 217 | $arrNew[$j] = $mergeArray($arr[$i], $arr[$i+1]); 218 | } 219 | 220 | $res = sorta($arrNew, $mergeFirst, $mergeArray); 221 | 222 | return $res; 223 | } 224 | -------------------------------------------------------------------------------- /algorithm/sort/quick.php: -------------------------------------------------------------------------------- 1 | 8 | */ 9 | 10 | /** 11 | * 快速排序. 12 | * 13 | * @param array $value 待排序数组 14 | * @param array $left 左边界 15 | * @param array $right 右边界 16 | * 17 | * @return array 18 | */ 19 | function quick(&$value, $left, $right) 20 | { 21 | // 左右界重合 跳出 22 | if ($left >= $right) { 23 | return; 24 | } 25 | $base = $left; 26 | do { 27 | // 从最右边开始找到第一个比基准小的值,互换位置 28 | // 找到基准索引为止 29 | for ($i=$right; $i > $base; --$i) { 30 | if ($value[$i] < $value[$base]) { 31 | $tmp = $value[$i]; 32 | $value[$i] = $value[$base]; 33 | $value[$base] = $tmp; 34 | $base = $i; // 更新基准值索引 35 | break; 36 | } 37 | } 38 | 39 | // 从最左边开始找到第一个比基准大的值,互换位置 40 | // 找到基准索引为止 41 | for ($j=$left; $j < $base; ++$j) { 42 | if ($value[$j] > $value[$base]) { 43 | $tmp = $value[$j]; 44 | $value[$j] = $value[$base]; 45 | $value[$base] = $tmp; 46 | $base = $j; // 更新基准值索引 47 | break; 48 | } 49 | } 50 | } while ($i > $j);// 直到左右索引重合为止 51 | 52 | // 开始递归 53 | // 以当前索引为分界 54 | // 开始排序左部分 55 | quick($value, $left, $i-1); 56 | // 开始排序右边部分 57 | quick($value, $i+1, $right); 58 | 59 | return $value; 60 | } 61 | 62 | /** 63 | * 快速排序.while版本 64 | * 65 | * @param array $value 待排序数组 66 | * @param array $left 左边界 67 | * @param array $right 右边界 68 | * 69 | * @return array 70 | */ 71 | function quick_while(&$value, $left, $right) 72 | { 73 | // 左右界重合 跳出 74 | if ($left >= $right) { 75 | return; 76 | } 77 | 78 | $point = $left; 79 | $i = $right; 80 | $j = $left; 81 | while ($i > $j) { 82 | //查右边值 83 | while ($i > $point) { 84 | if ($value[$i] < $value[$point]) { 85 | $tmp = $value[$i]; 86 | $value[$i] = $value[$point]; 87 | $value[$point] = $tmp; 88 | $point = $i; 89 | break; 90 | } 91 | --$i; 92 | } 93 | 94 | //查左边值 95 | while ($j < $point) { 96 | if ($value[$j] > $value[$point]) { 97 | $tmp = $value[$j]; 98 | $value[$j] = $value[$point]; 99 | $value[$point] = $tmp; 100 | $point = $j; 101 | break; 102 | } 103 | ++$j; 104 | } 105 | } 106 | 107 | // 开始递归 108 | // 以当前索引为分界 109 | // 开始排序左部分 110 | quick_while($value, $left, $i-1); 111 | // 开始排序右边部分 112 | quick_while($value, $i+1, $right); 113 | 114 | return $value; 115 | } 116 | -------------------------------------------------------------------------------- /algorithm/sort/radix.php: -------------------------------------------------------------------------------- 1 | 18 | */ 19 | 20 | /** 21 | * 基数排序 22 | * 23 | * Least Significant Digit first 24 | * 25 | * 最低位优先排序 26 | * 27 | * @param array $value 待排序数组 28 | * 29 | * @return array 30 | */ 31 | function radix_lsd(&$value = []) 32 | { 33 | // 获取序列值最大位数 34 | $max = 0; 35 | foreach ($value as $v) { 36 | $length = strlen((string)$v); 37 | if ($length > $max) { 38 | $max = $length;// 更新 39 | } 40 | } 41 | unset($v); 42 | $splice = 1;// 取最小位 初始从右往左数第一位 43 | 44 | while ($splice <= $max) { 45 | // 分配数字到桶中 46 | for ($i=0; $i < 10; $i++) { 47 | foreach ($value as $k => $v) { 48 | $length = strlen((string)$v); 49 | // 当前位索引位置 50 | $index = $length-$splice; 51 | // 不存在该位 则认为为0 52 | if ($index < 0) { 53 | if ($i === 0) { 54 | $arr[0][] = $v; 55 | } 56 | continue; 57 | } 58 | $aaa = ((string)$v)[$index]; 59 | if (((string)$v)[$index] === (string)$i) { 60 | $arr[$i][] = $v; 61 | } 62 | } 63 | unset($v); 64 | } 65 | // 合并桶中数字 66 | unset($value); 67 | foreach ($arr as $tmp) { 68 | foreach ($tmp as $v) { 69 | $value[] = $v; 70 | } 71 | } 72 | unset($tmp); 73 | unset($v); 74 | unset($arr); 75 | ++$splice; 76 | } 77 | return $value; 78 | } 79 | 80 | /** 81 | * 基数排序 82 | * 83 | * Most Significant Digit first 84 | * 85 | * 最高位优先排序 86 | * 87 | * @param array $value 待排序数组 88 | * @param integer $max 序列最大位数 89 | * 90 | * @return array 91 | */ 92 | function radix_msd(&$value = [], $max=0, $max_origin=0, $length_origin=0, &$origin=[], $key=0) 93 | { 94 | if ($max < 1) { 95 | return; 96 | } 97 | 98 | // 按最高位分组,不存在当前位则认为0 99 | $arr = []; 100 | for ($i=0; $i < 10; $i++) { 101 | foreach ($value as $v) { 102 | $length = strlen((string)$v); 103 | $index = $length - $max; 104 | if ($index < 0) { 105 | if ($i === 0) { 106 | $arr[0][] = $v; 107 | } 108 | continue; 109 | } 110 | if (((string)$v)[$index] === (string)$i) { 111 | $arr[$i][] = $v; 112 | } 113 | } 114 | unset($v); 115 | } 116 | unset($i); 117 | --$max; 118 | 119 | if (!empty($origin)) { 120 | $origin[$key] = $arr; 121 | }else{ 122 | $value = $arr; 123 | } 124 | foreach ($value as $k => &$v) { 125 | radix_msd($v, $max, $max_origin, $length_origin, $value, $k); 126 | } 127 | 128 | if ($max < $max_origin-1) { 129 | return; 130 | } 131 | 132 | // 重新拼接 133 | return get_value($value, $length_origin); 134 | } 135 | 136 | /** 137 | * 合并排序 138 | * 139 | * 合并最后按个位排序完成的值 140 | * 141 | * @param [type] $value 排序后值 142 | * @param integer $length 原始数组长度 143 | * @param array $result 存放排序后数的新空间 144 | * @return array 排序后数组 145 | */ 146 | function get_value($value=[], $length=0, &$result=[]) 147 | { 148 | if (count($result) === $length) { 149 | return; 150 | } 151 | foreach ($value as $k => $v) { 152 | if (is_array($v)) { 153 | get_value($v, $length, $result); 154 | continue; 155 | } 156 | $result[] = $v; 157 | } 158 | return $result; 159 | } 160 | -------------------------------------------------------------------------------- /algorithm/sort/select.php: -------------------------------------------------------------------------------- 1 | 8 | */ 9 | 10 | /** 11 | * 选择排序. 12 | * 13 | * @param array $value 待排序数组 14 | * 15 | * @return array 16 | */ 17 | function select_sort(&$value=[]) 18 | { 19 | $length = count($value)-1; 20 | for ($i=0; $i < $length; $i++) { 21 | $point = $i;// 最小值索引 22 | for ($j=$i+1; $j <= $length; $j++) { 23 | if ($value[$point] > $value[$j]) { 24 | $point = $j; 25 | } 26 | } 27 | $tmp = $value[$i]; 28 | $value[$i] = $value[$point]; 29 | $value[$point] = $tmp; 30 | } 31 | return $value; 32 | } 33 | -------------------------------------------------------------------------------- /algorithm/sort/shell.php: -------------------------------------------------------------------------------- 1 | 10 | */ 11 | 12 | /** 13 | * 希尔排序. 14 | * 15 | * 算法思路: 16 | * 给定一个初始步长,一般为序列长度的一半 17 | * 按步长分组 18 | * 每组进行插入排序 19 | * 取当前步长的一半为下个步长,继续上面的算法 20 | * 直到步长为1结束 21 | * 22 | * @param array $value 待排序数组 23 | * @param array $increment 步长 初始数组长度向下取整 24 | * 25 | * @return array 26 | */ 27 | function shell(&$value = [], $increment) 28 | { 29 | // 步长小于1为止 30 | if ($increment<1) { 31 | return; 32 | } 33 | // 分组插入排序 34 | // 循环步长次 35 | $a = 0; 36 | while ($a < $increment) { 37 | // 每组进行插入排序 38 | // 直到待插入值不存在为止 39 | $point = $a; // 已排序末尾初始位置 40 | while (isset($value[$point+$increment])) { 41 | $next = $value[$point + $increment]; // 待插入值 42 | // 插入逻辑 43 | for ($i=$point; $i >= $a; $i -= $increment) { 44 | // 当前值大于待插入值 则后移步长当前值 45 | if ($value[$i] > $next) { 46 | $value[$i+$increment] = $value[$i]; 47 | // 如果当前为首位索引位置 则当前位置插入待插入值 48 | if ($i === $a) { 49 | $value[$i] = $next; 50 | } 51 | continue; 52 | } 53 | // 当前值小于或者等于待插入值 则在上一个步长位置插入待插入值 54 | $value[$i+$increment] = $next; 55 | break; 56 | } 57 | $point += $increment; 58 | } 59 | ++$a; 60 | } 61 | // 递归 62 | shell($value, floor($increment/2)); 63 | return $value; 64 | } 65 | -------------------------------------------------------------------------------- /algorithm/test.php: -------------------------------------------------------------------------------- 1 | 6 | * @example php test.php 7 | */ 8 | 9 | // 初始值 10 | $data = [11, 67, 3, 121, 71, 6, 100, 45, 2, 19, 17, 99, 40, 3, 22]; 11 | 12 | 13 | // 参数 14 | $method = ''; 15 | if (isset($argv[1])) { 16 | $method = $argv[1]; 17 | } 18 | $path = dirname($_SERVER['SCRIPT_FILENAME']); 19 | 20 | /*---------------------------- bubble ---------------------------------*/ 21 | 22 | if ($method === 'bubble') { 23 | require($path . '/sort/bubble.php'); 24 | echo "\n"; 25 | echo "==========================冒泡排序========================= \n"; 26 | echo "\n"; 27 | print_r($data); 28 | echo "\n"; 29 | echo "=========上为初始值==================下为排序后值============= \n"; 30 | echo "\n"; 31 | // run 32 | print_r(bubble($data)); 33 | die; 34 | } 35 | 36 | 37 | /*---------------------------- bubble better ---------------------------------*/ 38 | 39 | if ($method === 'bubble-better') { 40 | require($path . '/sort/bubble.php'); 41 | echo "\n"; 42 | echo "==========================优化冒泡排序========================= \n"; 43 | echo "\n"; 44 | print_r($data); 45 | echo "\n"; 46 | echo "=========上为初始值=====================下为排序后值============= \n"; 47 | echo "\n"; 48 | // run 49 | print_r(bubble_better($data)); 50 | die; 51 | } 52 | 53 | 54 | /*---------------------------- quick ---------------------------------*/ 55 | 56 | if ($method === 'quick') { 57 | require($path . '/sort/quick.php'); 58 | echo "\n"; 59 | echo "==========================快速排序========================= \n"; 60 | echo "\n"; 61 | print_r($data); 62 | echo "\n"; 63 | echo "=========上为初始值==================下为排序后值============= \n"; 64 | echo "\n"; 65 | // run 66 | print_r(quick($data, 0, count($data) - 1)); 67 | die; 68 | } 69 | 70 | 71 | /*---------------------------- quick while版本 ---------------------------------*/ 72 | 73 | if ($method === 'quick-while') { 74 | require($path . '/sort/quick.php'); 75 | echo "\n"; 76 | echo "==========================快排while版========================= \n"; 77 | echo "\n"; 78 | print_r($data); 79 | echo "\n"; 80 | echo "=========上为初始值==================下为排序后值============= \n"; 81 | echo "\n"; 82 | // run 83 | print_r(quick_while($data, 0, count($data) - 1)); 84 | die; 85 | } 86 | 87 | 88 | /*---------------------------- select ---------------------------------*/ 89 | 90 | if ($method === 'select') { 91 | require($path . '/sort/select.php'); 92 | echo "\n"; 93 | echo "==========================选择排序========================= \n"; 94 | echo "\n"; 95 | print_r($data); 96 | echo "\n"; 97 | echo "=========上为初始值==================下为排序后值============= \n"; 98 | echo "\n"; 99 | // run 100 | print_r(select_sort($data)); 101 | die; 102 | } 103 | 104 | 105 | /*---------------------------- insert ---------------------------------*/ 106 | 107 | if ($method === 'insert') { 108 | require($path . '/sort/insert.php'); 109 | echo "\n"; 110 | echo "==========================插入排序========================= \n"; 111 | echo "\n"; 112 | print_r($data); 113 | echo "\n"; 114 | echo "=========上为初始值==================下为排序后值============= \n"; 115 | echo "\n"; 116 | // run 117 | print_r(insert($data, 0)); 118 | die; 119 | } 120 | 121 | 122 | /*---------------------------- merge_array ---------------------------------*/ 123 | 124 | if ($method === 'merge-array') { 125 | require($path . '/sort/merge.php'); 126 | echo "\n"; 127 | echo "================合并两个有序数组为一个有序数组================== \n"; 128 | echo "\n"; 129 | print_r([ 130 | [1, 13, 22, 39], 131 | [2, 3, 6, 10, 16, 32, 66, 88, 99] 132 | ]); 133 | echo "\n"; 134 | echo "=========上为初始值==================下为排序后值============= \n"; 135 | echo "\n"; 136 | // run 137 | print_r(merge_array( 138 | [1, 13, 22, 39], 139 | [2, 3, 6, 10, 16, 32, 66, 88, 99] 140 | )); 141 | die; 142 | } 143 | 144 | 145 | /*---------------------------- merge ---------------------------------*/ 146 | 147 | if ($method === 'merge') { 148 | require($path . '/sort/merge.php'); 149 | echo "\n"; 150 | echo "==========================归并排序========================= \n"; 151 | echo "看归并排序前,建议先看一下怎么合并两个有序数组为一个有序数据的逻辑 \n"; 152 | echo "执行 php test.php merge-array \n"; 153 | echo "\n"; 154 | print_r($data); 155 | echo "\n"; 156 | echo "=========上为初始值==================下为排序后值============= \n"; 157 | echo "\n"; 158 | // run 159 | print_r(merge($data, true)); 160 | die; 161 | } 162 | 163 | /*---------------------------- heap ---------------------------------*/ 164 | 165 | if ($method === 'heap') { 166 | require($path . '/sort/heap.php'); 167 | echo "\n"; 168 | echo "==========================堆排序========================= \n"; 169 | echo "\n"; 170 | print_r($data); 171 | echo "\n"; 172 | echo "=========上为初始值==================下为排序后值============= \n"; 173 | echo "\n"; 174 | // run 175 | print_r(heap($data)); 176 | die; 177 | } 178 | 179 | /*---------------------------- shell ---------------------------------*/ 180 | 181 | if ($method === 'shell') { 182 | require($path . '/sort/shell.php'); 183 | echo "\n"; 184 | echo "==========================希尔排序========================= \n"; 185 | echo "\n"; 186 | print_r($data); 187 | echo "\n"; 188 | echo "=========上为初始值==================下为排序后值============= \n"; 189 | echo "\n"; 190 | // run 191 | print_r(shell($data, floor(count($data)/2))); 192 | die; 193 | } 194 | 195 | /*---------------------------- radix lsd ---------------------------------*/ 196 | 197 | if ($method === 'radix-lsd') { 198 | require($path . '/sort/radix.php'); 199 | echo "\n"; 200 | echo "======================基数排序 最低位优先==================== \n"; 201 | echo "\n"; 202 | print_r($data); 203 | echo "\n"; 204 | echo "=========上为初始值==================下为排序后值============= \n"; 205 | echo "\n"; 206 | // run 207 | print_r(radix_lsd($data)); 208 | die; 209 | } 210 | 211 | /*---------------------------- radix msd ---------------------------------*/ 212 | 213 | if ($method === 'radix-msd') { 214 | require($path . '/sort/radix.php'); 215 | echo "\n"; 216 | echo "======================基数排序 最高位优先==================== \n"; 217 | echo "\n"; 218 | print_r($data); 219 | echo "\n"; 220 | echo "=========上为初始值==================下为排序后值============= \n"; 221 | echo "\n"; 222 | // run 223 | // 获取序列值最大位数 224 | $max = 0; 225 | foreach ($data as $v) { 226 | $length = strlen((string)$v); 227 | if ($length > $max) { 228 | $max = $length;// 更新 229 | } 230 | } 231 | unset($v); 232 | print_r(radix_msd($data, $max, $max, count($data))); 233 | die; 234 | } 235 | 236 | /*---------------------------- fibonacci ---------------------------------*/ 237 | 238 | if ($method === 'fibonacci') { 239 | require($path . '/fibonacci.php'); 240 | echo "\n"; 241 | echo "======================生成斐波拉耶数列==================== \n"; 242 | echo "\n"; 243 | print_r(recursion(16)); 244 | die; 245 | } 246 | 247 | /*---------------------------- warning ---------------------------------*/ 248 | 249 | echo "\n"; 250 | echo "参数有误,正确示例:php {$path}/test.php bubble \n"; 251 | echo "====================================== \n"; 252 | echo "参数列表: \n"; 253 | print_r([ 254 | '冒泡排序' => 'bubble', 255 | '冒泡排序优化版' => 'bubble-better', 256 | '快速排序' => 'quick', 257 | '快速排序while版' => 'quick-while', 258 | '选择排序' => 'select', 259 | '插入排序' => 'insert', 260 | '合并有序数组' => 'merge-array', 261 | '归并排序' => 'merge', 262 | '希尔排序' => 'shell', 263 | '基数排序LSD' => 'radix-lsd', 264 | '基数排序MSD' => 'radix-msd', 265 | '堆排序' => 'heap', 266 | '斐波纳耶数列' => 'fibonacci', 267 | // '计数排序' => 'count', 268 | // '桶排序' => 'bucket', 269 | // '二分查找' => 'binary-search' 270 | ]); 271 | -------------------------------------------------------------------------------- /data-structure/data-structure.md: -------------------------------------------------------------------------------- 1 | # 常用数据结构 2 | 3 | -------------------------------------------------------------------------------- 4 | 5 | ## 树(Tree) 6 | 7 | - 概念:树是n(n>=0)个节点的有限集T,T为空时称为空树,否则他满足如下两个条件: 8 | 9 | - 有且仅有一个特定的根(root)节点 10 | - 其余的节点可以分为m(m>=0)个互不相交的子集T1,T2,T3...Tm,其中每个子集本身又是一棵树,称之为子树(SubTree) 11 | 12 | - 特性:一棵非空树是由若干棵子树构成的,而子树又可由若干棵更小的子树构成。而这里的子树可以是叶子也可以是分支 13 | 14 | - 二叉树: 就是每个节点最多有两个子树的树结构 15 | 16 | - 满二叉树:除最后一层无子节点,每一层的所有节点都有两个子节点 17 | - 完全二叉树:只有最下面的两层子节点能小于2,且最下面一层只能空缺右边节点 18 | 19 | ## 链表 20 | 21 | - 链表由一系列结点组成,每个结点包含两部分:一是储存数据元素的数据域,二是储存下一个结点地址的指针域 22 | 23 | ## 数组 24 | 25 | - 概念:元素按序排列的集合 26 | 27 | ## 堆/栈 28 | 29 | - 堆:树形数据结构 30 | - 栈:先进后出特殊线性表 31 | 32 | ## 队列 33 | 34 | -概念:表尾插入并表头删除的先进先出的特殊线性表 35 | 36 | ## 图 37 | 38 | ## 散列表 39 | -------------------------------------------------------------------------------- /linux/command.md: -------------------------------------------------------------------------------- 1 | ### linux 常用命令 2 | 3 | 1. 切换目录:cd [目录] 4 | 2. 查看当前目录文件:ls -a[查看所有文件包括隐藏]/-l[查看文件显示权限和所属] 5 | 3. 查看当前所在路径: pwd 6 | 4. 复制文件或者文件夹:cp [filename/-r folder] 7 | 5. 远程复制文件或者文件夹: 8 | - 复制本地到远程: scp [-r] local_path username@ip:path 9 | - 复制远程到本地: scp [-r] username@ip:path local_path 10 | 6. 移动或重命名文件或文件夹: mv [file/folder] 11 | 7. 创建文件夹: mkdir [folder_name]; 12 | 8. 变更文件或文件夹权限:chmod [-R:遍历文件夹下所有文件] [权限] [file/folder] 13 | - 解释: 例如权限为777 代表 user/group/other 的权限为 4+2+1/4+2+1/4+2+1, 14 | 4代表read读权限, 2代表写权限, 1代表执行权限 15 | - drwxr--r--中的第一位: d代表文件夹,s代表socket文件,-代表普通文件,l代表软链 16 | 9. 变更文件所属用户或用户组: chown owner:group [file/folder] 17 | 10. 新建文件: 18 | - touch [filename] 19 | - vi/vim [filename] 20 | 11. 查看文件: 21 | - 输出文件内容:cat [filename] 22 | - tail [-f:实时输出文件内容] [filename] 23 | - less 24 | 12. 查找内容: 25 | - grep [正则] 26 | - awk 27 | 13. 建立软链: ln -s [realpath/filename] [realpath] 28 | 14. 查看包含所有用户的进程:ps -aux 29 | 15. 查看端口: netstat -anp 30 | - a代表:显示所有,默认不显示LISTEN的 31 | - n代表:不显示数字别名 32 | - p代表:显示关联的程序 33 | 16. 压缩 34 | - 解压缩:tar -zxvf [filename] 35 | - 压缩:tar -zcvf [filename] 36 | 17. 查看当前命令所在的路径: which 37 | 18. 查看当前用户 38 | - who 39 | - whoami 40 | 19. 查看当前系统运行多长时间:uptime 41 | 20. 可读性好的查看磁盘空间:df -h 42 | 21. 可读性好的查看文件空间:du -f --max-depth=[遍历文件夹的深度] [file/folder] 43 | 22. debian添加软件源:apt-add-repository [源] 44 | 23. 查找文件: 45 | - find [path] -name [filename] 46 | - find [path] -user [owername] 47 | - find [path] -group [groupname] 48 | 24. 删除文件或者文件夹: rm [-r] [file/folder] 49 | 25. 进程: 50 | - 杀掉进程:kill [pid] 51 | - 查看进程 52 | * 查看:ps -aux 53 | * 查看父进程ID(ppid):ps -ef 54 | 26. 关机/重启 55 | - 关机:shutdown -h now 56 | - 关机: init 0 57 | - 关机: halt 58 | - 关机: poweroff 59 | - 重启: shutdown -r now reboot 60 | 61 | 27. 我的常用tmux系列命令 62 | 63 | ``` 64 | 新建一个会话: 65 | tmux new -s <会话名称> 66 | 切到一个会话: 67 | tmux at -t <会话名称> 68 | 删除一个会话: 69 | tmux kill-session -t <会话名称> 70 | 获取会话列表: 71 | tmux list 72 | 临时切换一个窗口到最大或最小: 73 | prefix z 74 | 推出tmux但是保存会话: 75 | prefix d 76 | 创建一个窗口: 77 | prefix c 78 | 垂直拆分一个窗口: 79 | prefix % 80 | 水平拆分一个窗口: 81 | prefix " 82 | ``` 83 | 84 | 28. logrotate 85 | 86 | 增加配置/etc/logrotate.d: 87 | 88 | nginx示例文件 89 | ``` 90 | /var/log/nginx/*.log { 91 | # 打包日志频率 daily:每天 weekly:每周 monthly:每月 92 | daily 93 | # 打包文件添加日期后缀 94 | dateext 95 | # 找不到日志也ok 96 | missingok 97 | # 保存14份日志 98 | rotate 14 99 | # 压缩日志 默认gzip 100 | compress 101 | # 延时压缩到下次rotate 102 | delaycompress 103 | # 忽略空日志 104 | notifempty 105 | # ? 106 | create 0640 www-data adm 107 | # 执行完所有rotate再执行脚本 108 | sharedscripts 109 | # ? 110 | prerotate 111 | if [ -d /etc/logrotate.d/httpd-prerotate ]; then \ 112 | run-parts /etc/logrotate.d/httpd-prerotate; \ 113 | fi \ 114 | endscript 115 | # ? 116 | postrotate 117 | invoke-rc.d nginx rotate >/dev/null 2>&1 118 | endscript 119 | } 120 | ``` 121 | 122 | #### 强制执行: 123 | logrotate -f /etc/logrotate.d/nginx 124 | 125 | 126 | #### 附录:shell 判断文件 127 | ``` 128 | -e 文件名 如果文件存在则为真 129 | -d 文件名 如果文件存在且为目录则为真 130 | ``` 131 | 132 | 29. supervisor 133 | 134 | #### 安装 debian: 135 | sudo apt-get install supervisor 136 | 137 | #### 增加配置文件: 138 | cd /etc/supervisor/conf.d 139 | 140 | #### 配置文件示例: 141 | ``` 142 | [program:demo] 143 | # ? 144 | directory = yourpath 145 | # 启动进程的命令 146 | command = yourcommand 147 | # 启动supervisor时启动 148 | autostart = true 149 | # 进程exit自动重启 150 | autorestart = true 151 | # 执行命令的用户 152 | user = www-data 153 | # 日志路径 154 | stdout_logfile = /var/log/supervisor/demo.log 155 | # 这个no意思是启动例如nginx或者php-fpm时,由supervior接管守护 156 | daemonize = no 157 | ``` 158 | 159 | #### 启动或重启supervisor 160 | sudo service supervisor start 161 | sudo service supervisor restart 162 | 163 | #### 启动我们的进程 164 | sudo supervisorctl start demo 165 | 166 | 28. 查找文件位置 167 | whereis 文件名 168 | -------------------------------------------------------------------------------- /mysql/index.md: -------------------------------------------------------------------------------- 1 | ### 索引 2 | - 分析查询:通过这个查询可以分析查询语句的索引使用情况 3 | 4 | ``` 5 | explain select * from xxx where id = xxx 6 | ``` 7 | -------------------------------------------------------------------------------- /mysql/lock.md: -------------------------------------------------------------------------------- 1 | ### 锁 2 | - 乐观锁: 3 | update table table_name 4 | set column_name = value, version=version+1 5 | and 6 | where version = version; 7 | - 悲观锁:update table table_name set column_name = value for update; 8 | - 共享锁:x锁 9 | 10 | - 脏读:一个事务内修改了数据,另一个事务读取并使用了这个数据; 11 | - 幻读:一个事务内修改了涉及全表的数据,另一个事务往这个表里面插入了新的数据,第一个事务出现幻读; 12 | - 不可重复读:一个事务内连续读了两次数据,中间另一个事务修改了这个数据,导致第一个事务前后两次读的数据不一致; 13 | - 更新丢失:一个事务内变更了数据,另一个事务修改了这个数据,最后前一个事务commit导致另一个事务的变更丢失; 14 | 15 | 16 | ### 索引 17 | 18 | - 主键唯一索引 19 | - 唯一索引 20 | - 普通索引 21 | - 联合索引 22 | - 聚簇索引 23 | - 非聚簇索引 24 | -------------------------------------------------------------------------------- /mysql/sql.md: -------------------------------------------------------------------------------- 1 | ## 常用sql语句整理:mysql 2 | 3 | 4 | 1. 增 5 | 6 | - 增加一张表 7 | ``` 8 | CREATE TABLE `table_name`( 9 | ... 10 | )ENGINE=InnoDB DEFAULT CHARSET=utf8; 11 | ``` 12 | 13 | - 增加记录 14 | ``` 15 | INSERT INTO `your_table_name`(`column_name`) 16 | VALUES 17 | ('your_value_one'), 18 | ('your_value_two'); 19 | ``` 20 | 21 | - 增加字段 22 | ``` 23 | ALTER TABLE `your_table_name` 24 | ADD `your_column_name` ... 25 | AFTER `column_name`; 26 | ``` 27 | 28 | - 增加索引 29 | + 主键 30 | ``` 31 | ALTER TABLE `your_table_name` 32 | ADD PRIMARY KEY your_index_name(your_column_name); 33 | ``` 34 | + 唯一索引 35 | ``` 36 | ALTER TABLE `your_table_name` 37 | ADD UNIQUE your_index_name(your_column_name); 38 | ``` 39 | + 普通索引 40 | ``` 41 | ALTER TABLE `your_table_name` 42 | ADD INDEX your_index_name(your_column_name); 43 | ``` 44 | + 全文索引 45 | ``` 46 | ALTER TABLE `your_table_name` 47 | ADD FULLTEXT your_index_name(your_column_name); 48 | ``` 49 | 50 | 51 | 2. 删 52 | 53 | - 逐行删除 54 | ``` 55 | DELETE FORM `table_name` 56 | WHERE ...; 57 | ``` 58 | 59 | - 清空整张表 60 | ``` 61 | TRUNCATE TABLE `your_table_name`; 62 | ``` 63 | 64 | - 删除表 65 | ``` 66 | DROP TABLE `your_table_name`; 67 | ``` 68 | 69 | - 删除字段 70 | ``` 71 | ALTER TABLE `your_table_name` 72 | DROP `column_name`; 73 | ``` 74 | 75 | - 删除索引 76 | ``` 77 | ALTER TABLE `your_table_name` 78 | DROP INDEX your_index_name(your_column_name); 79 | ``` 80 | 81 | 82 | 3. 改 83 | 84 | - 变更数据 85 | ``` 86 | UPDATE `table_name` 87 | SET column_name=your_value 88 | WHERE ...; 89 | ``` 90 | 91 | - 变更字段 92 | ``` 93 | ALTER TABLE `your_table_name` 94 | CHANGE `your_column_name` `your_column_name` ...(变更); 95 | ``` 96 | 97 | - 变更字段值为另一张表的某个值 98 | ``` 99 | UPDATE `your_table_name` 100 | AS a 101 | JOIN `your_anther_table_name` 102 | AS b 103 | SET a.column = b.anther_column 104 | WHERE a.id = b.a_id...; 105 | ``` 106 | 107 | 4. 查 108 | 109 | 110 | - 普通查询 111 | ``` 112 | SELECT `column_name_one`, `column_name_two` 113 | FROM `table_name`; 114 | ``` 115 | 116 | - 关联查询 117 | ``` 118 | SELECT * 119 | FROM `your_table_name` 120 | AS a 121 | JOIN `your_anther_table_name` 122 | AS b 123 | WHERE a.column_name = b.column_name...; 124 | ``` 125 | 126 | - 合计函数条件查询:WHERE 关键字无法与合计函数一起使用 127 | ``` 128 | SELECT aggregate_function(column_name) 129 | FROM your_table_name 130 | GROUP BY column_name 131 | HAVING aggregate_function(column_name)...; 132 | ``` 133 | 134 | - 同一个实例下跨库查询 135 | ``` 136 | SELECT * 137 | FROM database_name.your_table_name 138 | AS a 139 | JOIN another_database_name.your_another_table_name 140 | AS b 141 | WHERE a.column_name = b.column_name...; 142 | ``` 143 | 144 | 5. 复制一张表结构 145 | ``` 146 | CREATE TABLE `your_table_name` 147 | LIKE `destination_table_name`; 148 | ``` 149 | 150 | 6. 完全复制一张表:表结构+全部数据 151 | ``` 152 | CREATE TABLE `your_table_name` 153 | LIKE `destination_table_name`; 154 | 155 | INSERT INTO `your_table_name` 156 | SELECT * 157 | FROM `destination_table_name`; 158 | ``` 159 | 160 | --- 161 | 162 | ### 附录:mysql常用命令 163 | - 登陆: mysql -h host -u username -p 164 | - 列出数据库:SHOW DATABESES; 165 | - 列出表:SHOW TABLES; 166 | - 列出表结构:DESC table_name 167 | - 使用一个数据库:USE database_name; 168 | - 导入:source 'file'; 169 | - 导出:mysqldump -h 127.0.0.1 -u root -p "database_name" "table_name" --where="condition" > file_name.sql; 170 | - 查看慢日志:mysqldumpslow -s [c:按记录次数排序/t:时间/l:锁定时间/r:返回的记录数] -t [n:前n条数据] -g "正则" /path 171 | - 新增用户: insert into `user`(`Host`, `User`, `authentication_string`) value('localhost', 'username', password('pwd')) 172 | 173 | ### mysql 5.7 新增用户 174 | 175 | ``` 176 | // 插入新用户 177 | insert into mysql.user(Host, User, authentication_string, ssl_cipher, x509_issuer, x509_subject 178 | value('localhost', 'username', password('password'), '', '', ''); 179 | 180 | // 数据库授权 181 | grant all privileges on dbname.name.* to username@localhost identified by 'password'; 182 | 183 | // 刷新权限信息 184 | FLUSH PRIVILEGES; 185 | ``` 186 | -------------------------------------------------------------------------------- /network/http.md: -------------------------------------------------------------------------------- 1 | ## 概念 2 | 3 | Hypertext Transfer Protocol, 超文本传输(转移)协议,是客户端和服务端传输文本制定的协议。构建WWW的具体的三项技术如下: 4 | 5 | WWW: world wide web, 万维网 6 | 7 | - HTML: Hypertext Markup Language, 超文本标记语言 8 | - HTTP: Hypertext Transfer Protocol, 超文本传输(转移)协议 (HTTP是TCP/IP的应用层协议) 9 | - URL: Uniform Resource Locator, 统一资源定位符号 10 | 11 | > URI: Uniform Resource Identitier, 统一资源标示符号,URL是URI的子集 12 | 13 | ## TCP/IP 14 | 15 | ``` 16 | 应用层(http/https/websocket/ftp...) => 定义:文本传输协议 17 | | 18 | 传输层(tcp/udp) => 定义:端口 19 | | 20 | 网络层(ip) => 定义:IP 21 | | 22 | 链路层(mac&数据包) => 定义:数据包,MAC地址 23 | | 24 | 实体层(光缆/电缆/交换机/路由/终端...) => 定义:物理 25 | ``` 26 | 27 | TCP/IP: 28 | 29 | - 解释一:分别代表tcp协议和ip协议 30 | - 解释二:如果按照网络五层架构,TCP/IP代表除了应用层其他层所有协议簇的统称 31 | 32 | TCP/IP connect: TCP/IP的三次握手: 33 | ``` 34 | 标有syn的数据包 35 | -------------> 36 | 标有syn/ack的数据包 37 | client <------------- server 38 | 标有ack的数据包 39 | --------------> 40 | ``` 41 | 42 | TCP/IP finish: TCP/IP的四次握手: 43 | ``` 44 | fin 45 | <------------- 46 | ack 47 | client(或server) -------------> server(或client) 48 | fin 49 | -------------> 50 | ack 51 | <------------- 52 | ``` 53 | 54 | ## HTTP 报文 55 | 56 | HTTP 报文由三部分组成: 57 | - Start Line 58 | - Headers 59 | - Entity Body 60 | 61 | HTTP 报文分为两类: 62 | - 请求报文 63 | - 响应报文 64 | 65 | ### 请求报文Start Line 66 | 67 | 语法 : <方法> <请求URL> <版本> 68 | 69 | #### HTTP Method 70 | 71 | + get: 获取资源,不携带http body,支持查询参数,大小2KB 72 | + post: 传输资源,http body, 大小默认8M,1000个input variable 73 | + put: 传输资源,http body,资源更新 74 | + delete: 删除资源,不携带http body 75 | + patch: 传输资源,http body,存在的资源局部更新 76 | + head: 获取http header,不携带http body 77 | + options: 获取支持的method,不携带http body 78 | + trace: 追踪,返回请求回环信息,不携带http body 79 | + connect: 建立隧道通信 80 | 81 | ### 响应报文Start Line 82 | 83 | 语法 : <方法> <状态码> <原因短语> 84 | 85 | #### HTTP Status Code 86 | 87 | + 200: ok 88 | + 301: 永久重定向 89 | + 302: 临时重定向 90 | + 303: 临时重定向,要求用get请求资源 91 | + 304: not modified, 返回缓存,和重定向无关 92 | + 307: 临时重定向,严格不从post到get 93 | + 400: 参数错误 94 | + 401: 未通过http认证 95 | + 403: forbidden,未授权 96 | + 404: not found,不存在资源 97 | + 500: internet server error,代码错误 98 | + 502: bad gateway,fastcgi返回的内容web server不明白 99 | + 503: service unavailable,服务不可用 100 | + 504: gateway timeout,fastcgi响应超时 101 | 102 | ### HTTP Header Fields 103 | 104 | 常见通用头部 105 | 106 | + Cache-Control: 107 | - no-cache: 不缓存过期的缓存 108 | - no-store: 不缓存 109 | + Pragma: no-cache, 不使用缓存,http1.1前的历史字段 110 | + Connection: 111 | - 控制不在转发给代理首部不字段 112 | - Keep-Alive/Close: 持久连接 113 | + Date: 创建http报文的日期 114 | 115 | 常见请求头 116 | 117 | + Accept: 可以处理的媒体类型和优先级 118 | + Host: 目标主机域名 119 | + Referer: 请求从哪发起的原始资源URI 120 | + User-Agent: 创建请求的用户代理名称 121 | + Cookie: cookie信息 122 | 123 | 常见响应头 124 | 125 | + Location: 重定向地址 126 | + Server: 被请求的服务web server的信息 127 | + Set-Cookie: 要设置的cookie信息 128 | - NAME: 要设置的键值对 129 | - expires: cookie过期时间 130 | - path: 指定发送cookie的目录 131 | - domain: 指定发送cookie的域名 132 | - Secure: 指定之后只有https下才发送cookie 133 | - HostOnly: 指定之后javascript无法读取cookie 134 | + Keep-Alive: 135 | 136 | HTTP协议初期每次连接结束后都会断开TCP连接,之后HEADER的connection字段定义Keep-Alive(HTTP 1.1 默认 持久连接),代表如果连接双方如果没有一方主动断开都不会断开TCP连接,减少了每次建立HTTP连接时进行TCP连接的消耗。 137 | 138 | ## Cookie/Session 139 | 140 | + Cookie: 工作机制是用户识别和状态管理,服务端为了管理用户的状态会通过客户端,把一些临时的数据写入到设备中Set-Cookie,当用户访问服务的时候,服务可以通过通信的方式取回之前存放的cookie。 141 | + Session: 由于http是无状态的,请求之间无法维系上下文,所以就出现了session作为会话控制,服务端存放用户的会话信息。 142 | 143 | ## HTTPs 144 | 145 | 概念:在http协议上增加了ssl(secure socket layer)层。 146 | 147 | ``` 148 | SSL层 149 | | 150 | 应用层 151 | | 152 | 传输层 153 | | 154 | 网络层 155 | | 156 | 链路层 157 | | 158 | 实体层 159 | ``` 160 | 161 | HTTPS 认证流程 162 | ``` 163 | 164 | 发起请求 165 | --------------------------->  server 166 | 下发证书 167 | <--------------------------- server 168 | 证书数字签名(用证书机构公钥加密) 169 | --------------------------->  证书机构 170 | 证书数字签名验证通过 171 | client(内置证书机构证书) <--------------------------- 证书机构 172 | 公钥加密随机密码串(未来的共享秘钥) 173 | --------------------------->  server私钥解密(非对称加密) 174 | SSL协议结束 HTTP协议开始 175 | <--------------------------- server(对称加密) 176 | 共享秘钥加密 HTTP 177 | --------------------------->  server(对称加密) 178 | ``` 179 | 180 | + 核对证书证书: 证书机构的公开秘钥验证证书的数字签名 181 | + 公开密钥加密建立连接:非对称加密 182 | + 共享密钥加密 183 | 184 | ## Websocket 185 | 186 | + 基于http协议建立连接,header的upgrade字段转化协议为websocket 187 | + 全双工通信,客户端建立连接 188 | 189 | ## HTTP2 190 | 191 | + 多路复用:多个请求共享一个tcp连接 192 | + 全双工通信 193 | + 必须https:// 194 | + 头部压缩 195 | + 二进制传输 -------------------------------------------------------------------------------- /network/internet-protocol.md: -------------------------------------------------------------------------------- 1 | ## 互联网协议 2 | - 概括:从上到下,越上越接近用户,越下越接近硬件 3 | - 应用层: 4 | + 规定应用程序的数据格式 5 | + [HEAD(以太网标头) [HEAD(IP标头) [HEAD(TCP标头) DATA(应用层数据包)]]] 6 | 7 | - 传输层(端口到端口的通信): 定义端口号 8 | + 端口: 9 | * 0到65535(2^16)的整数 10 | * 进程使用网卡的编号 11 | * 通过IP+mac确定主机,只要确定主机+端口(套接字socket),就能进行程序间的通信 12 | + UDP协议: 13 | * 数据包中加入端口依赖的新协议 14 | * 数据包[HEAD(发送、接收mac) [HEAD(发送、接收ip) [HEAD(发送、接收端口) DATA]]] 15 | * 简单,可靠性差,不知道对方是否接受包 16 | + TCP协议: 17 | * 带有确认机制的UDP协议 18 | * 过程复杂,实现困难,消耗资源 19 | ``` 20 | tcp/ip connect: tcp/ip的三次握手 21 | 标有syn的数据包 22 | -------------> 23 | 标有syn/ack的数据包 24 | client <------------- server 25 | 标有ack的数据包 26 | --------------> 27 | ``` 28 | 29 | - 网络层(主机到主机的通信):定义IP 30 | ``` 31 | tcp/ip finish: tcp/ip的四次握手 32 | fin 33 | <------------- 34 | ack 35 | client -------------> server 36 | fin 37 | -------------> 38 | ack 39 | <------------- 40 | ``` 41 | 42 | - 网络层(主机到主机的通信): 43 | + IP协议 44 | * ipv4: 45 | - 32个二进制位表示,由网络部分和主机部分构成, 46 | - 子网掩码: 网络部分都为1,主机部分都为0,目的判断ip的网络部分,如255.255.255.0(11111111.11111111.11111111.00000000) 47 | - IP数据包:标头Head+数据Data,放进以太网数据包的Data部分[HEAD [HEAD DATA]] 48 | - IP数据包的传递: 49 | + 非同一网络:无法获得mac地址,发送数据到网关,网关处理 50 | - ARP(Address Resolation Protocol): 解析地址协议,通过ip解析mac地址 51 | + 同一网络:mac地址填写FF:FF:FF:FF:FF:FF:FF,广播数据,对比ip,不符合丢包 52 | 53 | - 链接层:定义mac 54 | + 定义数据包(帧Frame) 55 | * 标头(Head):数据包的一些说明项, 如发送者、接收者、数据类型 56 | * 数据(Data):数据包的具体内容 57 | * 数据包:[HEAD DATA] 58 | + 定义网卡和网卡唯一的mac地址 59 | * 以太网规定接入网络的所有终端都应该具有网卡接口,数据包必须是从一个网卡的mac地址到另一网卡接口的mac地址 60 | * mac全球唯一,16位16位进制组成,前6厂商编号,后6网卡流水号 61 | + 广播发送数据 62 | * 向本网络内的所有设备发送数据包,对比接收者mac地址,不是丢包,是接受 63 | 64 | - 实体层:物理层 65 | + 终端(pc,phone,pad...)的物理连接(光缆,电缆,路由...),负责传递0和1信号 66 | -------------------------------------------------------------------------------- /network/nginx.md: -------------------------------------------------------------------------------- 1 | # client和nginx简易交互过程 2 | 3 | - step1:client发起http请求 4 | - step2:dns服务器解析域名得到主机ip 5 | - step3:默认端口为80,通过ip+port建立tcp/ip链接 6 | - step4:建立连接的tcp/ip三次握手,建立成功发送数据包 7 | - step5:nginx匹配请求 8 | 9 | - case .html: 静态内容,分发静态内容响应 10 | - case .php: php脚本,转发请求内容到php-fpm进程,分发php-fpm返回的内容响应 11 | 12 | - step6:断开连接的tcp/ip四次握手,断开连接 13 | 14 | # nginx和php简易交互过程 15 | 16 | - 背景:web server和服务端语言交互依赖的是cgi(Common Gateway Interface)协议,由于cgi效率不高(每次请求都需要重新起一个php-cgi解析器进程,这中间会进行加载php.ini配置等一系列的操作)所以后期产生了fastcgi协议(一种常驻型的cgi协议),php-cgi实现了fastcgi,但是相比php-cgi,php-fpm提供了更好的PHP进程管理方式,可以有效控制内存和进程并可以平滑重载PHP配置 17 | - 流程: 18 | 19 | - step1:nginx接收到一条http请求,会把环境变量,请求参数转变成php能懂的php变量 20 | 21 | ``` 22 | // nginx 配置资料 23 | location ~ \.php$ { 24 | include snippets/fastcgi-php.conf; //step1 25 | fastcgi_pass unix:/run/php/php7.0-fpm.sock; 26 | } 27 | ``` 28 | 29 | - step2:nginx匹配到.php结尾的访问通过fastcgi_pass命令传递给php-fpm.sock文件,其实这里 的ngnix发挥的是反向代理的角色,把http协议请求转到fastcgi协议请求 30 | 31 | ``` 32 | // nginx 配置资料 33 | location ~ \.php$ { 34 | include snippets/fastcgi-php.conf; 35 | fastcgi_pass unix:/run/php/php7.0-fpm.sock;// step2 36 | } 37 | ``` 38 | 39 | - step3:php-fpm.sock文件会被php-fpm的master进程所引用,这里nginx和php-fpm使用的是 linux的进程间通信方式unix domain socks,是一种基于文件而不是网络底册协议的通信方式 40 | 41 | - step4:php-fpm的master进程接收到请求后,会把请求分发到php-fpm的子进程,每个php-fpm 子进程都包含一个php解析器 42 | - step5:php-fpm进程处理完请求后返回给nginx 43 | 44 | # 附录 45 | 46 | - php-fpm进程管理的三种方式 47 | + static: 静态方式,php-fpm启动时及启动最大子进程数,优点是不需要额外的fork子进程过程,适合专门的服务器 48 | - 参数: 49 | - pm.max_children: 最大子进程数 50 | + dynamic: 动态方式,配置最大数和启动数,空闲数,实际使用过程fork进程,优点灵活节省内存,缺点fork过程有性能消耗 51 | - 参数: 52 | - pm.max_children: 最大进程数 53 | - pm.start_servers: 启动数,等于min_spare_servers + (max_spare_servers - min_spare_servers)/2 54 | - pm.min_spare_servers: 最小空闲进程数,如果空闲进程(idle)数小于该值,启动一个子进程 55 | - pm.max_spare_servers: 最大空闲进程数,如果空闲进程(idle)数大于该值,kill一个子进程 56 | + ondemand: 按需方式, 不启动子进程,按需fork,优点节省资源 57 | - 参数: 58 | - pm.max_children: 59 | - pm.process_idle_timeout: 子进程空闲多少秒后被kill 60 | -------------------------------------------------------------------------------- /patterns/adapter/Adapter.php: -------------------------------------------------------------------------------- 1 | _advancePlayerInstance = new AdvanceMp4Player(); 20 | break; 21 | case 'wma': 22 | $this->_advancePlayerInstance = new AdvanceWmaPlayer(); 23 | break; 24 | 25 | default: 26 | throw new Exception("$type is not supported", 400); 27 | break; 28 | } 29 | $this->_type = $type; 30 | } 31 | 32 | public function play($file='') 33 | { 34 | switch ($this->_type) { 35 | case 'mp4': 36 | $this->_advancePlayerInstance->playMp4($file); 37 | break; 38 | case 'wma': 39 | $this->_advancePlayerInstance->playWma($file); 40 | break; 41 | default: 42 | break; 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /patterns/adapter/AdvanceMp4Player.php: -------------------------------------------------------------------------------- 1 | play($file); 20 | break; 21 | case 'wma': 22 | $adapter = new Adapter($type); 23 | $adapter->play($file); 24 | break; 25 | 26 | default: 27 | throw new Exception("$type is not supported", 400); 28 | break; 29 | } 30 | 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /patterns/adapter/MediaAdvanceInterface.php: -------------------------------------------------------------------------------- 1 | 9 | * @example 运行 php test.php 10 | */ 11 | 12 | 13 | // 注册自加载 14 | spl_autoload_register('autoload'); 15 | 16 | function autoload($class) 17 | { 18 | require dirname($_SERVER['SCRIPT_FILENAME']) . '//..//' . str_replace('\\', '/', $class) . '.php'; 19 | } 20 | 21 | /************************************* test *************************************/ 22 | 23 | use adapter\AudioPlayer; 24 | 25 | try { 26 | //生产一台设备 27 | $mp4 = new AudioPlayer(); 28 | // 播放一个mp3 29 | $mp4->play('忍者', 'mp3'); 30 | // 播放一个wma 31 | $mp4->play('彩虹', 'wma'); 32 | // 播放一个mp4 33 | $mp4->play('龙卷风mv', 'mp4'); 34 | } catch (\Exception $e) { 35 | echo $e->getMessage(); 36 | } 37 | -------------------------------------------------------------------------------- /patterns/bridge/EatByChopsticks.php: -------------------------------------------------------------------------------- 1 | _gender = $gender; 30 | $this->_tool = $tool; 31 | } 32 | 33 | /** 34 | * 吃的行为 35 | * 36 | * @param string $food 实物 37 | * @return void 38 | */ 39 | abstract public function eat($food=''); 40 | } 41 | -------------------------------------------------------------------------------- /patterns/bridge/PersonMale.php: -------------------------------------------------------------------------------- 1 | _tool->eat($food); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /patterns/bridge/test.php: -------------------------------------------------------------------------------- 1 | 抽象为属性:性别 动作:吃 => 人吃的动作抽象为interface => 实现不同的吃法 8 | * 9 | * @author TIGERB 10 | * @example 运行 php test.php 11 | */ 12 | 13 | 14 | // 注册自加载 15 | spl_autoload_register('autoload'); 16 | 17 | function autoload($class) 18 | { 19 | require dirname($_SERVER['SCRIPT_FILENAME']) . '//..//' . str_replace('\\', '/', $class) . '.php'; 20 | } 21 | 22 | /************************************* test *************************************/ 23 | 24 | use bridge\PersonMale; 25 | use bridge\EatByChopsticks; 26 | use bridge\EatByFork; 27 | 28 | try { 29 | // 初始化一个用筷子吃饭的男人的实例 30 | $male = new PersonMale('male', new EatByChopsticks()); 31 | // 吃饭 32 | $male->eat('大盘鸡'); 33 | 34 | } catch (\Exception $e) { 35 | echo $e->getMessage(); 36 | } 37 | -------------------------------------------------------------------------------- /patterns/builder/BuilderInterface.php: -------------------------------------------------------------------------------- 1 | _name = $name; 52 | echo $this->_name . " 配置如下:\n"; 53 | // 构建硬件 54 | $this->hardware($hardware); 55 | // 构建软件 56 | $this->software($software); 57 | } 58 | 59 | /** 60 | * 构建硬件 61 | * 62 | * @param array $hardware 硬件参数 63 | * @return void 64 | */ 65 | public function hardware($hardware=array()) 66 | { 67 | // 创建cpu 68 | $hardwareCpu = new HardwareCpu(); 69 | $this->_cpu = $hardwareCpu->produce($hardware['cpu']); 70 | // 创建内存 71 | $hardwareRam = new HardwareRam(); 72 | $this->_ram = $hardwareRam->produce($hardware['ram']); 73 | // 创建储存 74 | $hardwareStorage = new HardwareStorage(); 75 | $this->_storage = $hardwareStorage->produce($hardware['storage']); 76 | } 77 | 78 | /** 79 | * 构建软件 80 | * 81 | * @param array $software 软件参数 82 | * @return void 83 | */ 84 | public function software($software=array()) 85 | { 86 | // 创建操作系统 87 | $softwareOs = new SoftwareOs(); 88 | $this->_os = $softwareOs->produce($software['os']); 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /patterns/builder/PhoneBuilder.php: -------------------------------------------------------------------------------- 1 | _name = $name; 63 | echo $this->_name . " 配置如下:\n"; 64 | // 构建硬件 65 | $this->hardware($hardware); 66 | // 构建软件 67 | $this->software($software); 68 | } 69 | 70 | /** 71 | * 构建硬件 72 | * @param array $hardware 硬件参数 73 | * @return void 74 | */ 75 | public function hardware($hardware=array()) 76 | { 77 | // 创建屏幕 78 | $hardwareScreen = new HardwareScreen(); 79 | $this->_screen = $hardwareScreen->produce($hardware['screen']); 80 | // 创建cpu 81 | $hardwareCpu = new HardwareCpu(); 82 | $this->_cpu = $hardwareCpu->produce($hardware['cpu']); 83 | // 创建内存 84 | $hardwareRam = new HardwareRam(); 85 | $this->_ram = $hardwareRam->produce($hardware['ram']); 86 | // 创建储存 87 | $hardwareStorage = new HardwareStorage(); 88 | $this->_storage = $hardwareStorage->produce($hardware['storage']); 89 | // 创建摄像头 90 | $hardwareCamera = new HardwareCamera(); 91 | $this->_camera = $hardwareCamera->produce($hardware['camera']); 92 | } 93 | 94 | /** 95 | * 构建软件 96 | * @param array $software 软件参数 97 | * @return void 98 | */ 99 | public function software($software=array()) 100 | { 101 | // 创建操作系统 102 | $softwareOs = new SoftwareOs(); 103 | $this->_os = $softwareOs->produce($software['os']); 104 | } 105 | } 106 | -------------------------------------------------------------------------------- /patterns/builder/Software.php: -------------------------------------------------------------------------------- 1 | 名称,硬件, 软件 13 | * // 硬件又由以下硬件构成 14 | * 硬件 => 屏幕,cpu, 内存, 储存, 摄像头 15 | * // 软件又由以下构成 16 | * 软件 => android, ubuntu 17 | * 18 | * * // mp3简单由以下构成 19 | * 手机 => 名称,硬件, 软件 20 | * // 硬件又由以下硬件构成 21 | * 硬件 => cpu, 内存, 储存 22 | * // 软件又由以下构成 23 | * 软件 => mp3 os 24 | * 25 | * @author TIGERB 26 | * @example 运行 php test.php 27 | */ 28 | 29 | 30 | // 注册自加载 31 | spl_autoload_register('autoload'); 32 | 33 | function autoload($class) 34 | { 35 | require dirname($_SERVER['SCRIPT_FILENAME']) . '//..//' . str_replace('\\', '/', $class) . '.php'; 36 | } 37 | 38 | /************************************* test *************************************/ 39 | 40 | use builder\PhoneBuilder; 41 | use builder\Mp3Builder; 42 | 43 | // 创建一个PhoneBuilder生产一款旗舰android手机 44 | $builder = new PhoneBuilder('某米8s', [ 45 | 'screen' => '5.0', 46 | 'cpu' => 16, 47 | 'ram' => 8, 48 | 'storage' => 64, 49 | 'camera' => '2000w' 50 | ],['os' => 'android 6.0']); 51 | 52 | echo "\n"; 53 | echo "----------------\n"; 54 | echo "\n"; 55 | 56 | // 创建一个Mp3Builder生产一款mp3 57 | $builder = new Mp3Builder('某族MP3', [ 58 | 'cpu' => 1, 59 | 'ram' => 1, 60 | 'storage' => 128, 61 | ],['os' => 'mp3 os']); 62 | -------------------------------------------------------------------------------- /patterns/chainOfResponsibility/Handler.php: -------------------------------------------------------------------------------- 1 | _nextHandler = $handler; 30 | return $handler; 31 | } 32 | 33 | /** 34 | * 启动 35 | * 36 | * @param Handler $handler 37 | */ 38 | public function start(Request $request) 39 | { 40 | $this->check($request); 41 | // 调用下一个对象 42 | if (!empty($this->_nextHandler)) { 43 | $this->_nextHandler->start($request); 44 | } 45 | } 46 | 47 | } 48 | -------------------------------------------------------------------------------- /patterns/chainOfResponsibility/HandlerAccessToken.php: -------------------------------------------------------------------------------- 1 | requestId}: 令牌校验通过~ \n"; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /patterns/chainOfResponsibility/HandlerArguments.php: -------------------------------------------------------------------------------- 1 | requestId}: 参数校验通过~ \n"; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /patterns/chainOfResponsibility/HandlerAuthority.php: -------------------------------------------------------------------------------- 1 | requestId}: 权限校验通过~ \n"; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /patterns/chainOfResponsibility/HandlerFrequent.php: -------------------------------------------------------------------------------- 1 | requestId}: 请求频率校验通过~ \n"; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /patterns/chainOfResponsibility/HandlerSign.php: -------------------------------------------------------------------------------- 1 | requestId}: 签名校验通过~ \n"; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /patterns/chainOfResponsibility/Request.php: -------------------------------------------------------------------------------- 1 | $name = $value; 24 | } 25 | 26 | /** 27 | * 魔术方法 获取私有属性 28 | * @param string $name 属性名称 29 | */ 30 | public function __get($name='') 31 | { 32 | $name = '_' . $name; 33 | return $this->$name; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /patterns/chainOfResponsibility/test.php: -------------------------------------------------------------------------------- 1 | 11 | * @example 运行 php test.php 12 | */ 13 | 14 | 15 | // 注册自加载 16 | spl_autoload_register('autoload'); 17 | 18 | function autoload($class) 19 | { 20 | require dirname($_SERVER['SCRIPT_FILENAME']) . '//..//' . str_replace('\\', '/', $class) . '.php'; 21 | } 22 | 23 | /************************************* test *************************************/ 24 | 25 | use chainOfResponsibility\HandlerAccessToken; 26 | use chainOfResponsibility\HandlerFrequent; 27 | use chainOfResponsibility\HandlerArguments; 28 | use chainOfResponsibility\HandlerSign; 29 | use chainOfResponsibility\HandlerAuthority; 30 | use chainOfResponsibility\Request; 31 | 32 | try { 33 | // 下面我们用责任链模式实现一个api-gateway即接口网关 34 | 35 | // 初始化一个请求对象 36 | $request = new Request(); 37 | // 设置一个请求身份id 38 | $request->requestId = uniqid(); 39 | 40 | // 初始化一个:令牌校验的handler 41 | $handlerAccessToken = new HandlerAccessToken(); 42 | // 初始化一个:访问频次校验的handler 43 | $handlerFrequent = new HandlerFrequent(); 44 | // 初始化一个:必传参数校验的handler 45 | $handlerArguments = new HandlerArguments(); 46 | // 初始化一个:签名校验的handler 47 | $handlerSign = new HandlerSign(); 48 | // 初始化一个:访问权限校验的handler 49 | $handlerAuthority = new HandlerAuthority(); 50 | 51 | // 构成对象链 52 | $handlerAccessToken->setNext($handlerFrequent) 53 | ->setNext($handlerArguments) 54 | ->setNext($handlerSign) 55 | ->setNext($handlerAuthority); 56 | // 启动网关 57 | $handlerAccessToken->start($request); 58 | 59 | } catch (\Exception $e) { 60 | echo $e->getMessage(); 61 | } 62 | -------------------------------------------------------------------------------- /patterns/command/Console.php: -------------------------------------------------------------------------------- 1 | _orderList, $order); 23 | } 24 | 25 | /** 26 | * 执行命令 27 | * @return mixed 28 | */ 29 | public function run() 30 | { 31 | foreach ($this->_orderList as $k => $v) { 32 | $v->execute(); 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /patterns/command/Order.php: -------------------------------------------------------------------------------- 1 | '' 21 | ]; 22 | 23 | /** 24 | * 构造函数 25 | * 26 | * @param Text $text 27 | * @param array $arguments 28 | */ 29 | public function __construct(Text $text, $arguments=[]) 30 | { 31 | $this->_text = $text; 32 | $this->_arguments = $arguments; 33 | } 34 | 35 | /** 36 | * 执行命令 37 | * 38 | * @return void 39 | */ 40 | public function execute() 41 | { 42 | $this->_text->create($this->_arguments['filename']); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /patterns/command/OrderSave.php: -------------------------------------------------------------------------------- 1 | '' 21 | ]; 22 | 23 | /** 24 | * 构造函数 25 | * 26 | * @param Text text 27 | * @param array $arguments 28 | */ 29 | public function __construct(Text $text, $arguments=[]) 30 | { 31 | $this->_text = $text; 32 | $this->_arguments = $arguments; 33 | } 34 | 35 | /** 36 | * 执行命令 37 | * 38 | * @return void 39 | */ 40 | public function execute() 41 | { 42 | $this->_text->save($this->_arguments['filename']); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /patterns/command/OrderWrite.php: -------------------------------------------------------------------------------- 1 | '', 21 | 'content' => '' 22 | ]; 23 | 24 | 25 | /** 26 | * 构造函数 27 | * 28 | * @param Text text 29 | * @param array $arguments 30 | */ 31 | public function __construct(Text $text, $arguments=[]) 32 | { 33 | $this->_text = $text; 34 | $this->_arguments = $arguments; 35 | } 36 | 37 | /** 38 | * 执行命令 39 | * 40 | * @return void 41 | */ 42 | public function execute() 43 | { 44 | $this->_text->Write( 45 | $this->_arguments['filename'], 46 | $this->_arguments['content'] 47 | ); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /patterns/command/Text.php: -------------------------------------------------------------------------------- 1 | 15 | * @example 运行 php test.php 16 | */ 17 | 18 | 19 | // 注册自加载 20 | spl_autoload_register('autoload'); 21 | 22 | function autoload($class) 23 | { 24 | require dirname($_SERVER['SCRIPT_FILENAME']) . '//..//' . str_replace('\\', '/', $class) . '.php'; 25 | } 26 | 27 | /************************************* test *************************************/ 28 | 29 | use command\Text; 30 | use command\OrderCreate; 31 | use command\OrderWrite; 32 | use command\OrderSave; 33 | use command\Console; 34 | 35 | try { 36 | // 创建一个记事本实例 37 | $text = new Text(); 38 | 39 | // 创建命令 40 | $create = new OrderCreate($text, [ 41 | 'filename' => 'test.txt' 42 | ]); 43 | // 写入命令 44 | $write = new OrderWrite($text, [ 45 | 'filename' => 'test.txt', 46 | 'content' => 'life is a struggle' 47 | ]); 48 | // 保存命令 49 | $save = new OrderSave($text, [ 50 | 'filename' => 'text.txt' 51 | ]); 52 | 53 | // 创建一个控制台 54 | $console = new Console(); 55 | // 添加命令 56 | $console->add($create); 57 | $console->add($write); 58 | $console->add($save); 59 | // 运行命令 60 | $console->run(); 61 | 62 | } catch (\Exception $e) { 63 | echo $e->getMessage(); 64 | } 65 | -------------------------------------------------------------------------------- /patterns/composite/CompositeInterface.php: -------------------------------------------------------------------------------- 1 | _name = $name; 31 | } 32 | 33 | /** 34 | * 魔法函数 35 | * @param string $name 属性名称 36 | * @return mixed 37 | */ 38 | public function __get($name='') 39 | { 40 | $name = '_' . $name; 41 | return $this->$name; 42 | } 43 | 44 | /** 45 | * 增加一个节点对象 46 | * 47 | * @return mixed 48 | */ 49 | public function add(CompositeInterface $composite) 50 | { 51 | throw new Exception('not support', 500); 52 | } 53 | 54 | /** 55 | * 删除节点一个对象 56 | * 57 | * @return mixed 58 | */ 59 | public function delete(CompositeInterface $composite) 60 | { 61 | throw new Exception('not support', 500); 62 | } 63 | 64 | /** 65 | * 打印对象组合. 66 | * 67 | * @return mixed 68 | */ 69 | public function printComposite() 70 | { 71 | throw new Exception('not support', 500); 72 | } 73 | 74 | /** 75 | * 实体类要实现的方法. 76 | * 77 | * @return mixed 78 | */ 79 | public function operation($operation = '', $content = '') 80 | { 81 | switch ($operation) { 82 | case 'write': 83 | $this->_content .= $content; 84 | echo 'write success'; 85 | break; 86 | case 'read': 87 | echo $this->_content; 88 | break; 89 | 90 | default: 91 | throw new \Exception("not support", 400); 92 | break; 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /patterns/composite/Folder.php: -------------------------------------------------------------------------------- 1 | _name = $name; 29 | } 30 | 31 | /** 32 | * 魔法函数 33 | * @param string $name 属性名称 34 | * @return mixed 35 | */ 36 | public function __get($name='') 37 | { 38 | $name = '_' . $name; 39 | return $this->$name; 40 | } 41 | 42 | /** 43 | * 增加一个节点对象 44 | * 45 | * @return void 46 | */ 47 | public function add(CompositeInterface $composite) 48 | { 49 | if (in_array($composite, $this->_composite, true)) { 50 | return; 51 | } 52 | $this->_composite[] = $composite; 53 | } 54 | 55 | /** 56 | * 删除节点一个对象 57 | * 58 | * @return void 59 | */ 60 | public function delete(CompositeInterface $composite) 61 | { 62 | $key = array_search($composite, $this->_composite, true); 63 | if (!$key) { 64 | throw new Exception("not found", 404); 65 | } 66 | unset($this->_composite[$key]); 67 | $this->_composite = array_values($this->_composite); 68 | } 69 | 70 | /** 71 | * 打印对象组合 72 | * 73 | * @return void 74 | */ 75 | public function printComposite() 76 | { 77 | foreach ($this->_composite as $v) { 78 | if ($v instanceof Folder) { 79 | echo '---' . $v->name . "---\n"; 80 | $v->printComposite(); 81 | continue; 82 | } 83 | echo $v->name . "\n"; 84 | } 85 | } 86 | 87 | /** 88 | * 实体类要实现的方法 89 | * 90 | * @return mixed 91 | */ 92 | public function operation() 93 | { 94 | return; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /patterns/composite/test.php: -------------------------------------------------------------------------------- 1 | 11 | * @example 运行 php test.php 12 | */ 13 | 14 | 15 | // 注册自加载 16 | spl_autoload_register('autoload'); 17 | 18 | function autoload($class) 19 | { 20 | require dirname($_SERVER['SCRIPT_FILENAME']) . '//..//' . str_replace('\\', '/', $class) . '.php'; 21 | } 22 | 23 | /************************************* test 实现一个文件夹*************************************/ 24 | 25 | use composite\Folder; 26 | use composite\File; 27 | 28 | try { 29 | // 构建一个根目录 30 | $root = new Folder('根目录'); 31 | 32 | // 根目录下添加一个test.php的文件和usr,mnt的文件夹 33 | $testFile = new File('test.php'); 34 | $usr = new Folder('usr'); 35 | $mnt = new Folder('mnt'); 36 | $root->add($testFile); 37 | $root->add($usr); 38 | $root->add($mnt); 39 | $usr->add($testFile);// usr目录下加一个test.php的文件 40 | 41 | // 打印根目录文件夹节点 42 | $root->printComposite(); 43 | 44 | } catch (\Exception $e) { 45 | echo $e->getMessage(); 46 | } 47 | -------------------------------------------------------------------------------- /patterns/decorator/BasicPulisher.php: -------------------------------------------------------------------------------- 1 | shoes = $shoes; 21 | } 22 | 23 | /** 24 | * 生产. 25 | */ 26 | public function product() 27 | { 28 | $this->shoes->product(); 29 | } 30 | 31 | /** 32 | * 装饰操作. 33 | */ 34 | abstract public function decorate($value); 35 | } 36 | -------------------------------------------------------------------------------- /patterns/decorator/DecoratorBrand.php: -------------------------------------------------------------------------------- 1 | shoes = $shoes; 18 | } 19 | 20 | public function __set($name='', $value='') 21 | { 22 | $this->$name = $value; 23 | } 24 | 25 | /** 26 | * 生产 27 | */ 28 | public function product() 29 | { 30 | $this->shoes->product(); 31 | $this->decorate($this->_brand); 32 | } 33 | 34 | /** 35 | * 贴标操作 36 | */ 37 | public function decorate($value='') 38 | { 39 | echo "贴上{$value}标志 \n"; 40 | } 41 | 42 | } 43 | -------------------------------------------------------------------------------- /patterns/decorator/MoviePulisher.php: -------------------------------------------------------------------------------- 1 | addMovieCompnent(); 16 | parent::pulishText(); 17 | } 18 | 19 | public function addMovieCompnent() { 20 | echo 'add movie compnent'.PHP_EOL; 21 | } 22 | 23 | } -------------------------------------------------------------------------------- /patterns/decorator/MusicPublisher.php: -------------------------------------------------------------------------------- 1 | addMusicCompnent(); 17 | parent::pulishText(); 18 | } 19 | 20 | public function addMusicCompnent() { 21 | echo 'add music compnent'.PHP_EOL; 22 | } 23 | 24 | } -------------------------------------------------------------------------------- /patterns/decorator/PulisherDerector.php: -------------------------------------------------------------------------------- 1 | pulisher = $pulisher; 18 | } 19 | 20 | public function pulishText() { 21 | $this->pulisher->pulishText(); 22 | } 23 | 24 | } -------------------------------------------------------------------------------- /patterns/decorator/PulisherInterface.php: -------------------------------------------------------------------------------- 1 | 10 | * @example 运行 php test.php 11 | */ 12 | 13 | 14 | // 注册自加载 15 | spl_autoload_register('autoload'); 16 | 17 | function autoload($class) 18 | { 19 | require dirname($_SERVER['SCRIPT_FILENAME']) . '//..//' . str_replace('\\', '/', $class) . '.php'; 20 | } 21 | 22 | /************************************* test *************************************/ 23 | 24 | use decorator\DecoratorBrand; 25 | use decorator\ShoesSport; 26 | use decorator\ShoesSkateboard; 27 | 28 | try { 29 | echo "未加装饰器之前:\n"; 30 | // 生产运动鞋 31 | $shoesSport = new ShoesSport(); 32 | $shoesSport->product(); 33 | 34 | echo "\n--------------------\n"; 35 | //----------------------------------- 36 | 37 | echo "加贴标装饰器:\n"; 38 | // 初始化一个贴商标适配器 39 | $DecoratorBrand = new DecoratorBrand(new ShoesSport()); 40 | $DecoratorBrand->_brand = 'nike'; 41 | // 生产nike牌运动鞋 42 | $DecoratorBrand->product(); 43 | } catch (\Exception $e) { 44 | echo $e->getMessage(); 45 | } 46 | -------------------------------------------------------------------------------- /patterns/decorator/testpulish.php: -------------------------------------------------------------------------------- 1 | derect($basicPulisher); 33 | $musicPulisher->derect($moviePulisher); 34 | $musicPulisher->pulishText(); 35 | 36 | 37 | }catch (\Exception $e) { 38 | echo $e->getMessage(); 39 | } -------------------------------------------------------------------------------- /patterns/facade/AnimalInterface.php: -------------------------------------------------------------------------------- 1 | _chicken = new Chicken(); 29 | $this->_pig = new Pig(); 30 | } 31 | 32 | /** 33 | * 生产方法 34 | * 35 | * 生产鸡 36 | * @return string 37 | */ 38 | public function produceChicken() 39 | { 40 | $this->_chicken->produce(); 41 | } 42 | 43 | /** 44 | * 生产方法 45 | * 46 | * 生产猪 47 | * @return string 48 | */ 49 | public function producePig() 50 | { 51 | $this->_pig->produce(); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /patterns/facade/Chicken.php: -------------------------------------------------------------------------------- 1 | 9 | * @example 运行 php test.php 10 | */ 11 | 12 | 13 | // 注册自加载 14 | spl_autoload_register('autoload'); 15 | 16 | function autoload($class) 17 | { 18 | require dirname($_SERVER['SCRIPT_FILENAME']) . '//..//' . str_replace('\\', '/', $class) . '.php'; 19 | } 20 | 21 | /************************************* test *************************************/ 22 | 23 | use facade\AnimalMaker; 24 | 25 | // 初始化外观类 26 | $animalMaker = new AnimalMaker(); 27 | 28 | // 生产一只猪 29 | $animalMaker->producePig(); 30 | 31 | // 生产一只鸡 32 | $animalMaker->produceChicken(); 33 | -------------------------------------------------------------------------------- /patterns/factory/AnimalInterface.php: -------------------------------------------------------------------------------- 1 | 12 | * @author jealone 13 | * @example 运行 php test.php 14 | */ 15 | 16 | 17 | // 注册自加载 18 | spl_autoload_register('autoload'); 19 | 20 | function autoload($class) 21 | { 22 | require dirname($_SERVER['SCRIPT_FILENAME']) . '//..//' . str_replace('\\', '/', $class) . '.php'; 23 | } 24 | 25 | /************************************* test *************************************/ 26 | 27 | use factory\Farm; 28 | use factory\Zoo; 29 | use factory\SampleFactory; 30 | 31 | // 初始化一个工厂 32 | $farm = new Farm(); 33 | 34 | // 生产一只鸡 35 | $farm->produce('chicken'); 36 | // 生产一只猪 37 | $farm->produce('pig'); 38 | 39 | // 初始化一个动物园工厂 40 | $zoo = new Zoo(); 41 | $zoo->produce("chicken"); 42 | $zoo->produce("pig"); 43 | 44 | // 工厂方法模式退化为简单工厂模式 45 | SampleFactory::produce("chicken"); 46 | SampleFactory::produce("pig"); 47 | -------------------------------------------------------------------------------- /patterns/factoryAbstract/AnimalFactory.php: -------------------------------------------------------------------------------- 1 | show(); 14 | echo "卖门票\n\n"; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /patterns/factoryAbstract/PeonyZoo.php: -------------------------------------------------------------------------------- 1 | show(); 13 | echo "卖门票\n\n"; 14 | } 15 | 16 | } 17 | -------------------------------------------------------------------------------- /patterns/factoryAbstract/PigFarm.php: -------------------------------------------------------------------------------- 1 | harvest(); 14 | echo "卖猪肉\n\n"; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /patterns/factoryAbstract/PlantFactory.php: -------------------------------------------------------------------------------- 1 | harvest(); 14 | echo "卖大米\n\n"; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /patterns/factoryAbstract/ZooInterface.php: -------------------------------------------------------------------------------- 1 | 12 | * @example 运行 php test.php 13 | */ 14 | 15 | 16 | // 注册自加载 17 | spl_autoload_register('autoload'); 18 | 19 | function autoload($class) 20 | { 21 | require dirname($_SERVER['SCRIPT_FILENAME']) . '//..//' . str_replace('\\', '/', $class) . '.php'; 22 | } 23 | 24 | /************************************* test *************************************/ 25 | 26 | use factoryAbstract\AnimalFactory; 27 | use factoryAbstract\PlantFactory; 28 | 29 | // 初始化一个动物生产线, 包含了一族产品 30 | $animal = new AnimalFactory(); 31 | 32 | // 初始化一个植物生产线, 包含了一族产品 33 | $plant = new PlantFactory(); 34 | 35 | // 模拟调用, 抽象工厂模式核心是面向接口编程 36 | function call(factoryAbstract\Factory $factory) { 37 | $earn = function(factoryAbstract\Income $income) { 38 | $income->money(); 39 | }; 40 | $earn($factory->createFarm()); 41 | $earn($factory->createZoo()); 42 | } 43 | 44 | call($animal); 45 | call($plant); 46 | -------------------------------------------------------------------------------- /patterns/filter/FilterGender.php: -------------------------------------------------------------------------------- 1 | _gender = $gender; 22 | } 23 | 24 | /** 25 | * 过滤方法 26 | * 27 | * @param array $persons 运动员集合 28 | * @return mixed 29 | */ 30 | public function filter(array $persons) 31 | { 32 | foreach ($persons as $k => $v) { 33 | if ($v->gender === $this->_gender) { 34 | $personsFilter[] = $persons[$k]; 35 | } 36 | } 37 | return $personsFilter; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /patterns/filter/FilterInterface.php: -------------------------------------------------------------------------------- 1 | _sportType = $sportType; 22 | } 23 | 24 | /** 25 | * 过滤方法 26 | * 27 | * @param array $persons 运动员集合 28 | * @return mixed 29 | */ 30 | public function filter(array $persons) 31 | { 32 | foreach ($persons as $k => $v) { 33 | if ($v->sportType === $this->_sportType) { 34 | $personsFilter[] = $persons[$k]; 35 | } 36 | } 37 | return $personsFilter; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /patterns/filter/SportsPerson.php: -------------------------------------------------------------------------------- 1 | _gender = $gender; 29 | $this->_sportType = $sportType; 30 | } 31 | 32 | /** 33 | * 魔法函数 34 | * @param string $value 35 | * @return mixed 36 | */ 37 | public function __get($value='') 38 | { 39 | $value = '_' . $value; 40 | return $this->$value; 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /patterns/filter/test.php: -------------------------------------------------------------------------------- 1 | 10 | * @example 运行 php test.php 11 | */ 12 | 13 | 14 | // 注册自加载 15 | spl_autoload_register('autoload'); 16 | 17 | function autoload($class) 18 | { 19 | require dirname($_SERVER['SCRIPT_FILENAME']) . '//..//' . str_replace('\\', '/', $class) . '.php'; 20 | } 21 | 22 | /************************************* test *************************************/ 23 | 24 | use filter\SportsPerson; 25 | use filter\FilterSportType; 26 | use filter\FilterGender; 27 | 28 | try { 29 | // 定义一组运动员 30 | $persons = []; 31 | $persons[] = new SportsPerson('male', 'basketball'); 32 | $persons[] = new SportsPerson('female', 'basketball'); 33 | $persons[] = new SportsPerson('male', 'football'); 34 | $persons[] = new SportsPerson('female', 'football'); 35 | $persons[] = new SportsPerson('male', 'swim'); 36 | $persons[] = new SportsPerson('female', 'swim'); 37 | 38 | // 按过滤男性 39 | $filterGender = new FilterGender('male'); 40 | var_dump($filterGender->filter($persons)); 41 | // 过滤运动项目篮球 42 | $filterSportType = new FilterSportType('basketball'); 43 | var_dump($filterSportType->filter($persons)); 44 | 45 | } catch (\Exception $e) { 46 | echo $e->getMessage(); 47 | } 48 | -------------------------------------------------------------------------------- /patterns/flyweight/AnimalInterface.php: -------------------------------------------------------------------------------- 1 | _farmMap)) { 37 | echo "来自缓存池-> "; 38 | return $this->_farmMap[$type];// 返回缓存 39 | } 40 | 41 | switch ($type) { 42 | case 'chicken': 43 | return $this->_farmMap[$type] = new Chicken(); 44 | break; 45 | 46 | case 'pig': 47 | return $this->_farmMap[$type] = new Pig(); 48 | break; 49 | 50 | default: 51 | echo "该农场不支持生产该农物~ \n"; 52 | break; 53 | } 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /patterns/flyweight/Pig.php: -------------------------------------------------------------------------------- 1 | 13 | * @example 运行 php test.php 14 | */ 15 | 16 | 17 | // 注册自加载 18 | spl_autoload_register('autoload'); 19 | 20 | function autoload($class) 21 | { 22 | require dirname($_SERVER['SCRIPT_FILENAME']) . '//..//' . str_replace('\\', '/', $class) . '.php'; 23 | } 24 | 25 | /************************************* test *************************************/ 26 | 27 | use flyweight\Farm; 28 | 29 | // 初始化一个工厂 30 | $farm = new Farm(); 31 | 32 | // 成产一只鸡 33 | $farm->produce('chicken')->getType(); 34 | // 再生产一只鸡 35 | $farm->produce('chicken')->getType(); 36 | -------------------------------------------------------------------------------- /patterns/interpreter/SqlInterpreter.php: -------------------------------------------------------------------------------- 1 | _setTableName($tableName); 39 | // 返回实例 40 | return self::$_instance; 41 | } 42 | 43 | /** 44 | * 设置表名 45 | * 46 | * @param string $tableName 表名 47 | */ 48 | private function _setTableName($tableName='') 49 | { 50 | $this->_tableName = $tableName; 51 | } 52 | 53 | /** 54 | * 插入一条数据 55 | * 56 | * @param array $data 数据 57 | * @return mixed 58 | */ 59 | public function insert($data=[]) 60 | { 61 | if (empty($data)) { 62 | throw new Exception("argument data is null", 400); 63 | } 64 | $count = count($data); 65 | //拼接字段 66 | $field = array_keys($data); 67 | $fieldString = ''; 68 | foreach ($field as $k => $v) { 69 | if ($k === (int)($count - 1)) { 70 | $fieldString .= "`{$v}`"; 71 | continue; 72 | } 73 | $fieldString .= "`{$v}`".','; 74 | } 75 | unset($k); 76 | unset($v); 77 | 78 | //拼接值 79 | $value = array_values($data); 80 | $valueString = ''; 81 | foreach ($value as $k => $v) { 82 | if ($k === (int)($count - 1)) { 83 | $valueString .= "'{$v}'"; 84 | continue; 85 | } 86 | $valueString .= "'{$v}'".','; 87 | } 88 | unset($k); 89 | unset($v); 90 | 91 | $sql = "INSERT INTO `{$this->_tableName}` ({$fieldString}) VALUES ({$valueString})"; 92 | 93 | echo $sql . "\n"; 94 | } 95 | 96 | /** 97 | * 删除数据 98 | * 99 | * @param array $data 数据 100 | * @return mixed 101 | */ 102 | public function delete($data=[]) 103 | { 104 | if (empty($data)) { 105 | throw new Exception("argument data is null", 400); 106 | } 107 | // 拼接where语句 108 | $count = (int)count($data); 109 | $where = ''; 110 | $dataCopy = $data; 111 | $pop = array_pop($dataCopy); 112 | if ($count === 1) { 113 | $field = array_keys($data)[0]; 114 | $value = array_values($data)[0]; 115 | $where = "`{$field}` = '{$value}'"; 116 | }else{ 117 | foreach ($data as $k => $v) { 118 | if ($v === $pop) { 119 | $where .= "`{$k}` = '{$v}'"; 120 | continue; 121 | } 122 | $where .= "`{$k}` = '{$v}' AND "; 123 | } 124 | } 125 | 126 | $sql = "DELETE FROM `{$this->_tableName}` WHERE {$where}"; 127 | 128 | echo $sql . "\n"; 129 | } 130 | 131 | /** 132 | * 更新一条数据 133 | * 134 | * @param array $data 数据 135 | * @return mixed 136 | */ 137 | public function update($data=[]) 138 | { 139 | if (empty($data)) { 140 | throw new Exception("argument data is null", 400); 141 | } 142 | if (empty($data['id'])) { 143 | throw new Exception("argument data['id'] is null", 400); 144 | } 145 | $set = ''; 146 | $dataCopy = $data; 147 | $pop = array_pop($dataCopy); 148 | foreach ($data as $k => $v) { 149 | if ($v === $pop) { 150 | $set .= "`{$k}` = '$v'"; 151 | continue; 152 | } 153 | $set .= "`{$k}` = '$v',"; 154 | } 155 | 156 | $sql = "UPDATE `{$this->_tableName}` SET {$set}"; 157 | 158 | echo $sql . "\n"; 159 | } 160 | 161 | /** 162 | * 查找一条数据 163 | * 164 | * @param array $data 数据 165 | * @return mixed 166 | */ 167 | public function find($data=[]) 168 | { 169 | if (empty($data)) { 170 | throw new Exception("argument data is null", 400); 171 | } 172 | 173 | // 拼接where语句 174 | $count = (int)count($data); 175 | $where = ''; 176 | $dataCopy = $data; 177 | $pop = array_pop($dataCopy); 178 | if ($count === 1) { 179 | $field = array_keys($data)[0]; 180 | $value = array_values($data)[0]; 181 | $where = "`{$field}` = '{$value}'"; 182 | }else{ 183 | foreach ($data as $k => $v) { 184 | if ($v === $pop) { 185 | $where .= "`{$k}` = '{$v}'"; 186 | continue; 187 | } 188 | $where .= "`{$k}` = '{$v}' AND "; 189 | } 190 | } 191 | 192 | $sql = "SELECT * FROM `{$this->_tableName}` WHERE {$where}"; 193 | 194 | echo $sql . "\n"; 195 | } 196 | } 197 | -------------------------------------------------------------------------------- /patterns/interpreter/test.php: -------------------------------------------------------------------------------- 1 | 11 | * @example 运行 php test.php 12 | */ 13 | 14 | 15 | // 注册自加载 16 | spl_autoload_register('autoload'); 17 | 18 | function autoload($class) 19 | { 20 | require dirname($_SERVER['SCRIPT_FILENAME']) . '//..//' . str_replace('\\', '/', $class) . '.php'; 21 | } 22 | 23 | /************************************* test *************************************/ 24 | 25 | use interpreter\SqlInterpreter; 26 | 27 | try { 28 | //增加数据 29 | SqlInterpreter::db('user')->insert([ 30 | 'nickname' => 'tigerb', 31 | 'mobile' => '1366666666', 32 | 'password' => '123456' 33 | ]); 34 | //删除数据 35 | SqlInterpreter::db('user')->delete([ 36 | 'nickname' => 'tigerb', 37 | 'mobile' => '1366666666', 38 | ]); 39 | //修改数据 40 | SqlInterpreter::db('member')->update([ 41 | 'id' => '1', 42 | 'nickname' => 'tigerbcode' 43 | ]); 44 | //查询数据 45 | SqlInterpreter::db('member')->find([ 46 | 'mobile' => '1366666666', 47 | ]); 48 | } catch (\Exception $e) { 49 | echo 'error:' . $e->getMessage(); 50 | } 51 | -------------------------------------------------------------------------------- /patterns/iterator/Iterator.php: -------------------------------------------------------------------------------- 1 | $name; 25 | } 26 | 27 | /** 28 | * 添加老师 29 | * @param string $name 30 | */ 31 | public function addTeacher($name='') 32 | { 33 | $this->_teachers[] = $name; 34 | } 35 | 36 | /** 37 | * 获取教师迭代器 38 | * 39 | * @return mixed 40 | */ 41 | public function getIterator() 42 | { 43 | return new TeacherIterator($this); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /patterns/iterator/TeacherIterator.php: -------------------------------------------------------------------------------- 1 | _teachers = $school->teachers; 30 | } 31 | 32 | /** 33 | * 是否还有下一个 34 | * 35 | * @return boolean 36 | */ 37 | public function hasNext() 38 | { 39 | if ($this->_index < count($this->_teachers)) { 40 | return true; 41 | } 42 | return false; 43 | } 44 | 45 | /** 46 | * 下一个 47 | * 48 | * @return object 49 | */ 50 | public function next() 51 | { 52 | if (!$this->hasNext()) { 53 | echo NULL; 54 | return; 55 | } 56 | $index = $this->_index + 1; 57 | echo $this->_teachers[$index]; 58 | } 59 | 60 | /** 61 | * 当前 62 | * 63 | * @return mixed 64 | */ 65 | public function current() 66 | { 67 | if (!isset($this->_teachers[$this->_index])) { 68 | echo NULL; 69 | return; 70 | } 71 | $current = $this->_teachers[$this->_index]; 72 | $this->_index += 1; 73 | echo $current . "\n"; 74 | } 75 | 76 | /** 77 | * 当前索引 78 | * 79 | * @return integer 80 | */ 81 | public function index() 82 | { 83 | echo $this->_index; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /patterns/iterator/test.php: -------------------------------------------------------------------------------- 1 | 10 | * @example 运行 php test.php 11 | */ 12 | 13 | 14 | // 注册自加载 15 | spl_autoload_register('autoload'); 16 | 17 | function autoload($class) 18 | { 19 | require dirname($_SERVER['SCRIPT_FILENAME']) . '//..//' . str_replace('\\', '/', $class) . '.php'; 20 | } 21 | 22 | /************************************* test *************************************/ 23 | 24 | use iterator\SchoolExperimental; 25 | 26 | try { 27 | // 初始化一个实验小学 28 | $experimental = new SchoolExperimental(); 29 | // 添加老师 30 | $experimental->addTeacher('Griffin'); 31 | $experimental->addTeacher('Curry'); 32 | $experimental->addTeacher('Mc'); 33 | $experimental->addTeacher('Kobe'); 34 | $experimental->addTeacher('Rose'); 35 | $experimental->addTeacher('Kd'); 36 | // 获取教师迭代器 37 | $iterator = $experimental->getIterator(); 38 | // 打印所有老师 39 | do { 40 | $iterator->current(); 41 | } while ($iterator->hasNext()); 42 | 43 | } catch (\Exception $e) { 44 | echo 'error:' . $e->getMessage(); 45 | } 46 | -------------------------------------------------------------------------------- /patterns/mediator/HouseMediator.php: -------------------------------------------------------------------------------- 1 | doSomthing($person); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /patterns/mediator/Landlord.php: -------------------------------------------------------------------------------- 1 | name}’租出去一件闲置房给‘{$person->name}’ ~ \n"; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /patterns/mediator/Person.php: -------------------------------------------------------------------------------- 1 | _name = $name; 21 | } 22 | 23 | /** 24 | * 魔术方法 25 | * 读取私有属性 26 | * 27 | * @param string $name 属性名称 28 | * @return mixed 29 | */ 30 | function __get($name='') 31 | { 32 | $name = '_' . $name; 33 | return $this->$name; 34 | } 35 | 36 | /** 37 | * 抽象方法 38 | * 39 | * @return mixed 40 | */ 41 | abstract function doSomthing(Person $person); 42 | } 43 | -------------------------------------------------------------------------------- /patterns/mediator/Tenant.php: -------------------------------------------------------------------------------- 1 | rentHouse($this); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /patterns/mediator/test.php: -------------------------------------------------------------------------------- 1 | 12 | * @example 运行 php test.php 13 | */ 14 | 15 | 16 | // 注册自加载 17 | spl_autoload_register('autoload'); 18 | 19 | function autoload($class) 20 | { 21 | require dirname($_SERVER['SCRIPT_FILENAME']) . '//..//' . str_replace('\\', '/', $class) . '.php'; 22 | } 23 | 24 | /************************************* test *************************************/ 25 | 26 | use mediator\Tenant; 27 | use mediator\Landlord; 28 | use mediator\HouseMediator; 29 | 30 | try { 31 | // 初始化一个租客 32 | $tenant = new Tenant('小明'); 33 | 34 | // 小明直接找小梅租房 35 | $landlord = new Landlord('小梅'); 36 | echo $landlord->doSomthing($tenant); 37 | 38 | // 小明通过房屋中介租房 39 | // 初始化一个房屋中介 40 | $mediator = new HouseMediator(); 41 | // 租房 42 | $mediator->rentHouse($tenant); 43 | 44 | } catch (\Exception $e) { 45 | echo 'error:' . $e->getMessage(); 46 | } 47 | -------------------------------------------------------------------------------- /patterns/memento/Editor.php: -------------------------------------------------------------------------------- 1 | _content = $content; 26 | // 打印初始内容 27 | $this->read(); 28 | 29 | // 初始化备忘录插件 30 | $this->_memento = new Memento(); 31 | // 第一次打开编辑器自动保存一次以提供重置状态操作 32 | $this->save($content); 33 | } 34 | 35 | /** 36 | * 写入内容 37 | * 38 | * @param string $value 文本 39 | * @return boolean 40 | */ 41 | function write($value='') 42 | { 43 | $this->_content .= $value; 44 | $this->read(); 45 | } 46 | 47 | /** 48 | * 读取当前内容 49 | * 50 | * @param string $value 文本 51 | * @return boolean 52 | */ 53 | function read() 54 | { 55 | echo $this->_content? $this->_content . "\n": "空文本" . "\n"; 56 | } 57 | 58 | 59 | /** 60 | * 保存内容 61 | * 62 | * @return boolean 63 | */ 64 | function save() 65 | { 66 | $this->_memento->add(clone $this); 67 | } 68 | 69 | /** 70 | * 后退 71 | * 72 | * @return boolean 73 | */ 74 | function undo() 75 | { 76 | // 获取上个状态 77 | $undo = $this->_memento->undo(); 78 | // 重置当前状态为上个状态 79 | $this->_content = $undo->_content; 80 | } 81 | 82 | /** 83 | * 复原 84 | * 85 | * @return boolean 86 | */ 87 | function redo() 88 | { 89 | // 获取开始状态 90 | $undo = $this->_memento->redo(); 91 | // 重置当前状态为开始状态 92 | $this->_content = $undo->_content; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /patterns/memento/Memento.php: -------------------------------------------------------------------------------- 1 | _mementoList, $editor); 21 | } 22 | 23 | /** 24 | * 返回编辑器实例上个状态 25 | * 26 | * @param Editor $editor 编辑器实例 27 | */ 28 | function undo() 29 | { 30 | return array_pop($this->_mementoList); 31 | } 32 | 33 | /** 34 | * 返回编辑器实例开始状态 35 | * 36 | * @param Editor $editor 编辑器实例 37 | */ 38 | function redo() 39 | { 40 | return array_shift($this->_mementoList); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /patterns/memento/test.php: -------------------------------------------------------------------------------- 1 | 12 | * @example 运行 php test.php 13 | */ 14 | 15 | 16 | // 注册自加载 17 | spl_autoload_register('autoload'); 18 | 19 | function autoload($class) 20 | { 21 | require dirname($_SERVER['SCRIPT_FILENAME']) . '//..//' . str_replace('\\', '/', $class) . '.php'; 22 | } 23 | 24 | /************************************* test *************************************/ 25 | 26 | use memento\Editor; 27 | 28 | try { 29 | // 初始化一个编辑器并新建一个空文件 30 | $editor = new Editor(''); 31 | 32 | // 写入一段文本 33 | $editor->write('hello php !'); 34 | // 保存 35 | $editor->save(); 36 | // 修改刚才的文本 37 | $editor->write(' no code no life !'); 38 | // 撤销 39 | $editor->undo(); 40 | $editor->read(); 41 | // 再次修改并保存文本 42 | $editor->write(' life is a struggle !'); 43 | $editor->save(); 44 | // 重置 45 | $editor->redo(); 46 | $editor->read(); 47 | 48 | } catch (\Exception $e) { 49 | echo 'error:' . $e->getMessage(); 50 | } 51 | -------------------------------------------------------------------------------- /patterns/nullObject/NullPerson.php: -------------------------------------------------------------------------------- 1 | _name = $name; 21 | } 22 | 23 | /** 24 | * 魔术方法 25 | * 读取私有属性 26 | * 27 | * @param string $name 属性名称 28 | * @return mixed 29 | */ 30 | function __get($name='') 31 | { 32 | $name = '_' . $name; 33 | return $this->$name; 34 | } 35 | 36 | /** 37 | * 抽象方法 38 | * 39 | * @return mixed 40 | */ 41 | abstract function doSomthing($person); 42 | } 43 | -------------------------------------------------------------------------------- /patterns/nullObject/Student.php: -------------------------------------------------------------------------------- 1 | name}’让学生‘{$this->name}’回答了一道题~ \n"; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /patterns/nullObject/Teacher.php: -------------------------------------------------------------------------------- 1 | doSomthing($this); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /patterns/nullObject/test.php: -------------------------------------------------------------------------------- 1 | 13 | * @example 运行 php test.php 14 | */ 15 | 16 | 17 | // 注册自加载 18 | spl_autoload_register('autoload'); 19 | 20 | function autoload($class) 21 | { 22 | require dirname($_SERVER['SCRIPT_FILENAME']) . '//..//' . str_replace('\\', '/', $class) . '.php'; 23 | } 24 | 25 | /************************************* test *************************************/ 26 | 27 | use nullObject\Teacher; 28 | use nullObject\Student; 29 | 30 | try { 31 | //创建一个老师:路飞 32 | $teacher = new Teacher('路飞'); 33 | 34 | // 创建学生 35 | $mc = new Student('麦迪'); 36 | $kobe = new Student('科比'); 37 | $paul = new Student('保罗'); 38 | 39 | // 老师提问 40 | $teacher->doSomthing($mc); 41 | $teacher->doSomthing($kobe); 42 | $teacher->doSomthing($paul); 43 | $teacher->doSomthing('小李');// 提问了一个班级里不存在人名 44 | 45 | 46 | } catch (\Exception $e) { 47 | echo 'error:' . $e->getMessage(); 48 | } 49 | -------------------------------------------------------------------------------- /patterns/observer/Observable.php: -------------------------------------------------------------------------------- 1 | $name; 31 | } 32 | 33 | /** 34 | * 附加观察者 35 | * @return void 36 | */ 37 | public function attach(ObserverInterface $observer) 38 | { 39 | if (!in_array($observer, $this->_observers, true)) { 40 | $this->_observers[] = $observer; 41 | } 42 | } 43 | 44 | /** 45 | * 解除观察者 46 | * @return void 47 | */ 48 | public function detach(ObserverInterface $observer) 49 | { 50 | foreach ($this->_observers as $k => $v) { 51 | if ($v === $observer) { 52 | unset($this->_observers[$k]); 53 | } 54 | } 55 | } 56 | 57 | /** 58 | * 通知观察者 59 | * @return void 60 | */ 61 | public function notify() 62 | { 63 | foreach ($this->_observers as $v) { 64 | $v->doSomething($this); 65 | } 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /patterns/observer/ObservableInterface.php: -------------------------------------------------------------------------------- 1 | _name . "通知了观察者1 \n"; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /patterns/observer/ObserverExampleTwo.php: -------------------------------------------------------------------------------- 1 | _name . "通知了观察者2 \n"; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /patterns/observer/ObserverInterface.php: -------------------------------------------------------------------------------- 1 | _observers, true)) { 27 | $this->_observers[] = $observer; 28 | } 29 | } 30 | 31 | /** 32 | * 解除观察者 33 | * @param \SplObserver $observer 34 | * @return void 35 | */ 36 | public function detach(\SplObserver $observer) 37 | { 38 | foreach ($this->_observers as $k => $v) { 39 | if ($v === $observer) { 40 | unset($this->_observers[$k]); 41 | } 42 | } 43 | } 44 | 45 | /** 46 | * 通知观察者 47 | * @return void 48 | */ 49 | public function notify() 50 | { 51 | foreach ($this->_observers as $observer) { 52 | $observer->update($this); 53 | } 54 | } 55 | 56 | 57 | /** 58 | * 获取消息 59 | * @return string 60 | */ 61 | public function getMessage() 62 | { 63 | return $this->_message; 64 | } 65 | 66 | public function setMessage($msg) 67 | { 68 | $this->_message = $msg; 69 | } 70 | } 71 | 72 | -------------------------------------------------------------------------------- /patterns/observer/spl/ObserverExampleOne.php: -------------------------------------------------------------------------------- 1 | getMessage() . "通知了观察者1 \n"; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /patterns/observer/spl/ObserverExampleTwo.php: -------------------------------------------------------------------------------- 1 | getMessage() . "通知了观察者2 \n"; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /patterns/observer/spl/test.php: -------------------------------------------------------------------------------- 1 | 9 | * @example 运行 php test.php 10 | */ 11 | 12 | 13 | // 注册自加载 14 | spl_autoload_register('autoload'); 15 | 16 | function autoload($class) 17 | { 18 | require dirname($_SERVER['SCRIPT_FILENAME']) . '//..//' . str_replace('\\', '/', $class) . '.php'; 19 | } 20 | 21 | /************************************* test *************************************/ 22 | 23 | use spl\Observable; 24 | use spl\ObserverExampleOne; 25 | use spl\ObserverExampleTwo; 26 | 27 | // 注册一个被观察者对象 28 | $observable = new Observable(); 29 | // 注册观察者们 30 | $observerExampleOne = new ObserverExampleOne(); 31 | $observerExampleTwo = new ObserverExampleTwo(); 32 | 33 | // 附加观察者 34 | $observable->attach($observerExampleOne); 35 | $observable->attach($observerExampleTwo); 36 | 37 | // 被观察者通知观察者们 38 | $observable->notify(); 39 | -------------------------------------------------------------------------------- /patterns/observer/test.php: -------------------------------------------------------------------------------- 1 | 9 | * @example 运行 php test.php 10 | */ 11 | 12 | 13 | // 注册自加载 14 | spl_autoload_register('autoload'); 15 | 16 | function autoload($class) 17 | { 18 | require dirname($_SERVER['SCRIPT_FILENAME']) . '//..//' . str_replace('\\', '/', $class) . '.php'; 19 | } 20 | 21 | /************************************* test *************************************/ 22 | 23 | use observer\Observable; 24 | use observer\ObserverExampleOne; 25 | use observer\ObserverExampleTwo; 26 | 27 | // 注册一个被观察者对象 28 | $observable = new Observable(); 29 | // 注册观察者们 30 | $observerExampleOne = new ObserverExampleOne(); 31 | $observerExampleTwo = new ObserverExampleTwo(); 32 | 33 | // 附加观察者 34 | $observable->attach($observerExampleOne); 35 | $observable->attach($observerExampleTwo); 36 | 37 | // 被观察者通知观察者们 38 | $observable->notify(); 39 | -------------------------------------------------------------------------------- /patterns/prototype/Prototype.php: -------------------------------------------------------------------------------- 1 | _name = $name; 18 | } 19 | 20 | /** 21 | * 魔术方法 设置属性 22 | * 23 | * @param string $name 属性名称 24 | * @param string $value 属性值 25 | */ 26 | public function __set($name='', $value='') 27 | { 28 | $this->$name = $value; 29 | } 30 | 31 | /** 32 | * 打印对象名称 33 | * 34 | * @return sting 35 | */ 36 | public function getName() 37 | { 38 | echo '我是对象' . $this->_name . " \n\n"; 39 | } 40 | 41 | /** 42 | * 获取原型对象 43 | * 44 | * @return object 45 | */ 46 | public function getPrototype() 47 | { 48 | return clone $this; 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /patterns/prototype/PrototypeAbstract.php: -------------------------------------------------------------------------------- 1 | 9 | * @example 运行 php test.php 10 | */ 11 | 12 | 13 | // 注册自加载 14 | spl_autoload_register('autoload'); 15 | 16 | function autoload($class) 17 | { 18 | require dirname($_SERVER['SCRIPT_FILENAME']) . '//..//' . str_replace('\\', '/', $class) . '.php'; 19 | } 20 | 21 | /************************************* test *************************************/ 22 | 23 | use prototype\Prototype; 24 | 25 | // 创建一个原型对象 26 | $prototype = new Prototype(); 27 | 28 | // 获取一个原型的clone 29 | $prototypeCloneOne = $prototype->getPrototype(); 30 | $prototypeCloneOne->_name = 'one'; 31 | $prototypeCloneOne->getName(); 32 | 33 | // 获取一个原型的clone 34 | $prototypeCloneTwo = $prototype->getPrototype(); 35 | $prototypeCloneTwo->_name = 'two'; 36 | $prototypeCloneTwo->getName(); 37 | 38 | // 再次获取$prototypeCloneOne的名称 39 | $prototypeCloneOne->getName(); 40 | -------------------------------------------------------------------------------- /patterns/proxy/Proxy.php: -------------------------------------------------------------------------------- 1 | _shoesType = $shoesType; 27 | } 28 | 29 | /** 30 | * 生产. 31 | */ 32 | public function product() 33 | { 34 | switch ($this->_shoesType) { 35 | case 'sport': 36 | echo "我可以偷点工减点料"; 37 | $this->_shoes = new ShoesSport(); 38 | break; 39 | case 'skateboard': 40 | echo "我可以偷点工减点料"; 41 | $this->_shoes = new ShoesSkateboard(); 42 | break; 43 | 44 | default: 45 | throw new Exception("shoes type is not available", 404); 46 | break; 47 | } 48 | $this->_shoes->product(); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /patterns/proxy/ShoesInterface.php: -------------------------------------------------------------------------------- 1 | subject = $_subject; 14 | } 15 | 16 | public function doSomething() { 17 | $this->subject->doSomething(); 18 | } 19 | 20 | } -------------------------------------------------------------------------------- /patterns/proxy/common/RealSubject.php: -------------------------------------------------------------------------------- 1 | doSomething(); 22 | 23 | echo "\n--------------------\n"; 24 | 25 | echo "加代理:\n"; 26 | $proxy = new Proxy($subject); 27 | // 代工厂生产运动鞋 28 | $proxy->doSomething(); 29 | } catch (\Exception $e) { 30 | echo $e->getMessage(); 31 | } 32 | -------------------------------------------------------------------------------- /patterns/proxy/dynamic/InvocationHandler.php: -------------------------------------------------------------------------------- 1 | cls = $reflection->getNamespaceName().$reflection->getName(); 20 | $methods = $reflection->getMethods(\ReflectionMethod::IS_PUBLIC); 21 | foreach ($methods as &$method) { 22 | $method = $method->getName(); 23 | } 24 | unset($method); 25 | $this->interface = $methods; 26 | $this->handler = $handler; 27 | $this->reflection = $reflection; 28 | } 29 | 30 | 31 | public static function newProxyInstance($object, $handler) { 32 | return new self(new \ReflectionObject($object), $handler); 33 | } 34 | 35 | public static function newProxyClass($class, $handler) { 36 | return new self(new \ReflectionClass($class), $handler); 37 | } 38 | 39 | function __call($name, $arguments) { 40 | if (in_array($name, $this->interface)) { 41 | $this->handler->invoke($this, $name, $arguments); 42 | } 43 | } 44 | 45 | 46 | } -------------------------------------------------------------------------------- /patterns/proxy/dynamic/RealSubject.php: -------------------------------------------------------------------------------- 1 | obj = $obj; 15 | } 16 | 17 | /** 18 | * @param $proxy 19 | * @param $method 20 | * @param $args 21 | * @return mixed 22 | */ 23 | public function invoke($proxy, $method, $args) 24 | { 25 | return call_user_func_array(array($this->obj, $method), $args); 26 | } 27 | 28 | 29 | } -------------------------------------------------------------------------------- /patterns/proxy/dynamic/test.php: -------------------------------------------------------------------------------- 1 | doSomething(); 25 | echo "\n--------------------\n"; 26 | } catch (\Exception $e) { 27 | echo $e->getMessage(); 28 | } 29 | -------------------------------------------------------------------------------- /patterns/proxy/enforce/Proxy.php: -------------------------------------------------------------------------------- 1 | subject = $_subject; 14 | } 15 | 16 | public function doSomething() { 17 | $this->subject->doSomething(); 18 | } 19 | 20 | public function getProxy() 21 | { 22 | return $this; 23 | } 24 | 25 | 26 | } -------------------------------------------------------------------------------- /patterns/proxy/enforce/RealSubject.php: -------------------------------------------------------------------------------- 1 | isProxy()) 12 | echo "具体的对象处理过程\n"; 13 | else 14 | echo "请使用代理访问"; 15 | } 16 | 17 | public function getProxy() 18 | { 19 | $this->proxy = new Proxy($this); 20 | return $this->proxy; 21 | 22 | } 23 | 24 | private function isProxy() { 25 | return ($this->proxy instanceof Proxy); 26 | } 27 | 28 | } -------------------------------------------------------------------------------- /patterns/proxy/enforce/Subject.php: -------------------------------------------------------------------------------- 1 | doSomething(); 21 | 22 | echo "\n--------------------\n"; 23 | 24 | echo "使用强制代理:\n"; 25 | $proxy = $subject->getProxy(); 26 | // 代工厂生产运动鞋 27 | $proxy->doSomething(); 28 | } catch (\Exception $e) { 29 | echo $e->getMessage(); 30 | } 31 | -------------------------------------------------------------------------------- /patterns/proxy/ext/IProxy.php: -------------------------------------------------------------------------------- 1 | subject = $_subject; 14 | } 15 | 16 | public function doSomething() { 17 | $this->subject->doSomething(); 18 | $this->extension(); 19 | } 20 | 21 | public function extension() 22 | { 23 | echo "实现一个扩展\n"; 24 | } 25 | 26 | 27 | } -------------------------------------------------------------------------------- /patterns/proxy/ext/RealSubject.php: -------------------------------------------------------------------------------- 1 | doSomething(); 21 | 22 | echo "\n--------------------\n"; 23 | 24 | echo "加代理:\n"; 25 | $proxy = new Proxy($subject); 26 | $proxy->doSomething(); 27 | } catch (\Exception $e) { 28 | echo $e->getMessage(); 29 | } 30 | -------------------------------------------------------------------------------- /patterns/proxy/test.php: -------------------------------------------------------------------------------- 1 | 11 | * @example 运行 php test.php 12 | */ 13 | 14 | 15 | // 注册自加载 16 | spl_autoload_register('autoload'); 17 | 18 | function autoload($class) 19 | { 20 | require dirname($_SERVER['SCRIPT_FILENAME']) . '//..//' . str_replace('\\', '/', $class) . '.php'; 21 | } 22 | 23 | /************************************* test *************************************/ 24 | 25 | use proxy\Proxy; 26 | use proxy\ShoesSport; 27 | 28 | try { 29 | echo "未加代理之前:\n"; 30 | // 生产运动鞋 31 | $shoesSport = new ShoesSport(); 32 | $shoesSport->product(); 33 | 34 | echo "\n--------------------\n"; 35 | //----------------------------------- 36 | 37 | echo "加代理:\n"; 38 | // 把运动鞋产品线外包给代工厂 39 | $proxy = new Proxy('sport'); 40 | // 代工厂生产运动鞋 41 | $proxy->product(); 42 | } catch (\Exception $e) { 43 | echo $e->getMessage(); 44 | } 45 | -------------------------------------------------------------------------------- /patterns/proxy/virtual/Proxy.php: -------------------------------------------------------------------------------- 1 | subject == null) 12 | $this->subject = new RealSubject(); 13 | 14 | $this->subject->doSomething(); 15 | } 16 | 17 | } -------------------------------------------------------------------------------- /patterns/proxy/virtual/RealSubject.php: -------------------------------------------------------------------------------- 1 | doSomething(); 21 | } catch (\Exception $e) { 22 | echo $e->getMessage(); 23 | } 24 | -------------------------------------------------------------------------------- /patterns/singleton/Singleton.php: -------------------------------------------------------------------------------- 1 | 8 | * @example 运行 php test.php 9 | */ 10 | 11 | 12 | // 注册自加载 13 | spl_autoload_register('autoload'); 14 | 15 | function autoload($class) 16 | { 17 | require dirname($_SERVER['SCRIPT_FILENAME']) . '//..//' . str_replace('\\', '/', $class) . '.php'; 18 | } 19 | 20 | /************************************* test *************************************/ 21 | 22 | use singleton\Singleton; 23 | 24 | // 获取单例 25 | $instance = Singleton::getInstance(); 26 | $instance->test(); 27 | 28 | // clone对象试试 29 | $instanceClone = clone $instance; 30 | -------------------------------------------------------------------------------- /patterns/state/Farm.php: -------------------------------------------------------------------------------- 1 | _name} \n"; 23 | } 24 | 25 | /** 26 | * 收割 27 | * 28 | * @return string 29 | */ 30 | function harvest() 31 | { 32 | echo "收获了一片 {$this->_name} \n"; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /patterns/state/FarmSpring.php: -------------------------------------------------------------------------------- 1 | _name} \n"; 23 | } 24 | 25 | /** 26 | * 收割 27 | * 28 | * @return string 29 | */ 30 | function harvest() 31 | { 32 | echo "收获了一片 {$this->_name} \n"; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /patterns/state/FarmSummer.php: -------------------------------------------------------------------------------- 1 | _name} \n"; 23 | } 24 | 25 | /** 26 | * 收割 27 | * 28 | * @return string 29 | */ 30 | function harvest() 31 | { 32 | echo "收获了一片 {$this->_name} \n"; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /patterns/state/FarmWinter.php: -------------------------------------------------------------------------------- 1 | _name} \n"; 23 | } 24 | 25 | /** 26 | * 收割 27 | * 28 | * @return string 29 | */ 30 | function harvest() 31 | { 32 | echo "收获了一片 {$this->_name} \n"; 33 | } 34 | 35 | } 36 | -------------------------------------------------------------------------------- /patterns/state/Farmer.php: -------------------------------------------------------------------------------- 1 | _state = new FarmSpring(); 43 | } 44 | if ($currentSeason === 'summer') { 45 | $this->_state = new FarmSummer(); 46 | } 47 | if ($currentSeason === 'autumn') { 48 | $this->_state = new FarmAutumn(); 49 | } 50 | if ($currentSeason === 'winter') { 51 | $this->_state = new FarmWinter(); 52 | } 53 | } 54 | 55 | /** 56 | * 设置下个季节状态 57 | */ 58 | private function nextSeason() 59 | { 60 | $nowKey = (int)array_search($this->_currentSeason, $this->_season); 61 | if ($nowKey < 3) { 62 | $nextSeason = $this->_season[$nowKey+1]; 63 | }else{ 64 | $nextSeason = 'spring'; 65 | } 66 | $this->_currentSeason = $nextSeason; 67 | $this->setState($this->_currentSeason); 68 | } 69 | 70 | /** 71 | * 设置初始状态 72 | */ 73 | function __construct($season = 'spring') 74 | { 75 | $this->_currentSeason = $season; 76 | $this->setState($this->_currentSeason); 77 | } 78 | 79 | /** 80 | * 种植 81 | * 82 | * @return string 83 | */ 84 | function grow() 85 | { 86 | $this->_state->grow(); 87 | } 88 | 89 | /** 90 | * 收割 91 | * 92 | * @return string 93 | */ 94 | function harvest() 95 | { 96 | $this->_state->harvest(); 97 | // 设置下一个季节状态 98 | $this->nextSeason(); 99 | } 100 | 101 | } 102 | -------------------------------------------------------------------------------- /patterns/state/test.php: -------------------------------------------------------------------------------- 1 | 21 | * @example 运行 php test.php 22 | */ 23 | 24 | 25 | // 注册自加载 26 | spl_autoload_register('autoload'); 27 | 28 | function autoload($class) 29 | { 30 | require dirname($_SERVER['SCRIPT_FILENAME']) . '//..//' . str_replace('\\', '/', $class) . '.php'; 31 | } 32 | 33 | /************************************* test *************************************/ 34 | 35 | use state\Farmer; 36 | 37 | try { 38 | // 初始化一个农民 39 | $farmer = new Farmer(); 40 | 41 | // 春季 42 | $farmer->grow(); 43 | $farmer->harvest(); 44 | // 夏季 45 | $farmer->grow(); 46 | $farmer->harvest(); 47 | // 秋季 48 | $farmer->grow(); 49 | $farmer->harvest(); 50 | // 冬季 51 | $farmer->grow(); 52 | $farmer->harvest(); 53 | 54 | } catch (\Exception $e) { 55 | echo 'error:' . $e->getMessage(); 56 | } 57 | -------------------------------------------------------------------------------- /patterns/strategy/StrategyExampleOne.php: -------------------------------------------------------------------------------- 1 | _strategy = $strategy; 26 | } 27 | 28 | /** 29 | * 模拟一个操作 30 | * 31 | * @return mixed 32 | */ 33 | public function someOperation() 34 | { 35 | $this->_strategy->doSomething(); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /patterns/strategy/test.php: -------------------------------------------------------------------------------- 1 | 9 | * @example 运行 php test.php 10 | */ 11 | 12 | 13 | // 注册自加载 14 | spl_autoload_register('autoload'); 15 | 16 | function autoload($class) 17 | { 18 | require dirname($_SERVER['SCRIPT_FILENAME']) . '//..//' . str_replace('\\', '/', $class) . '.php'; 19 | } 20 | 21 | /************************************* test *************************************/ 22 | 23 | use strategy\Substance; 24 | use strategy\StrategyExampleOne; 25 | use strategy\StrategyExampleTwo; 26 | 27 | // 使用策略1 28 | $substanceOne = new Substance(new StrategyExampleOne); 29 | $substanceOne->someOperation(); 30 | 31 | // 使用策略2 32 | $substanceTwo = new Substance(new StrategyExampleTwo); 33 | $substanceTwo->someOperation(); 34 | -------------------------------------------------------------------------------- /patterns/template/Sms.php: -------------------------------------------------------------------------------- 1 | initialize($config); 35 | } 36 | 37 | /** 38 | * 初始化运营商配置 39 | * 40 | * 每个厂商的配置不一定相同,所以子类复写这个方法即可 41 | * 42 | * @param array $config 运营商配置 43 | * @return void 44 | */ 45 | abstract function initialize($config=[]); 46 | 47 | /** 48 | * 生成短信文本 49 | * 50 | * 短信模板和厂商无关 51 | * 52 | * @return void 53 | */ 54 | function makeText() 55 | { 56 | $this->_text .= rand(000000, 999999); 57 | } 58 | 59 | /** 60 | * 厂商发送短信方法 61 | * 62 | * 每个厂商复写这个方法即可 63 | * 64 | * @param integer $mobile 手机号 65 | * @return void 66 | */ 67 | abstract function sendSms($mobile=0); 68 | 69 | /** 70 | * 发送短信 71 | * 72 | * 最终调用的方法,明确了算法顺序 73 | * 74 | * @param integer $mobile 手机号 75 | * @return void 76 | */ 77 | final function send($mobile=0) 78 | { 79 | // 生成文本 80 | $this->makeText(); 81 | // 发送短信 82 | $this->sendSms($mobile); 83 | } 84 | 85 | } 86 | -------------------------------------------------------------------------------- /patterns/template/SmsCompanyOne.php: -------------------------------------------------------------------------------- 1 | _config = $config; 24 | } 25 | 26 | /** 27 | * 厂商发送短信方法 28 | * 29 | * 每个厂商复写这个方法即可 30 | * 31 | * @param integer $mobile 手机号 32 | * @return void 33 | */ 34 | function sendSms($mobile=0) 35 | { 36 | // 实现具体的短信发送方法 37 | echo "厂商‘one’给手机号{$mobile}发送了短信:{$this->_text} \n"; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /patterns/template/SmsCompanyTwo.php: -------------------------------------------------------------------------------- 1 | _config = $config; 24 | } 25 | 26 | /** 27 | * 厂商发送短信方法 28 | * 29 | * 每个厂商复写这个方法即可 30 | * 31 | * @param integer $mobile 手机号 32 | * @return void 33 | */ 34 | function sendSms($mobile=0) 35 | { 36 | // 实现具体的短信发送方法 37 | echo "厂商‘two’给手机号{$mobile}发送了短信:{$this->_text} \n"; 38 | } 39 | 40 | } 41 | -------------------------------------------------------------------------------- /patterns/template/test.php: -------------------------------------------------------------------------------- 1 | 14 | * @example 运行 php test.php 15 | */ 16 | 17 | 18 | // 注册自加载 19 | spl_autoload_register('autoload'); 20 | 21 | function autoload($class) 22 | { 23 | require dirname($_SERVER['SCRIPT_FILENAME']) . '//..//' . str_replace('\\', '/', $class) . '.php'; 24 | } 25 | 26 | /************************************* test *************************************/ 27 | 28 | use template\SmsCompanyOne; 29 | use template\SmsCompanyTwo; 30 | 31 | try { 32 | // 用厂商one发短信 33 | $one = new SmsCompanyOne([ 34 | 'appkey' => 'akjlooolllnn', 35 | ]); 36 | $one->send('13666666666'); 37 | 38 | // 用厂商two发短息 39 | $one = new SmsCompanyTwo([ 40 | 'pwd' => 'adadeooonn', 41 | ]); 42 | $one->send('13666666666'); 43 | 44 | } catch (\Exception $e) { 45 | echo 'error:' . $e->getMessage(); 46 | } 47 | -------------------------------------------------------------------------------- /patterns/thought.md: -------------------------------------------------------------------------------- 1 | ## 设计模式 2 | 3 | ###### 面向对象的设计原则 4 | - 对接口编程,不要对实现编程 5 | - 使用对象之间的组合,减少对继承的使用 6 | - 抽象用于不同的事物,而接口用于事物的行为 7 | 8 | ###### 设计模式的设计原则 9 | - 开闭原则:对扩展开放,对修改封闭 10 | + mean: 实例的内部不可修改,但可以增加新功能 11 | - 依赖倒转:对接口编程,依赖于抽象而不依赖于具体 12 | + mean: 就是把公共的拿出来,定义成抽象类、接口、抽象方法,然后大家再去实现这个抽 13 | 象,实现的方法各有不同,各个实体相互独立没有依赖,各个实体离开谁都能活 14 | - 接口隔离:使用多个接口,而不是对一个接口编程,去依赖降低耦合 15 | + mean: 就是抽象再抽象 16 | - 最少知道:减少内部依赖,尽可能的独立 17 | + mean: 实现依赖注入容器,把依赖的实体注入到一个实例(所谓容器) 18 | - 合成复用:多个独立的实体合成聚合,而不是使用继承 19 | + mean:尽可能不用继承,使用以上三种方式构成代码结构 20 | - 里氏代换:超类(父类)出现的地方,派生类(子类)都可以出现 21 | + mean:能用父类实现的子类也能实现 22 | 23 | ###### 简单设计原则 24 | - 通过所有测试:及需求为上 25 | - 尽可能的消除重复:高内聚低耦合 26 | - 尽可能的清晰表达:可读性 27 | - 更少代码元素:常量,变量,函数,类,包 …… 都属于代码元素,降低复杂性 28 | - 以上四个原则的重要程度依次降低 29 | 30 | > 核心:高内聚松耦合(单一职责),外部依赖,实体对抽象编程,抽象就是分层 31 | -------------------------------------------------------------------------------- /patterns/visitor/AnimailInterface.php: -------------------------------------------------------------------------------- 1 | eat(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /patterns/visitor/VisitorAmerica.php: -------------------------------------------------------------------------------- 1 | 14 | * @example 运行 php test.php 15 | */ 16 | 17 | 18 | // 注册自加载 19 | spl_autoload_register('autoload'); 20 | 21 | function autoload($class) 22 | { 23 | require dirname($_SERVER['SCRIPT_FILENAME']) . '//..//' . str_replace('\\', '/', $class) . '.php'; 24 | } 25 | 26 | /************************************* test *************************************/ 27 | 28 | use visitor\Person; 29 | use visitor\VisitorAsia; 30 | use visitor\VisitorAmerica; 31 | 32 | // 生产一个人的实例 33 | $person = new Person(); 34 | 35 | // 来到了亚洲 36 | $person->eat(new VisitorAsia()); 37 | 38 | // 来到了美洲 39 | $person->eat(new VisitorAmerica()); 40 | -------------------------------------------------------------------------------- /php/magic-function/__call.php: -------------------------------------------------------------------------------- 1 | 8 | */ 9 | 10 | require('./function.php'); 11 | if (!isset($argv[1])) { 12 | die('error: variable is_use_magic is empty'); 13 | } 14 | $is_use_magic = $argv[1]; 15 | 16 | /** 17 | * 18 | */ 19 | class ClassOne 20 | { 21 | public function __construct() 22 | { 23 | # code... 24 | } 25 | 26 | public function test() 27 | { 28 | # code... 29 | } 30 | } 31 | 32 | /** 33 | * 构造函数使用魔术函数__construct 34 | */ 35 | class ClassTwo 36 | { 37 | public function __construct() 38 | { 39 | # code... 40 | } 41 | 42 | public function __call($method, $argus) 43 | { 44 | # code... 45 | } 46 | } 47 | 48 | $a = getmicrotime(); 49 | if ($is_use_magic === 'no_magic') { 50 | $instance = new ClassOne(); 51 | $instance->test(); 52 | }else { 53 | $instance = new ClassTwo(); 54 | $instance->test(); 55 | } 56 | $b = getmicrotime(); 57 | 58 | echo ($b-$a) . "\n"; 59 | -------------------------------------------------------------------------------- /php/magic-function/__callStatic.php: -------------------------------------------------------------------------------- 1 | 8 | */ 9 | 10 | require('./function.php'); 11 | if (!isset($argv[1])) { 12 | die('error: variable is_use_magic is empty'); 13 | } 14 | $is_use_magic = $argv[1]; 15 | 16 | /** 17 | * 存在test静态方法 18 | */ 19 | class ClassOne 20 | { 21 | public function __construct() 22 | { 23 | # code... 24 | } 25 | 26 | public static function test() 27 | { 28 | # code... 29 | } 30 | } 31 | 32 | /** 33 | * 使用重载实现test 34 | */ 35 | class ClassTwo 36 | { 37 | public function __construct() 38 | { 39 | # code... 40 | } 41 | 42 | public static function __callStatic($method, $argus) 43 | { 44 | # code... 45 | } 46 | } 47 | 48 | $a = getmicrotime(); 49 | if ($is_use_magic === 'no_magic') { 50 | ClassOne::test(); 51 | }else { 52 | ClassTwo::test(); 53 | } 54 | $b = getmicrotime(); 55 | 56 | echo ($b-$a) . "\n"; 57 | -------------------------------------------------------------------------------- /php/magic-function/__construct.php: -------------------------------------------------------------------------------- 1 | 8 | */ 9 | 10 | require('./function.php'); 11 | if (!isset($argv[1])) { 12 | die('error: variable is_use_magic is empty'); 13 | } 14 | $is_use_magic = $argv[1]; 15 | 16 | /** 17 | * 构造函数使用类名 18 | */ 19 | class ClassOne 20 | { 21 | public function classOne() 22 | { 23 | # code... 24 | } 25 | } 26 | 27 | /** 28 | * 构造函数使用魔术函数__construct 29 | */ 30 | class ClassTwo 31 | { 32 | public function __construct() 33 | { 34 | # code... 35 | } 36 | } 37 | 38 | $a = getmicrotime(); 39 | if ($is_use_magic === 'no_magic') { 40 | new ClassOne(); 41 | }else { 42 | new ClassTwo(); 43 | } 44 | $b = getmicrotime(); 45 | 46 | echo ($b-$a) . "\n"; 47 | -------------------------------------------------------------------------------- /php/magic-function/__get.php: -------------------------------------------------------------------------------- 1 | 8 | */ 9 | 10 | require('./function.php'); 11 | if (!isset($argv[1])) { 12 | die('error: variable is_use_magic is empty'); 13 | } 14 | $is_use_magic = $argv[1]; 15 | 16 | /** 17 | * 实现公共方法获取私有属性 18 | */ 19 | class ClassOne 20 | { 21 | /** 22 | * 私有属性 23 | * 24 | * @var string 25 | */ 26 | private $someVariable = 'private'; 27 | 28 | public function __construct() 29 | { 30 | # code... 31 | } 32 | 33 | public function getSomeVariable() 34 | { 35 | return $this->someVariable; 36 | } 37 | } 38 | 39 | /** 40 | * 使用_get获取私有属性 41 | */ 42 | class ClassTwo 43 | { 44 | /** 45 | * 私有属性 46 | * 47 | * @var string 48 | */ 49 | private $someVariable = 'private'; 50 | 51 | public function __construct() 52 | { 53 | # code... 54 | } 55 | 56 | public function __get($name = '') 57 | { 58 | return $this->$name; 59 | } 60 | } 61 | 62 | $a = getmicrotime(); 63 | if ($is_use_magic === 'no_magic') { 64 | $instance = new ClassOne(); 65 | $instance->getSomeVariable(); 66 | }else { 67 | $instance = new ClassTwo(); 68 | $instance->someVariable; 69 | } 70 | $b = getmicrotime(); 71 | 72 | echo ($b-$a) . "\n"; 73 | -------------------------------------------------------------------------------- /php/magic-function/__set.php: -------------------------------------------------------------------------------- 1 | 8 | */ 9 | 10 | require('./function.php'); 11 | if (!isset($argv[1])) { 12 | die('error: variable is_use_magic is empty'); 13 | } 14 | $is_use_magic = $argv[1]; 15 | 16 | /** 17 | * 实现公共方法设置私有属性 18 | */ 19 | class ClassOne 20 | { 21 | /** 22 | * 私有属性 23 | * 24 | * @var string 25 | */ 26 | private $someVariable = 'private'; 27 | 28 | public function __construct() 29 | { 30 | # code... 31 | } 32 | 33 | public function setSomeVariable($value = '') 34 | { 35 | $this->someVariable = $value; 36 | } 37 | } 38 | 39 | /** 40 | * 使用_set设置私有属性 41 | */ 42 | class ClassTwo 43 | { 44 | /** 45 | * 私有属性 46 | * 47 | * @var string 48 | */ 49 | private $someVariable = 'private'; 50 | 51 | public function __construct() 52 | { 53 | # code... 54 | } 55 | 56 | public function __set($name = '', $value = '') 57 | { 58 | $this->$name = $value; 59 | } 60 | } 61 | 62 | $a = getmicrotime(); 63 | if ($is_use_magic === 'no_magic') { 64 | $instance = new ClassOne(); 65 | $instance->setSomeVariable('public'); 66 | }else { 67 | $instance = new ClassTwo(); 68 | $instance->someVariable = 'public'; 69 | } 70 | $b = getmicrotime(); 71 | 72 | echo ($b-$a) . "\n"; 73 | -------------------------------------------------------------------------------- /php/magic-function/analysis: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # $1 待读取的文件 3 | # $2 脚本执行次数 4 | # 5 | # sh analysis ./logs/__construct_no_magic_php5.log 10000 6 | sum=0 7 | max=0 8 | min=0 9 | i=0 10 | while read line 11 | do 12 | if [ "$i" -eq 0 ]; then 13 | min=$line 14 | fi 15 | i=$(($i+1)) 16 | sum=$(($sum+$line)) 17 | if [ "$max" -lt "$line" ]; then 18 | max=$line 19 | fi 20 | if [ "$min" -gt "$line" ]; then 21 | min=$line 22 | fi 23 | done < "$1" 24 | echo avg: $(($sum/$2))μm 25 | echo max: $maxμm 26 | echo min: $minμm 27 | -------------------------------------------------------------------------------- /php/magic-function/function.php: -------------------------------------------------------------------------------- 1 | > ./logs/__"$4"_"$2"_"$3".log 24 | i=$(($i+1)) 25 | done 26 | -------------------------------------------------------------------------------- /php/standard.md: -------------------------------------------------------------------------------- 1 |

PHP编码规范及建议

2 | 3 | ### 编码规范 4 | 5 | - PHP代码文件必须以 doSomething(); 254 | 255 | do_something(); 256 | 257 | ``` 258 | 259 | - 控制结构的开始花括号 { 必须 写在声明的同一行,而结束花括号 } 必须 写在主体后自成一行。 260 | 261 | ``` 262 | if ($valueOne === $valueTwo) { 263 | // code... 264 | } 265 | 266 | switch ($valueThree) { 267 | case 'value': 268 | // code... 269 | break; 270 | 271 | default: 272 | // code... 273 | break; 274 | } 275 | 276 | do { 277 | // code... 278 | } while ($valueFour <= 10); 279 | 280 | while ($valueFive <= 10) { 281 | // code... 282 | } 283 | 284 | for ($i = 0; $i < $valueSix; $i++) { 285 | // code... 286 | } 287 | ``` 288 | 289 | - 控制结构的开始左括号后和结束右括号前,都一定不可有空格符。 290 | 291 | ``` 292 | if ($valueOne === $valueTwo) {// 控制结构(右边和)左边不加空格 293 | // code... 294 | } 295 | ``` 296 | 297 | ### 编码建议 298 | 299 | - sql过长 300 | 301 | ``` 302 | // heredoc语法 303 | $sql = << 0 317 | && $b > 0 318 | && $c > 0 319 | && $d > 0 320 | && $e > 0) { 321 | 322 | } 323 | ``` 324 | 325 | - 方法或函数参数大于三个换行 326 | 327 | ``` 328 | public function tooLangFunction( 329 | $valueOne = '', 330 | $valueTwo = '', 331 | $valueThree = '', 332 | $valueFour = '', 333 | $valueFive = '', 334 | $valueSix = '') 335 | { 336 | //coding... 337 | } 338 | ``` 339 | 340 | - 链式操作超过两个 341 | 342 | ``` 343 | $this->nameTest->functionOne() 344 | ->functionTwo() 345 | ->functionThree(); 346 | ``` 347 | 348 | - 数组php5.4以后,使用[] 349 | 350 | ``` 351 | $a = [ 352 | 'aaa' => 'aaa', 353 | 'bbb' => 'bbb' 354 | ]; 355 | ``` 356 | 357 | - 单引号多引号 358 | - 字符串中无变量,单引号 359 | - 字符串中有变量,双引号 360 | 361 | ``` 362 | $str = 'str'; 363 | $arg = "$str"; 364 | ``` 365 | 366 | - 声明类或者方法或函数添加描述&属性描述&作者 367 | 368 | ``` 369 | /** 370 | * 类描述 371 | * 372 | * desc 373 | */ 374 | class StandardExample 375 | { 376 | /** 377 | * 常量描述. 378 | * 379 | * @var string 380 | */ 381 | const THIS_IS_A_CONST = ''; 382 | 383 | /** 384 | * 属性描述. 385 | * 386 | * @var string 387 | */ 388 | public $nameTest = ''; 389 | 390 | /** 391 | * 构造函数. 392 | * 393 | * 构造函数描述 394 | * @author name 395 | * @param string $value 形参名称/描述 396 | * @return 返回值类型 返回值描述 397 | * 返回值类型:string,array,object,mixed(多种,不确定的),void(无返回值) 398 | */ 399 | public function __construct($value = '') 400 | { 401 | // coding... 402 | } 403 | ``` 404 | 405 | - api方法提供测试样例example 406 | 407 | ``` 408 | /** 409 | * 成员方法名称. 410 | * 411 | * 成员方法描述 412 | * 413 | * @param string $value 形参名称/描述 414 | * 415 | * @example domain/api/controller/action?argu1=111&argu2=222 416 | */ 417 | public function testFunction($value = '') 418 | { 419 | // code... 420 | } 421 | ``` 422 | 423 | - 使用try...catch... 424 | 425 | ``` 426 | try { 427 | 428 | // coding... 429 | 430 | } catch (\Exception $e) { 431 | // coding... 432 | } 433 | 434 | ``` 435 | 436 | - 连续调用多个方法(大于3个)使用foreach 437 | 438 | ``` 439 | // 改写doSome为doSomething 440 | class StandardExample 441 | { 442 | /** 443 | * 方法列表 444 | * 445 | * @var array 446 | */ 447 | private $_functionList = []; 448 | 449 | public function __construct($functionList = array()) 450 | { 451 | $this->_functionList = $value; 452 | } 453 | 454 | public function doSome() 455 | { 456 | $this->functionOne(); 457 | $this->functionTwo(); 458 | $this->functionThree(); 459 | $this->functionFour(); 460 | } 461 | 462 | public function doSomething() 463 | { 464 | foreach($this->_functionList as $function) { 465 | $this->$function(); 466 | } 467 | } 468 | 469 | ... 470 | } 471 | ``` 472 | 473 | - 文件顶部进行版权声明 474 | 475 | ``` 476 | // +---------------------------------------------------------------------- 477 | // | Company Name xx服务 478 | // +---------------------------------------------------------------------- 479 | // | Copyright (c) 2017 http://domain All rights reserved. 480 | // +---------------------------------------------------------------------- 481 | // | Author: name 482 | // +---------------------------------------------------------------------- 483 | ``` 484 | -------------------------------------------------------------------------------- /php/standard.php: -------------------------------------------------------------------------------- 1 | 6 | */ 7 | 8 | namespace Standard; // 顶部命名空间 9 | // 空一行 10 | use Test\TestClass;//use引入类 11 | 12 | /** 13 | * 类描述 14 | * 15 | * 类名必须大写开头驼峰. 16 | */ 17 | abstract class StandardExample // {}必须换行 18 | { 19 | /** 20 | * 常量描述. 21 | * 22 | * @var string 23 | */ 24 | const THIS_IS_A_CONST = ''; // 常量全部大写下划线分割 25 | 26 | /** 27 | * 属性描述. 28 | * 29 | * @var string 30 | */ 31 | public $nameTest = ''; // 属性名称建议开头小写驼峰 32 | // 成员属性必须添加public(不能省略), private, protected修饰符 33 | 34 | /** 35 | * 属性描述. 36 | * 37 | * @var string 38 | */ 39 | private $_privateNameTest = ''; // 类私有成员属性,【个人建议】下划线小写开头驼峰 40 | 41 | /** 42 | * 构造函数. 43 | * 44 | * 构造函数描述 45 | * 46 | * @param string $value 形参名称/描述 47 | */ 48 | public function __construct($value = '')// 成员方法必须添加public(不能省略), private, protected修饰符 49 | {// {}必须换行 50 | 51 | $this->nameTest = new TestClass(); 52 | 53 | // 链式操作 54 | $this->nameTest->functionOne() 55 | ->functionTwo() 56 | ->functionThree(); 57 | 58 | // 一段代码逻辑执行完毕 换行 59 | // code... 60 | } 61 | 62 | /** 63 | * 成员方法名称. 64 | * 65 | * 成员方法描述 66 | * 67 | * @param string $value 形参名称/描述 68 | * 69 | * @return 返回值类型 返回值描述 70 | * 返回值类型:string,array,object,mixed(多种,不确定的),void(无返回值) 71 | */ 72 | public function testFunction($value = '')// 成员方法必须小写开头驼峰 73 | { 74 | // code... 75 | } 76 | 77 | /** 78 | * 成员方法名称. 79 | * 80 | * 成员方法描述 81 | * 82 | * @param string $value 形参名称/描述 83 | * 84 | * @return 返回值类型 返回值描述 85 | */ 86 | private function _privateTestFunction($value = '')// 私有成员方法【个人建议】下划线小写开头驼峰 87 | { 88 | // code... 89 | } 90 | 91 | /** 92 | * 成员方法名称. 93 | * 94 | * 成员方法描述 95 | * 96 | * @param string $value 形参名称/描述 97 | * 98 | * @return 返回值类型 返回值描述 99 | */ 100 | public static function staticFunction($value = '')// static位于修饰符之后 101 | { 102 | // code... 103 | } 104 | 105 | /** 106 | * 成员方法名称. 107 | * 108 | * 成员方法描述 109 | * 110 | * @param string $value 形参名称/描述 111 | * 112 | * @return 返回值类型 返回值描述 113 | */ 114 | abstract public function abstractFunction($value = ''); // abstract位于修饰符之前 115 | 116 | /** 117 | * 成员方法名称. 118 | * 119 | * 成员方法描述 120 | * 121 | * @param string $value 形参名称/描述 122 | * 123 | * @return 返回值类型 返回值描述 124 | */ 125 | final public function finalFunction($value = '')// final位于修饰符之前 126 | { 127 | // code... 128 | } 129 | 130 | /** 131 | * 成员方法名称. 132 | * 133 | * 成员方法描述 134 | * 135 | * @param string $valueOne 形参名称/描述 136 | * @param string $valueTwo 形参名称/描述 137 | * @param string $valueThree 形参名称/描述 138 | * @param string $valueFour 形参名称/描述 139 | * @param string $valueFive 形参名称/描述 140 | * @param string $valueSix 形参名称/描述 141 | * 142 | * @return 返回值类型 返回值描述 143 | */ 144 | public function tooLangFunction( 145 | $valueOne = '', // 变量命名可小写开头驼峰或者下划线命名,个人那习惯,据说下划线可读性好 146 | $valueTwo = '', 147 | $valueThree = '', 148 | $valueFour = '', 149 | $valueFive = '', 150 | $valueSix = '')// 参数过多换行 151 | { 152 | if ($valueOne === $valueTwo) {// 控制结构=>后加空格,同{一行,(右边和)左边不加空格 153 | // code... 154 | } 155 | 156 | switch ($valueThree) { 157 | case 'value': 158 | // code... 159 | break; 160 | 161 | default: 162 | // code... 163 | break; 164 | } 165 | 166 | do { 167 | // code... 168 | } while ($valueFour <= 10); 169 | 170 | while ($valueFive <= 10) { 171 | // code... 172 | } 173 | 174 | for ($i=0; $i < $valueSix; $i++) { 175 | // code... 176 | } 177 | } 178 | } 179 | -------------------------------------------------------------------------------- /pit.md: -------------------------------------------------------------------------------- 1 | ###### 记一些坑 2 | 3 | ``` 4 | //phpfpm配置 5 | 6 | pm.max_children = 最大并发数 7 | 8 | 详细的答案: 9 | pm.max_children 表示 php-fpm 能启动的子进程的最大数量。 10 | 因为 php-fpm 是多进程单线程同步模式,即一个子进程同时最多处理一个请求,所以子进程数等于最大并发数。 11 | 但是实际使用中一般不用考虑,因为php默认配置为动态均衡的子进程管理,不用手动设置这些配置。 12 | ``` 13 | 14 | ``` 15 | //日志调试方法 16 | 17 | /** 18 | * 超级调试 19 | * 20 | * 调试非本地环境或分布式环境,通过Log查看变量传递 21 | * 写入变量值到\var\log\php_super_debug.log 22 | * @param mixed $data 日志数据 23 | * @param string $log_path 日志路径 24 | * @param string $log_name 日志名称 25 | * @return void 26 | */ 27 | function super_debug($data, $log_path='\var\log\', $log_name='debug') 28 | { 29 | error_log(json_encode($data, JSON_UNESCAPED_UNICODE)."\n", 3, $log_path.$log_name); 30 | } 31 | ``` 32 | 33 | ``` 34 | // php实现下载图片 35 | 36 | header('Content-type: image/jpeg'); 37 | header('Content-Disposition: attachment; filename=download_name.jpg'); 38 | readfile($yourFilePath); 39 | ``` 40 | 41 | ``` 42 | // php5.6开始干掉了@语法,php上传图片兼容版本写法 43 | 44 | if (class_exists('\CURLFile')) { 45 | curl_setopt($curl, CURLOPT_SAFE_UPLOAD, true); 46 | $data = array('file' => new \CURLFile(realpath($destination)));//5.5+ 47 | } else { 48 | if (defined('CURLOPT_SAFE_UPLOAD')) { 49 | curl_setopt($curl, CURLOPT_SAFE_UPLOAD, false); 50 | } 51 | $data = array('file' => '@' . realpath($destination));//<=5.5 52 | } 53 | ``` 54 | 55 | ``` 56 | // 序列化与反序列化 57 | 58 | 概念: 59 | 序列化:把变量(所有类型)转成能传输和储存的变量(不丢失原变量的属性和结构) 60 | 反序列化:把字符串转成原变量 61 | 62 | 函数: 63 | 序列化:serialize, json_encode(不能序列化对象) 64 | 反序列化:unserialize, json_decode 65 | ``` 66 | 67 | ``` 68 | // 组合和聚合的区别 69 | 组合:A类在实例化对象的过程中产生了对B类的引用 70 | 聚合:A类在实例化对象的过程中,不会立即实例化B类,而是等待外界非A类的对象传递 71 | 72 | ``` 73 | 74 | ``` 75 | // 记一个坑 76 | 77 | ip2long函数 78 | - 32位系统下会转成带符号的int,范围-2^31~2^31-1 79 | - 64位系统下会转成不带符号的int,范围0~2^32-1 80 | ``` 81 | 82 | ``` 83 | // static和self的区别 84 | 85 | 第一种解释: 86 | - static: 代表当前所引用的类 87 | - self: 代表当前代码片断所在的类 88 | 89 | 第二种解释: 90 | 如果子类和父类都有一个“A”方法。那么 91 | - static: 会调用到子类的A方法 92 | - self: 会调用到当前类的A方法,如果在子类中self::A(),将会调用到子类的A方法,如果在父类中,将会调用父类的A方法。 93 | 94 | ``` 95 | 96 | ``` 97 | //json_encode 使用时的一个坑 98 | 99 | json_encode有中文时,需要加入JSON_UNESCAPED_UNICODE,json_encode($data, JSON_UNESCAPED_UNICODE); (PHP版本要求:必须PHP5.4+),否则中文会转义为Unicode编码。 100 | 101 | 例如: 102 | $arr = array('a'=>'只有所有者有读和写的权' ,'b'=>'所有者有读和写的权限,组用户只有读的权限'); 103 | echo json_encode($arr); 104 | 105 | 1. 不加JSON_UNESCAPED_UNICODE时,结果为: 106 | {"a":"\u53ea\u6709\u6240\u6709\u8005\u6709\u8bfb\u548c\u5199\u7684\u6743","b":"\u6240\u6709\u8005\u6709\u8bfb\u548c\u5199\u7684\u6743\u9650\uff0c\u7ec4\u7528\u6237\u53ea\u6709\u8bfb\u7684\u6743\u9650"} 107 | 108 | 2. 加了JSON_UNESCAPED_UNICODE时,结果为:{"a":"只有所有者有读和写的权","b":"所有者有读和写的权限,组用户只有读的权限"} 109 | ``` 110 | 111 | ###### 技巧 112 | 113 | - linux 114 | + df -h: 更易读的查看磁盘空间 115 | + du -h --max-depth=1 file_path:查看文件夹占用的空间,--max-depth文件夹下显示层级 116 | + sudo rm -rf \*.log:清理日志 117 | + socket 118 | * http socket = ip:port 119 | * unix domain socket: unix process communication 进程间通信 120 | + ubuntu16.04安装php5源:sudo apt-add-repository ppa:ondrej/php 121 | + ubuntu中文支持:sudo apt-get install language-pack-zh-hant language-pack-zh-hans 122 |    + debian使用lantern无法启动: 安装依赖apt-get install libappindicator3-1 123 | + 查看端口占用:lsof -i:[端口号] / netstat -a(显示所有选项,默认不显示LISTEN)p(显示关联的程序)n(不显示别名显示数字) | grep [端口号] 124 | 125 | - php: 126 | + json_encode($data, JSON_UNESCAPED_UNICODE) 127 | + php的自定义头信息都可以使用$_SERVER['HTTP_*']来获取 128 | + 如果你想知道脚本开始执行(译注:即服务器端收到客户端请求)的时刻,使用$_SERVER[‘REQUEST_TIME’]要好于time() 129 | + error_log(json_encode($data, JSON_UNESCAPED_UNICODE), 1/3, 'tigerbcoder@gmail.com/log_path') 130 | + sudo watch service php5.6-fpm status 131 | + foreach后的好习惯reset指针位置,unset掉$key,$value 132 | + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); 133 | + laravel ['lærə,vɛl] 134 | + php中的语言结构:echo,exit(),print,empty(),unset(),isset(),list(),eval(),array() 135 | - git: 136 | + git commit --amend 重写最近commit message 137 | + git cherry-pick 移花接木 138 | - composer: 139 | + 修改包来源: sudo composer config repositories.包名 vcs 包地址 140 | 141 | 142 | ###### PHP的不足 143 | - PHP还是有很多不足的地方,比如无法进行高效的运算 144 | -------------------------------------------------------------------------------- /redis/cache.php: -------------------------------------------------------------------------------- 1 | 8 | * @example php cache.php 9 | */ 10 | 11 | $redis = new \Redis(); 12 | $redis->connect('127.0.0.1', 6379); 13 | 14 | // 缓存数据 15 | $redis->set('cache-key', json_encode([ 16 | 'data-list' => '这是个缓存数据~' 17 | ]), JSON_UNESCAPED_UNICODE); 18 | echo "字符串缓存成功~ \n\n"; 19 | 20 | // 获取缓存数据 21 | $data = $redis->get('cache-key'); 22 | echo "读取缓存数据为: \n"; 23 | print_r(json_decode($data,true)); 24 | -------------------------------------------------------------------------------- /redis/optimistic-lock.php: -------------------------------------------------------------------------------- 1 | 8 | * @example php optimistic-lock.php 9 | */ 10 | 11 | $redis = new \Redis(); 12 | $redis->connect('127.0.0.1', 6379); 13 | 14 | // 监视 count 值 15 | $redis->watch('count'); 16 | 17 | // 开启事务 18 | $redis->multi(); 19 | 20 | // 操作count 21 | $time = time(); 22 | $redis->set('count', $time); 23 | 24 | //------------------------------- 25 | /** 26 | * 模拟并发下其他进程进行set count操作 请执行下面操作 27 | * 28 | * redis-cli 执行 $redis->set('count', 'is simulate'); 模拟其他终端 29 | */ 30 | sleep(10); 31 | //------------------------------- 32 | 33 | // 提交事务 34 | $res = $redis->exec(); 35 | 36 | if ($res) { 37 | // 成功... 38 | echo 'success:' . $time; 39 | return; 40 | } 41 | 42 | // 失败... 43 | echo 'fail:' . $time; 44 | -------------------------------------------------------------------------------- /redis/pessmistic-lock.php: -------------------------------------------------------------------------------- 1 | 8 | * @example php pessmistic-lock.php 9 | */ 10 | 11 | $timeout = 5000; 12 | 13 | $redis = new \Redis(); 14 | $redis->connect('127.0.0.1', 6379); 15 | 16 | do { 17 | $microtime = microtime(true) * 1000; 18 | $microtimeout = $microtime+$timeout+1; 19 | // 上锁 20 | $isLock = $redis->setnx('lock.count', $microtimeout); 21 | if (!$isLock) { 22 | $getTime = $redis->get('lock.count'); 23 | if ($getTime > $microtime) { 24 | // 睡眠 降低抢锁频率 缓解redis压力 25 | usleep(5000); 26 | // 未超时继续等待 27 | continue; 28 | } 29 | // 超时,抢锁,可能有几毫秒级时间差可忽略 30 | $previousTime = $redis->getset('lock.count', $microtimeout); 31 | if ((int)$previousTime < $microtime) { 32 | break; 33 | } 34 | } 35 | } while (!$isLock); 36 | 37 | $count = $redis->get('count')? : 0; 38 | 39 | // file_put_contents('/var/log/count.log.1', ($count+1)); 40 | 41 | // 业务逻辑 42 | echo "执行count加1操作~ \n\n"; 43 | $redis->set('count', $count+1); 44 | // 删除锁 45 | $redis->del('lock.count'); 46 | // 打印count值 47 | $count = $redis->get('count'); 48 | echo "count值为:$count \n"; 49 | -------------------------------------------------------------------------------- /redis/queue.php: -------------------------------------------------------------------------------- 1 | 8 | * @example php cache.php 9 | */ 10 | 11 | $redis = new \Redis(); 12 | $redis->connect('127.0.0.1', 6379); 13 | 14 | // 进队列 15 | $userId = mt_rand(000000, 999999); 16 | $redis->rpush('QUEUE_NAME',json_encode(['user_id' => $userId])); 17 | $userId = mt_rand(000000, 999999); 18 | $redis->rpush('QUEUE_NAME',json_encode(['user_id' => $userId])); 19 | $userId = mt_rand(000000, 999999); 20 | $redis->rpush('QUEUE_NAME',json_encode(['user_id' => $userId])); 21 | echo "数据进队列成功 \n"; 22 | 23 | // 查看队列 24 | $res = $redis->lrange('QUEUE_NAME', 0, 1000); 25 | echo "当前队列数据为: \n"; 26 | print_r($res); 27 | 28 | echo "----------------------------- \n"; 29 | 30 | // 出队列 31 | $redis->lpop('QUEUE_NAME'); 32 | echo "数据出队列成功 \n"; 33 | 34 | // 查看队列 35 | $res = $redis->lrange('QUEUE_NAME', 0, 1000); 36 | echo "当前队列数据为: \n"; 37 | print_r($res); 38 | -------------------------------------------------------------------------------- /redis/subscribe-publish/publish.php: -------------------------------------------------------------------------------- 1 | 8 | * @example php publish.php 9 | */ 10 | 11 | //发布 12 | $redis = new \Redis(); 13 | $redis->connect('127.0.0.1', 6379); 14 | $redis->publish('msg', '来自msg频道的推送'); 15 | echo "msg频道消息推送成功~ \n"; 16 | $redis->close(); 17 | -------------------------------------------------------------------------------- /redis/subscribe-publish/subscribe.php: -------------------------------------------------------------------------------- 1 | 8 | * @example php subscribe.php 9 | */ 10 | 11 | // ini_set(‘default_socket_timeout’, -1); 12 | 13 | $redis = new \Redis(); 14 | $redis->pconnect('127.0.0.1', 6379); 15 | 16 | //订阅 17 | echo "订阅msg这个频道,等待消息推送... \n"; 18 | $redis->subscribe(['msg'], 'callfun'); 19 | function callfun($redis, $channel, $msg) 20 | { 21 | print_r([ 22 | 'redis' => $redis, 23 | 'channel' => $channel, 24 | 'msg' => $msg 25 | ]); 26 | } 27 | -------------------------------------------------------------------------------- /redis/test.php: -------------------------------------------------------------------------------- 1 | 6 | * @example php test.php 7 | */ 8 | 9 | // 参数 10 | $method = ''; 11 | if (isset($argv[1])) { 12 | $method = $argv[1]; 13 | } 14 | $path = dirname($_SERVER['SCRIPT_FILENAME']); 15 | 16 | /*---------------------------- cache ---------------------------------*/ 17 | 18 | if ($method === 'cache') { 19 | require($path . '/cache.php'); 20 | die; 21 | } 22 | 23 | /*---------------------------- queue ---------------------------------*/ 24 | 25 | if ($method === 'queue') { 26 | require($path . '/queue.php'); 27 | die; 28 | } 29 | 30 | /*---------------------------- p-lock ---------------------------------*/ 31 | 32 | if ($method === 'p-lock') { 33 | require($path . '/pessmistic-lock.php'); 34 | die; 35 | } 36 | 37 | /*---------------------------- o-lock ---------------------------------*/ 38 | 39 | if ($method === 'o-lock') { 40 | require($path . '/optimistic-lock.php'); 41 | die; 42 | } 43 | 44 | /*---------------------------- sub ---------------------------------*/ 45 | 46 | if ($method === 'sub') { 47 | require($path . '/subscribe-publish/subscribe.php'); 48 | die; 49 | } 50 | 51 | /*---------------------------- pub ---------------------------------*/ 52 | 53 | if ($method === 'pub') { 54 | require($path . '/subscribe-publish/publish.php'); 55 | die; 56 | } 57 | 58 | /*---------------------------- warning ---------------------------------*/ 59 | 60 | echo "\n"; 61 | echo "参数有误,正确示例:php {$path}/test.php p-lock \n"; 62 | echo "====================================== \n"; 63 | echo "参数列表: \n"; 64 | print_r([ 65 | '缓存' => 'cache', 66 | '队列' => 'queue', 67 | '悲观锁' => 'p-lock', 68 | '乐观锁' => 'o-lock', 69 | '消息订阅/推送' => [ 70 | '订阅' => 'sub', 71 | '推送' => 'pub' 72 | ], 73 | ]); 74 | --------------------------------------------------------------------------------