-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathatom.xml
686 lines (412 loc) · 567 KB
/
atom.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Lsc’s Home</title>
<subtitle>Soldiers who don't want to be generals are not good soldiers</subtitle>
<link href="/atom.xml" rel="self"/>
<link href="http://blog.feifan.news/"/>
<updated>2019-12-17T05:48:28.270Z</updated>
<id>http://blog.feifan.news/</id>
<author>
<name>LiuShuaiCai</name>
</author>
<generator uri="http://hexo.io/">Hexo</generator>
<entry>
<title>GCC基本使用</title>
<link href="http://blog.feifan.news/2019/11/25/gcc/"/>
<id>http://blog.feifan.news/2019/11/25/gcc/</id>
<published>2019-11-25T14:02:30.000Z</published>
<updated>2019-12-17T05:48:28.270Z</updated>
<content type="html"><![CDATA[<h2 id="1、GCC编译流程"><a href="#1、GCC编译流程" class="headerlink" title="1、GCC编译流程"></a>1、GCC编译流程</h2><p><code>GCC</code>编译器在编译<code>C语言</code>程序时需要经过以下四步:</p><ol><li>预处理:将C语言源程序预处理,生成<code>.i</code>文件</li><li>编译:预处理后的<code>.i</code>文件编译成为汇编语言,生成<code>.s</code>文件</li><li>汇编:将汇编语言文件经过汇编,生成目标文件<code>.o</code>文件</li><li>链接:将各个模块的<code>.o</code>文件链接起来,生成可执行的程序文件<a id="more"></a>备注:可执行程序的内部是一系列计算机指令和数据的集合,它们都是二进制形式的,CPU 可以直接识别,毫无障碍</li></ol><h2 id="2、GCC常用命令"><a href="#2、GCC常用命令" class="headerlink" title="2、GCC常用命令"></a>2、GCC常用命令</h2><div class="table-container"><table><thead><tr><th style="text-align:center">编译选项</th><th style="text-align:center">选项意义 </th></tr></thead><tbody><tr><td style="text-align:center">-E</td><td style="text-align:center">预处理指定的源文件,但不进行编译,生成.i文件</td></tr><tr><td style="text-align:center">-S</td><td style="text-align:center">编译指定的源文件,但不进行汇编,生成.s文件</td></tr><tr><td style="text-align:center">-c</td><td style="text-align:center">编译、汇编指定的源文件,但不进行链接,生成.o文件</td></tr><tr><td style="text-align:center"> -o [file1] [file2]</td><td style="text-align:center">将文件 file2 编译成可执行文件 file1</td></tr><tr><td style="text-align:center"> -I directory</td><td style="text-align:center">指定 include 包含文件的搜索目录 </td></tr><tr><td style="text-align:center"> -g</td><td style="text-align:center">生成调试信息,该程序可以被调试器调试</td></tr></tbody></table></div><h2 id="3、GCC实例"><a href="#3、GCC实例" class="headerlink" title="3、GCC实例"></a>3、GCC实例</h2><p>下面展示GCC的编译过程,实例如下:<br><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string"><stdio.h></span></span></span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="built_in">puts</span>(<span class="string">"GCC常用命令"</span>);</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><h3 id="3-1、预处理-Pre-processing"><a href="#3-1、预处理-Pre-processing" class="headerlink" title="3.1、预处理(Pre-processing)"></a>3.1、预处理(Pre-processing)</h3><p>在该阶段,编译器将C源代码中的包含的头文件如stdio.h编译进来,用户可以使用gcc的选项”-E”进行查看。<br>执行命令:<code>gcc -E gcc.c -o gcc.i</code>。</p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">[<span class="number">0</span>:<span class="number">18</span>:<span class="number">35</span>] liushuaicai:gcc $ gcc -E gcc.c -o gcc.i</span><br><span class="line">[<span class="number">0</span>:<span class="number">18</span>:<span class="number">59</span>] liushuaicai:gcc $ ls</span><br><span class="line">gcc.c gcc.i</span><br></pre></td></tr></table></figure><h3 id="3-2、编译阶段-Compiling"><a href="#3-2、编译阶段-Compiling" class="headerlink" title="3.2、编译阶段(Compiling)"></a>3.2、编译阶段(Compiling)</h3><p>第二步进行的是编译阶段,在这个阶段中,Gcc首先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的工作,在检查无误后,Gcc把代码翻译 成汇编语言。用户可以使用”-S”选项来进行查看,该选项只进行编译而不进行汇编,生成汇编代码。<br>执行命令:<code>gcc -S gcc.i -o gcc.s</code></p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">[<span class="number">0</span>:<span class="number">24</span>:<span class="number">44</span>] liushuaicai:gcc $ gcc -S gcc.i -o gcc.s</span><br><span class="line">[<span class="number">0</span>:<span class="number">25</span>:<span class="number">18</span>] liushuaicai:gcc $ ls</span><br><span class="line">gcc.c gcc.i gcc.s</span><br></pre></td></tr></table></figure><h3 id="3-3、汇编阶段-Assembling"><a href="#3-3、汇编阶段-Assembling" class="headerlink" title="3.3、汇编阶段(Assembling)"></a>3.3、汇编阶段(Assembling)</h3><p>汇编阶段是把编译阶段生成的”.s”文件转成二进制目标代码,选项 -c。<br>执行命令:<code>gcc -c gcc.s -o gcc.o</code></p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">[<span class="number">0</span>:<span class="number">25</span>:<span class="number">19</span>] liushuaicai:gcc $ gcc -c gcc.s -o gcc.o</span><br><span class="line">[<span class="number">0</span>:<span class="number">28</span>:<span class="number">17</span>] liushuaicai:gcc $ ls</span><br><span class="line">gcc.c gcc.i gcc.o gcc.s</span><br></pre></td></tr></table></figure><h3 id="3-4、链接阶段-Link"><a href="#3-4、链接阶段-Link" class="headerlink" title="3.4、链接阶段(Link)"></a>3.4、链接阶段(Link)</h3><p>在成功编译之后,就进入了链接阶段。<br>执行命令:<code>gcc gcc.o -o gcc.out</code></p><figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">0</span>:<span class="number">30</span>:<span class="number">04</span>] liushuaicai:gcc $ gcc gcc.o -o gcc.out</span><br><span class="line">[<span class="number">0</span>:<span class="number">32</span>:<span class="number">50</span>] liushuaicai:gcc $ ls</span><br><span class="line">gcc.c gcc.i gcc.o gcc.out gcc.s</span><br><span class="line">[<span class="number">0</span>:<span class="number">32</span>:<span class="number">51</span>] liushuaicai:gcc $ ./gcc.out</span><br><span class="line">GCC常用命令</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
<h2 id="1、GCC编译流程"><a href="#1、GCC编译流程" class="headerlink" title="1、GCC编译流程"></a>1、GCC编译流程</h2><p><code>GCC</code>编译器在编译<code>C语言</code>程序时需要经过以下四步:</p>
<ol>
<li>预处理:将C语言源程序预处理,生成<code>.i</code>文件</li>
<li>编译:预处理后的<code>.i</code>文件编译成为汇编语言,生成<code>.s</code>文件</li>
<li>汇编:将汇编语言文件经过汇编,生成目标文件<code>.o</code>文件</li>
<li>链接:将各个模块的<code>.o</code>文件链接起来,生成可执行的程序文件
</summary>
<category term="GCC" scheme="http://blog.feifan.news/categories/GCC/"/>
<category term="GCC" scheme="http://blog.feifan.news/tags/GCC/"/>
<category term="CC" scheme="http://blog.feifan.news/tags/CC/"/>
</entry>
<entry>
<title>Supervisor 进程管理</title>
<link href="http://blog.feifan.news/2019/06/28/supervisor/"/>
<id>http://blog.feifan.news/2019/06/28/supervisor/</id>
<published>2019-06-27T23:21:43.000Z</published>
<updated>2019-12-17T05:48:34.311Z</updated>
<content type="html"><![CDATA[<p><img src="/images/supervisor.png" alt="supervisor"><br><a id="more"></a></p>]]></content>
<summary type="html">
<p><img src="/images/supervisor.png" alt="supervisor"><br>
</summary>
<category term="Linux" scheme="http://blog.feifan.news/categories/Linux/"/>
<category term="supervisor" scheme="http://blog.feifan.news/tags/supervisor/"/>
</entry>
<entry>
<title>Monolog - 为PHP创建</title>
<link href="http://blog.feifan.news/2019/05/04/monolog/"/>
<id>http://blog.feifan.news/2019/05/04/monolog/</id>
<published>2019-05-04T04:58:07.000Z</published>
<updated>2019-05-06T15:50:38.788Z</updated>
<content type="html"><![CDATA[<p><img src="/images/monolog.png" alt="monolog"><br>在我们的平常工作中,通过日志排查问题、收集数据等是很常见的方法,Monolog 就是专门为PHP的日志而创建的库,它让日志记录变得更加方便。<br><a id="more"></a><br>Monolog 的特点: </p><pre><code>Monolog 将您的日志发送到文件,套接字,收件箱,数据库和各种 Web 服务;实现了 PSR-3 接口,您可以在自己的库中键入提示,以保持最大的互操作性;</code></pre><h2 id="1、安装方法"><a href="#1、安装方法" class="headerlink" title="1、安装方法"></a>1、安装方法</h2><p>创建一个目录,初始化 composer 包<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">composer init</span><br></pre></td></tr></table></figure></p><p>一路点击 <code>Enter</code> 键创建 <code>composer.json</code> 文件。<br>安装 monolog 包<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">composer require monolog/monolog</span><br></pre></td></tr></table></figure></p><p>结构目录如下:</p><pre><code>.├── composer.json├── composer.lock└── vendor ├── autoload.php ├── composer ├── monolog └── psr4 directories, 3 files</code></pre><h2 id="2、基本用法"><a href="#2、基本用法" class="headerlink" title="2、基本用法"></a>2、基本用法</h2><p>以下来自<a href="https://github.com/Seldaek/monolog" target="_blank" rel="noopener">官方</a>实例:<br><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"><?php</span></span><br><span class="line"><span class="keyword">use</span> <span class="title">Monolog</span>\<span class="title">Logger</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">Monolog</span>\<span class="title">Handler</span>\<span class="title">StreamHandler</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// create a log channel</span></span><br><span class="line">$log = <span class="keyword">new</span> Logger(<span class="string">'name'</span>);</span><br><span class="line">$log->pushHandler(<span class="keyword">new</span> StreamHandler(<span class="string">'path/to/your.log'</span>, Logger::WARNING));</span><br><span class="line"></span><br><span class="line"><span class="comment">// add records to the log</span></span><br><span class="line">$log->warning(<span class="string">'Foo'</span>);</span><br><span class="line">$log->error(<span class="string">'Bar'</span>);</span><br></pre></td></tr></table></figure></p><h2 id="3、使用说明"><a href="#3、使用说明" class="headerlink" title="3、使用说明"></a>3、使用说明</h2><h3 id="3-1、核心概念"><a href="#3-1、核心概念" class="headerlink" title="3.1、核心概念"></a>3.1、核心概念</h3><p>每个 Logger 实例都有一个「通道(channel)」和一个「处理器(handler)栈」。<br><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// create a log channel</span></span><br><span class="line">$log = <span class="keyword">new</span> Logger(<span class="string">'name'</span>);</span><br><span class="line"><span class="comment">// create a handler</span></span><br><span class="line">$log->pushHandler(<span class="keyword">new</span> StreamHandler(<span class="string">'./log/stat/'</span>.date(<span class="string">'Ymd'</span>).<span class="string">'.log'</span>, Logger::WARNING));</span><br></pre></td></tr></table></figure></p><p>每次向记录器添加记录时,都会遍历一遍「处理器(handler)栈」,每个处理器都会判断是否处理该条记录,如果处理,遍历结束。<br><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// add records to the log</span></span><br><span class="line">$log->warning(<span class="string">'Foo'</span>);</span><br></pre></td></tr></table></figure></p><p>warning 方法<br><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">warning</span><span class="params">($message, array $context = array<span class="params">()</span>)</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">$this</span>->addRecord(<span class="keyword">static</span>::WARNING, $message, $context);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">addRecord</span><span class="params">($level, $message, array $context = array<span class="params">()</span>)</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="comment">// 如果处理器栈为空,直接输出记录</span></span><br><span class="line"> <span class="keyword">if</span> (!<span class="keyword">$this</span>->handlers) {</span><br><span class="line"> <span class="keyword">$this</span>->pushHandler(<span class="keyword">new</span> StreamHandler(<span class="string">'php://stderr'</span>, <span class="keyword">static</span>::DEBUG));</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">// 记录等级的名称-WARNING</span></span><br><span class="line"> $levelName = <span class="keyword">static</span>::getLevelName($level);</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 检查是否有任何处理程序将处理此消息,以便我们可以提前返回并保存周期</span></span><br><span class="line"><span class="comment"> * check if any handler will handle this message so we can return early and save cycles</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> $handlerKey = <span class="keyword">null</span>;</span><br><span class="line"> reset(<span class="keyword">$this</span>->handlers);</span><br><span class="line"> <span class="comment">// 循环遍历处理器栈</span></span><br><span class="line"> <span class="keyword">while</span> ($handler = current(<span class="keyword">$this</span>->handlers)) {</span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * +------------------------------------------------</span></span><br><span class="line"><span class="comment"> * + 判断是否处理该条记录,只要record的级别大于处理器的级别,就处理该条记录</span></span><br><span class="line"><span class="comment"> * +------------------------------------------------</span></span><br><span class="line"><span class="comment"> * + public function isHandling(array $record)</span></span><br><span class="line"><span class="comment"> * + {</span></span><br><span class="line"><span class="comment"> * + return $record['level'] >= $this->level;</span></span><br><span class="line"><span class="comment"> * + }</span></span><br><span class="line"><span class="comment"> * +------------------------------------------------</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">if</span> ($handler->isHandling(<span class="keyword">array</span>(<span class="string">'level'</span> => $level))) {</span><br><span class="line"> $handlerKey = key(<span class="keyword">$this</span>->handlers);</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> next(<span class="keyword">$this</span>->handlers);</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">// 如果没有处理器,返回false</span></span><br><span class="line"> <span class="keyword">if</span> (<span class="keyword">null</span> === $handlerKey) {</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 设置时区</span></span><br><span class="line"> <span class="keyword">if</span> (!<span class="keyword">static</span>::$timezone) {</span><br><span class="line"> <span class="keyword">static</span>::$timezone = <span class="keyword">new</span> \DateTimeZone(date_default_timezone_get() ?: <span class="string">'UTC'</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">// php7.1+ always has microseconds enabled, so we do not need this hack</span></span><br><span class="line"> <span class="keyword">if</span> (<span class="keyword">$this</span>->microsecondTimestamps && PHP_VERSION_ID < <span class="number">70100</span>) {</span><br><span class="line"> $ts = \DateTime::createFromFormat(<span class="string">'U.u'</span>, sprintf(<span class="string">'%.6F'</span>, microtime(<span class="keyword">true</span>)), <span class="keyword">static</span>::$timezone);</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> $ts = <span class="keyword">new</span> \DateTime(<span class="keyword">null</span>, <span class="keyword">static</span>::$timezone);</span><br><span class="line"> }</span><br><span class="line"> $ts->setTimezone(<span class="keyword">static</span>::$timezone);</span><br><span class="line"></span><br><span class="line"> $record = <span class="keyword">array</span>(</span><br><span class="line"> <span class="string">'message'</span> => (string) $message,</span><br><span class="line"> <span class="string">'context'</span> => $context,</span><br><span class="line"> <span class="string">'level'</span> => $level,</span><br><span class="line"> <span class="string">'level_name'</span> => $levelName,</span><br><span class="line"> <span class="string">'channel'</span> => <span class="keyword">$this</span>->name,</span><br><span class="line"> <span class="string">'datetime'</span> => $ts,</span><br><span class="line"> <span class="string">'extra'</span> => <span class="keyword">array</span>(),</span><br><span class="line"> );</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> <span class="comment">// 对额外的数据进行处理</span></span><br><span class="line"> <span class="keyword">foreach</span> (<span class="keyword">$this</span>->processors <span class="keyword">as</span> $processor) {</span><br><span class="line"> $record = call_user_func($processor, $record);</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">// 写入日志</span></span><br><span class="line"> <span class="keyword">while</span> ($handler = current(<span class="keyword">$this</span>->handlers)) {</span><br><span class="line"> <span class="keyword">if</span> (<span class="keyword">true</span> === $handler->handle($record)) {</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> next(<span class="keyword">$this</span>->handlers);</span><br><span class="line"> }</span><br><span class="line"> } <span class="keyword">catch</span> (<span class="keyword">Exception</span> $e) {</span><br><span class="line"> <span class="keyword">$this</span>->handleException($e, $record);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">true</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><h3 id="3-2、日志级别"><a href="#3-2、日志级别" class="headerlink" title="3.2、日志级别"></a>3.2、日志级别</h3><p>Monolog支持 <a href="http://tools.ietf.org/html/rfc5424" target="_blank" rel="noopener">RFC 5424</a> 描述的日志记录级别</p><div class="table-container"><table><thead><tr><th>Level</th><th>Number</th><th>Desc</th></tr></thead><tbody><tr><td>DEBUG</td><td>100</td><td>调试:详细的调试信息</td></tr><tr><td>INFO</td><td>200</td><td>信息:关注的事件。示例:用户登录、SQL日志</td></tr><tr><td>NOTICE</td><td>250</td><td>注意:正常但重要的事件</td></tr><tr><td>WARNING</td><td>300</td><td>警告:非错误发生的例外情况。示例:使用不推荐使用的API,使用不当的API,不一定错误的不良内容</td></tr><tr><td>ERROR</td><td>400</td><td>错误:运行时错误,不需要立即执行,但通常应记录和监视</td></tr><tr><td>CRITICAL</td><td>500</td><td>严重:危急情况。示例:应用程序组件不可用,意外异常</td></tr><tr><td>ALERT</td><td>550</td><td>警报:必须立即采取行动。示例:整个网站关闭,数据库不可用等。这应该触发SMS警报并唤醒您</td></tr><tr><td>EMERGENCY</td><td>600</td><td>紧急情况:系统无法使用</td></tr></tbody></table></div><h3 id="3-3、在日志中添加额外数据"><a href="#3-3、在日志中添加额外数据" class="headerlink" title="3.3、在日志中添加额外数据"></a>3.3、在日志中添加额外数据</h3><p>Monolog 提供了两种不同的方法来实现在日志中添加额外的数据:</p><ul><li><strong>使用日志记录上下文</strong><br>第一种方式是上下文,可以给日志传递一个数组:<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$log->warning(<span class="string">'Foo'</span>, [<span class="string">'name'</span> => <span class="string">'lsc'</span>]);</span><br></pre></td></tr></table></figure></li></ul><p>打印日志:</p><pre><code>[2019-05-06 09:49:52] name.WARNING: Foo {"name":"lsc"} []</code></pre><p>简单的处理程序(例如StreamHandler)将简单地将数组格式化为字符串,但更丰富的处理程序可以利用上下文(例如,FirePHP能够以非常方式显示数组,没研究怎么使用)。</p><ul><li><strong>使用处理器</strong><br>第二种方法是使用处理器为所有记录添加额外数据。处理器可以是任何可调用的。他们将获取记录作为参数,并且必须在最终更改extra它的一部分后返回它。<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">$log->pushProcessor(<span class="function"><span class="keyword">function</span><span class="params">($record)</span> </span>{</span><br><span class="line"> $record[<span class="string">'message'</span>] = <span class="string">'Hello '</span> . $record[<span class="string">'message'</span>];</span><br><span class="line"> $record[<span class="string">'extra'</span>][<span class="string">'age'</span>] = <span class="number">28</span>;</span><br><span class="line"> <span class="keyword">return</span> $record;</span><br><span class="line">});</span><br></pre></td></tr></table></figure></li></ul><p>打印日志:</p><pre><code>[2019-05-06 09:56:55] name.WARNING: Hello Foo {"name":"lsc"} {"age":28}</code></pre><h3 id="3-4、利用通道"><a href="#3-4、利用通道" class="headerlink" title="3.4、利用通道"></a>3.4、利用通道</h3><p>通道是识别记录与应用程序的哪个部分相关的好方法。这在大型应用程序中很有用(并且由Symfony中的MonologBundle使用)。<br>例如:多个Logger实例共享一个写入单个日志文件的处理器。<br><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"><?php</span></span><br><span class="line"><span class="keyword">require_once</span> <span class="string">"./vendor/autoload.php"</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">use</span> <span class="title">Monolog</span>\<span class="title">Logger</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">Monolog</span>\<span class="title">Handler</span>\<span class="title">StreamHandler</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// Create some handlers</span></span><br><span class="line">$stream = <span class="keyword">new</span> StreamHandler(<span class="string">'./log/log2.log'</span>, Logger::DEBUG);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 创建一个Logger实例</span></span><br><span class="line">$logger = <span class="keyword">new</span> Logger(<span class="string">'channel1'</span>);</span><br><span class="line">$logger->pushHandler($stream);</span><br><span class="line">$logger->error(<span class="string">'this is channel1'</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 创建一个新的Logger实例</span></span><br><span class="line">$logger2 = <span class="keyword">new</span> Logger(<span class="string">'channel2'</span>);</span><br><span class="line">$logger2->pushHandler($stream);</span><br><span class="line">$logger2->error(<span class="string">'this is channel2'</span>);</span><br><span class="line"></span><br><span class="line"><span class="comment">// 复制 channel2 的实例</span></span><br><span class="line">$logger3 = $logger->withName(<span class="string">'channel2'</span>);</span><br><span class="line">$logger3->error(<span class="string">'this is logger3'</span>);</span><br></pre></td></tr></table></figure></p><p>打印日志:</p><pre><code>[2019-05-06 02:08:42] channel1.ERROR: this is channel1 [] [][2019-05-06 02:08:42] channel2.ERROR: this is channel2 [] [][2019-05-06 02:08:42] channel2.ERROR: this is logger3 [] []</code></pre><p>流处理器 StreamHandler 的参数:</p><div class="table-container"><table><thead><tr><th>名称</th><th>类型</th><th>默认值</th><th>描述</th></tr></thead><tbody><tr><td>stream</td><td>resource 或者 string</td><td>无(必传)</td><td>文件流</td></tr><tr><td>level</td><td>int</td><td>100(debug)</td><td>将触发此处理程序的最低日志记录级别</td></tr><tr><td>bubble</td><td>bool</td><td>true</td><td>消息处理后,指示消息是否推送到其他通道</td></tr><tr><td>filePermission</td><td>int 或者 null</td><td>644</td><td>日志文件权限</td></tr><tr><td>useLocking</td><td>bool</td><td>false</td><td>写入之前尝试锁定日志文件</td></tr></tbody></table></div><h3 id="3-5、自定义日志格式"><a href="#3-5、自定义日志格式" class="headerlink" title="3.5、自定义日志格式"></a>3.5、自定义日志格式</h3><p>在 Monolog 中,可以通过 <code>setFormatter</code> 方法设置自定义的日志格式:<br><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"><?php</span></span><br><span class="line"><span class="keyword">require_once</span> <span class="string">"./vendor/autoload.php"</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">use</span> <span class="title">Monolog</span>\<span class="title">Logger</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">Monolog</span>\<span class="title">Handler</span>\<span class="title">StreamHandler</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">Monolog</span>\<span class="title">Formatter</span>\<span class="title">LineFormatter</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">Monolog</span>\<span class="title">Formatter</span>\<span class="title">JsonFormatter</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// 创建处理器</span></span><br><span class="line">$stream = <span class="keyword">new</span> StreamHandler(<span class="string">'./log/log3.log'</span>, Logger::DEBUG);</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 自定义日志格式</span></span><br><span class="line"><span class="comment"> * </span></span><br><span class="line"><span class="comment"> * <span class="doctag">@var</span> string $dateFormat 时间格式</span></span><br><span class="line"><span class="comment"> * 默认时间格式:"Y-m-d H:i:s"</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line">$dateFormat = <span class="string">"Y-m-d H:i:s"</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@var</span> string $output 输出格式</span></span><br><span class="line"><span class="comment"> * 默认输出格式:"[%datetime%] %channel%.%level_name%: %message% %context% %extra%\n"</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line">$output = <span class="string">"%datetime%#%channel%#%level_name%#%message% %context% %extra%\n"</span>;</span><br><span class="line"><span class="comment">// 格式化日志</span></span><br><span class="line">$formatter = <span class="keyword">new</span> LineFormatter($output, $dateFormat);</span><br><span class="line">$stream->setFormatter($formatter);</span><br><span class="line"><span class="comment">// $stream->setFormatter(new JsonFormatter());</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">// 创建一个Logger实例</span></span><br><span class="line">$logger = <span class="keyword">new</span> Logger(<span class="string">'channel'</span>);</span><br><span class="line">$logger->pushHandler($stream);</span><br><span class="line">$logger->error(<span class="string">'自定义日志格式'</span>);</span><br></pre></td></tr></table></figure></p><p>打印日志:</p><pre><code>2019-05-06 03:02:25#channel#ERROR#自定义日志格式 [] []</code></pre><h2 id="参考文章"><a href="#参考文章" class="headerlink" title="参考文章"></a>参考文章</h2><p><a href="https://learnku.com/articles/8108/the-log-system-of-laravel-monolog" target="_blank" rel="noopener">Laravel 的日志系统 - monolog</a><br><a href="https://github.com/Seldaek/monolog" target="_blank" rel="noopener">官方文档</a><br>想了解更多可以查看官方文档。</p>]]></content>
<summary type="html">
<p><img src="/images/monolog.png" alt="monolog"><br>在我们的平常工作中,通过日志排查问题、收集数据等是很常见的方法,Monolog 就是专门为PHP的日志而创建的库,它让日志记录变得更加方便。<br>
</summary>
<category term="PHP" scheme="http://blog.feifan.news/categories/PHP/"/>
<category term="PHP" scheme="http://blog.feifan.news/tags/PHP/"/>
</entry>
<entry>
<title>JWT 小结</title>
<link href="http://blog.feifan.news/2019/04/15/jwt-php/"/>
<id>http://blog.feifan.news/2019/04/15/jwt-php/</id>
<published>2019-04-15T04:30:34.000Z</published>
<updated>2019-05-06T15:38:02.753Z</updated>
<content type="html"><![CDATA[<p><img src="/images/jwt-php2.jpg" alt="JWT小结"><br>通过 <a href="https://jwt.io/introduction" target="_blank" rel="noopener">官方文档</a> 对 JWT 做了初步的 <a href="/2019/04/11/jwt/">了解</a>,又参考了一些好的文章总结了一下。<br><a id="more"></a></p><h2 id="1、JWT-组成"><a href="#1、JWT-组成" class="headerlink" title="1、JWT 组成"></a>1、JWT 组成</h2><p>JWT 由三部分组成:header + payload + signature,这三部分用 base64 编码后,最终 Token 由点(.)将编码后的字符串连接起来。具体流程如下:<br><img src="/images/jwt-php.jpg" alt="JWT-PHP"><br>备注:如果图片看不清楚,可以看<a href="http://note.youdao.com/noteshare?id=a14eab7c8b5aea1d0c79419d8e96138b" target="_blank" rel="noopener">源文件</a>,下面再大致的说一下三个部分内容:</p><h3 id="1-1、Header-头信息"><a href="#1-1、Header-头信息" class="headerlink" title="1.1、Header 头信息"></a>1.1、Header 头信息</h3><p>Header 通常由两部分组成:<strong>签名类型</strong>(即“JWT”) 和 <strong>签名算法</strong>(例如 HMAC SHA256 或 RSA )。<br>例如:</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">{</span><br><span class="line"> <span class="string">"alg"</span>: <span class="string">"HS256"</span>,</span><br><span class="line"> <span class="string">"typ"</span>: <span class="string">"JWT"</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>Header 部分的信息一般是必须的,有开发人员自己提前定义的。签名算法(alg)是必不可少的,因为后面获取签名要使用该算法,常用算法:HS256,HS384,HS512,RS256,RS384,RS512,ES256,ES384,ES512,PS256,PS384,PS512。</p><h3 id="1-2、Payload-载荷"><a href="#1-2、Payload-载荷" class="headerlink" title="1.2、Payload 载荷"></a>1.2、Payload 载荷</h3><p>Payload 包含的是需要验证的信息,下面是一般常规的<a href="https://tools.ietf.org/html/rfc7519#section-4.1" target="_blank" rel="noopener">验证属性</a>:</p><div class="table-container"><table><thead><tr><th style="text-align:left">属性</th><th style="text-align:left">全拼</th><th style="text-align:left">说明</th></tr></thead><tbody><tr><td style="text-align:left">iss</td><td style="text-align:left">Issuer</td><td style="text-align:left">该 JWT 的签发者</td></tr><tr><td style="text-align:left">iat</td><td style="text-align:left">Issued At</td><td style="text-align:left">签发时间</td></tr><tr><td style="text-align:left">exp</td><td style="text-align:left">Expiration Time</td><td style="text-align:left">过期时间,这里是一个 Unix 时间戳</td></tr><tr><td style="text-align:left">nbf</td><td style="text-align:left">Not Before</td><td style="text-align:left">该时间之前不接收处理该 Token</td></tr><tr><td style="text-align:left">sub</td><td style="text-align:left">Subject</td><td style="text-align:left">该 JWT 所面向的用户</td></tr><tr><td style="text-align:left">aud</td><td style="text-align:left">Audience</td><td style="text-align:left">接收该 JWT 的一方</td></tr><tr><td style="text-align:left">jti</td><td style="text-align:left">JWT ID</td><td style="text-align:left">该 Token 的唯一标识</td></tr></tbody></table></div><p>在 <a href="/2019/04/11/jwt/">JWT 简介</a> 中已经介绍过,Payload 有三种类型声明 registered、public 和 private,例如:<br><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">array</span>(</span><br><span class="line"> <span class="string">'iss'</span> => <span class="string">'lsc'</span>,</span><br><span class="line"> <span class="string">'iat'</span> => time(),</span><br><span class="line"> <span class="string">'exp'</span> => time() + <span class="number">20</span>,</span><br><span class="line"> <span class="string">'nbf'</span> => time(),</span><br><span class="line"> <span class="string">'sub'</span> => <span class="string">'admin.com'</span>,</span><br><span class="line"> <span class="string">'aud'</span> => <span class="string">'www.admin.com'</span>,</span><br><span class="line"> <span class="string">'jti'</span> => md5(uniqid(<span class="string">'JWT'</span>).time()),</span><br><span class="line"> <span class="string">'uid'</span> => <span class="number">123</span>,</span><br><span class="line"> <span class="string">'userName'</span> => <span class="string">'sweet'</span></span><br><span class="line">);</span><br></pre></td></tr></table></figure></p><p>这些属性都是可选的,不是必须的,自己也可以自定义一些属性。<br>当然我们也可以把一些常用的非私密的信息放在 Payload 中,来减少一些数据库的查询。</p><h3 id="1-3、Signature-签名"><a href="#1-3、Signature-签名" class="headerlink" title="1.3、Signature 签名"></a>1.3、Signature 签名</h3><p>签名是对 Header 和 Payload 通过签名算法(Header[‘alg’])加密后编码的字符串,主要用于验证,防止用户修改 Token 信息。</p><pre><code>key = 'secretkey'unsignedToken = encodeBase64(header) + '.' + encodeBase64(payload)signature = HMAC-SHA256(key, unsignedToken)</code></pre><p>最后生成 Token</p><pre><code>token = encodeBase64(header) + '.' + encodeBase64(payload) + '.' + encodeBase64(signature)</code></pre><h2 id="2、JWT-的工作方式"><a href="#2、JWT-的工作方式" class="headerlink" title="2、JWT 的工作方式"></a>2、JWT 的工作方式</h2><p>用户在登录成功之后的每次请求都会带上 JWT,通常 JWT 放在 Header 头信息中的 Authorization 字段中,表示方法如下:</p><pre><code>Authorization: Bearer <token></code></pre><p>JWT 应用的基本使用流程:</p><pre><code>1、账户密码登录成功后;2、根据验证信息获取 Token,返还给客户端,由客户端保存在 localstorage 或者 cookie 中;3、之后的每次请求,在头信息中 `Authorization:Bearer <token>` ,到达服务端;4、服务端接收到请求之后,通过签名以及时间的验证,判断所传 Token 是否有效;5、有效:返回服务端数据,无效:重新登录备注:我们还需要将服务器设置为接受来自所有域的请求,用Access-Control-Allow-Origin: *˜</code></pre><h2 id="3、PHP-实现-JWT"><a href="#3、PHP-实现-JWT" class="headerlink" title="3、PHP 实现 JWT"></a>3、PHP 实现 JWT</h2><p>下面是我参考 <a href="https://learnku.com/articles/21951" target="_blank" rel="noopener">PHP 使用 jwt 用户身份认证 </a> ,整理了一下代码如下:<br><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br><span class="line">252</span><br><span class="line">253</span><br><span class="line">254</span><br><span class="line">255</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"><?php</span></span><br><span class="line"><span class="class"><span class="keyword">interface</span> <span class="title">JwtInterface</span></span></span><br><span class="line"><span class="class"></span>{</span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 获取 Token</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> array $header 头信息</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> array $payload JWT载荷</span></span><br><span class="line"><span class="comment"> * </span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> string</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">getToken</span><span class="params">()</span>:<span class="title">string</span></span>;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 验证 Token 是否有效,默认验证 exp nbf iat时间</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> string $token 需要验证的 Token 值</span></span><br><span class="line"><span class="comment"> * </span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> bool</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">verifyToken</span><span class="params">(string $token)</span>:<span class="title">array</span></span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Jwt</span> <span class="keyword">implements</span> <span class="title">JwtInterface</span></span></span><br><span class="line"><span class="class"></span>{</span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 默认的头部信息</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@property</span> string alg 生成 signature 的算法</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@property</span> string typ 类型</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">private</span> $header = <span class="keyword">array</span>(</span><br><span class="line"> <span class="string">'alg'</span> => <span class="string">'HS256'</span>,</span><br><span class="line"> <span class="string">'typ'</span> => <span class="string">'JWT'</span></span><br><span class="line"> );</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * alg 对应的算法方式</span></span><br><span class="line"><span class="comment"> * </span></span><br><span class="line"><span class="comment"> * <span class="doctag">@property</span> array $algConfig</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">private</span> $algConfig = <span class="keyword">array</span>(</span><br><span class="line"> <span class="string">'HS256'</span> => <span class="string">'sha256'</span>,</span><br><span class="line"> );</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * JWT 的有效载荷</span></span><br><span class="line"><span class="comment"> * </span></span><br><span class="line"><span class="comment"> * <span class="doctag">@property</span> array $payload</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">private</span> $payload;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 使用 HMAC 生成信息摘要时所使用的密钥</span></span><br><span class="line"><span class="comment"> * </span></span><br><span class="line"><span class="comment"> * <span class="doctag">@property</span> string $key;</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">private</span> $key = <span class="string">'123456'</span>;</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 初始化 JWT 的有效载荷</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__construct</span><span class="params">()</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 默认的有效载荷,非必须</span></span><br><span class="line"><span class="comment"> * </span></span><br><span class="line"><span class="comment"> * <span class="doctag">@property</span> string iss (Issuer) 该 JWT 的签发者</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@property</span> int iat (Issued At) 签发时间</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@property</span> int exp (Expiration Time) 过期时间</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@property</span> int nbf (Not Before) 该时间之前不接收处理该 Token</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@property</span> string sub (Subject) 该 JWT 所面向的用户</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@property</span> string aud (Audience) 接收该 JWT 的一方</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@property</span> string jti (JWT ID) 该 Token 的唯一标识</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">$this</span>->payload = <span class="keyword">array</span>(</span><br><span class="line"> <span class="string">'iss'</span> => <span class="string">'lsc'</span>,</span><br><span class="line"> <span class="string">'iat'</span> => time(),</span><br><span class="line"> <span class="string">'exp'</span> => time() + <span class="number">20</span>,</span><br><span class="line"> <span class="string">'nbf'</span> => time(),</span><br><span class="line"> <span class="string">'sub'</span> => <span class="string">'admin.com'</span>,</span><br><span class="line"> <span class="string">'aud'</span> => <span class="string">'www.admin.com'</span>,</span><br><span class="line"> <span class="string">'jti'</span> => md5(uniqid(<span class="string">'JWT'</span>).time())</span><br><span class="line"> );</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 设置头信息 Header</span></span><br><span class="line"><span class="comment"> * </span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> array $header </span></span><br><span class="line"><span class="comment"> * </span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> $this</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">setHeader</span><span class="params">(array $header)</span>:<span class="title">Jwt</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="keyword">$this</span>->header = array_merge(<span class="keyword">$this</span>->header, $header);</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">$this</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 设置 JWT 的有效载荷</span></span><br><span class="line"><span class="comment"> * </span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> array $payload</span></span><br><span class="line"><span class="comment"> * </span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> $this</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">setPayload</span><span class="params">(array $payload)</span>:<span class="title">Jwt</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="keyword">$this</span>->payload = array_merge(<span class="keyword">$this</span>->payload, $payload);</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">$this</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 设置密钥</span></span><br><span class="line"><span class="comment"> * </span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> string $key</span></span><br><span class="line"><span class="comment"> * </span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> $this</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">setKey</span><span class="params">(string $key)</span>:<span class="title">Jwt</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="keyword">if</span>($key){</span><br><span class="line"> <span class="keyword">$this</span>->key = $key;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">$this</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * https://jwt.io/ 中base64UrlEncode编码实现</span></span><br><span class="line"><span class="comment"> * </span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> string $input 需要编码的字符串</span></span><br><span class="line"><span class="comment"> * </span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> string</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">private</span> <span class="function"><span class="keyword">function</span> <span class="title">base64UrlEncode</span><span class="params">(string $input)</span>:<span class="title">string</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="keyword">return</span> str_replace(<span class="string">'='</span>, <span class="string">''</span>, strtr(base64_encode($input), <span class="string">'+/'</span>, <span class="string">'-_'</span>));</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * https://jwt.io/ 中base64UrlEncode解码实现</span></span><br><span class="line"><span class="comment"> * </span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> string $input 需要解码的字符串</span></span><br><span class="line"><span class="comment"> * </span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> string</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">private</span> <span class="function"><span class="keyword">function</span> <span class="title">base64UrlDecode</span><span class="params">(string $input)</span>:<span class="title">string</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> $remainder = strlen($input) % <span class="number">4</span>;</span><br><span class="line"> <span class="keyword">if</span> ($remainder) {</span><br><span class="line"> $addlen = <span class="number">4</span> - $remainder;</span><br><span class="line"> $input .= str_repeat(<span class="string">'='</span>, $addlen);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> base64_decode(strtr($input, <span class="string">'-_'</span>, <span class="string">'+/'</span>));</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * https://jwt.io/ 中HMACSHA256签名实现</span></span><br><span class="line"><span class="comment"> * </span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> string $input 为base64UrlEncode(header).".".base64UrlEncode(payload)</span></span><br><span class="line"><span class="comment"> * </span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> string</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">private</span> <span class="function"><span class="keyword">function</span> <span class="title">signature</span><span class="params">(string $input, string $alg)</span>:<span class="title">string</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">$this</span>->base64UrlEncode(</span><br><span class="line"> hash_hmac(</span><br><span class="line"> <span class="keyword">$this</span>->algConfig[$alg],</span><br><span class="line"> $input,</span><br><span class="line"> <span class="keyword">$this</span>->key,</span><br><span class="line"> <span class="keyword">true</span></span><br><span class="line"> )</span><br><span class="line"> );</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 获取jwt token</span></span><br><span class="line"><span class="comment"> * </span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> string</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">getToken</span><span class="params">()</span>:<span class="title">string</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="keyword">if</span> (<span class="keyword">$this</span>->payload && <span class="keyword">$this</span>->header) {</span><br><span class="line"> $base64Header = <span class="keyword">$this</span>->base64UrlEncode(json_encode(<span class="keyword">$this</span>->header, JSON_UNESCAPED_UNICODE));</span><br><span class="line"> $base64Payload = <span class="keyword">$this</span>->base64UrlEncode(json_encode(<span class="keyword">$this</span>->payload, JSON_UNESCAPED_UNICODE));</span><br><span class="line"> $token = $base64Header .<span class="string">'.'</span>. $base64Payload.<span class="string">'.'</span>.<span class="keyword">$this</span>->signature($base64Header .<span class="string">'.'</span>. $base64Payload, <span class="keyword">$this</span>->header[<span class="string">'alg'</span>]);</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> $token = <span class="string">''</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> $token;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 验证 token 是否有效,默认只验证 exp, nbf, iat 时间</span></span><br><span class="line"><span class="comment"> * </span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> string $token 需要验证的 token</span></span><br><span class="line"><span class="comment"> * </span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> array</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">verifyToken</span><span class="params">(string $token)</span>:<span class="title">array</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> $tokens = explode(<span class="string">'.'</span>, $token);</span><br><span class="line"> <span class="keyword">if</span> (count($tokens) != <span class="number">3</span>) {</span><br><span class="line"> <span class="keyword">echo</span> <span class="string">'Token 格式不正确'</span>; </span><br><span class="line"> <span class="keyword">return</span> [];</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 列出 Header、Payload、Signature</span></span><br><span class="line"> <span class="keyword">list</span>($base64Header, $base64Payload, $sign) = $tokens;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 获取 JWT 算法</span></span><br><span class="line"> $base64DecodeHeader = json_decode(<span class="keyword">$this</span>->base64UrlDecode($base64Header), JSON_OBJECT_AS_ARRAY);</span><br><span class="line"> <span class="keyword">if</span> (!<span class="keyword">isset</span>($base64DecodeHeader[<span class="string">'alg'</span>]) || !$base64DecodeHeader[<span class="string">'alg'</span>]) {</span><br><span class="line"> <span class="keyword">echo</span> <span class="string">'JWT 算法不能为空'</span>;</span><br><span class="line"> <span class="keyword">return</span> [];</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 验证签名</span></span><br><span class="line"> <span class="keyword">if</span> (<span class="keyword">$this</span>->signature($base64Header.<span class="string">'.'</span>.$base64Payload, $base64DecodeHeader[<span class="string">'alg'</span>]) !== $sign) {</span><br><span class="line"> <span class="keyword">echo</span> <span class="string">'签名认证失败'</span>;</span><br><span class="line"> <span class="keyword">return</span> [];</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> $payload = json_decode(<span class="keyword">$this</span>->base64UrlDecode($base64Payload), JSON_OBJECT_AS_ARRAY);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 签发时间大于当前服务器时间验证失败</span></span><br><span class="line"> <span class="keyword">if</span> (<span class="keyword">isset</span>($payload[<span class="string">'iat'</span>]) && $payload[<span class="string">'iat'</span>] > time()) {</span><br><span class="line"> <span class="keyword">echo</span> <span class="string">'签发时间大于当前服务器时间'</span>;</span><br><span class="line"> <span class="keyword">return</span> [];</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 过期时间小于当前服务器时间验证失败</span></span><br><span class="line"> <span class="keyword">if</span> (<span class="keyword">isset</span>($payload[<span class="string">'exp'</span>]) && $payload[<span class="string">'exp'</span>] < time()) {</span><br><span class="line"> <span class="keyword">echo</span> <span class="string">'过期时间小于当前服务器时间'</span>;</span><br><span class="line"> <span class="keyword">return</span> [];</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 该 nbf 时间之前不接收处理该 Token</span></span><br><span class="line"> <span class="keyword">if</span> (<span class="keyword">isset</span>($payload[<span class="string">'nbf'</span>]) && $payload[<span class="string">'nbf'</span>] > time()) {</span><br><span class="line"> <span class="keyword">echo</span> <span class="string">'该 nbf 时间之前不接收处理该 Token'</span>;</span><br><span class="line"> <span class="keyword">return</span> [];</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 返回 JWT 的有效载荷</span></span><br><span class="line"> <span class="keyword">return</span> $payload;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">$jwt = <span class="keyword">new</span> Jwt();</span><br><span class="line"></span><br><span class="line">$token = $jwt->getToken();</span><br><span class="line"><span class="comment">// echo $token;</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">$payload = $jwt->verifyToken($token);</span><br><span class="line">print_r($payload);</span><br></pre></td></tr></table></figure></p><p>打印结果如下:</p><pre><code>Array( [iss] => lsc [iat] => 1555435646 [exp] => 1555435666 [nbf] => 1555435646 [sub] => admin.com [aud] => www.admin.com [jti] => 28bc53b6c411a7362951fdaf50fa075f)</code></pre><p>这个小 Demo 包含了获取 Token,以及验证 Token 是否正确,功能较为简洁,但很容易理解,更能帮助理解这个过程。</p><h2 id="4、注意事项"><a href="#4、注意事项" class="headerlink" title="4、注意事项"></a>4、注意事项</h2><p>由于 Token 中的信息是公开的,所以在使用的过程中,最好注意以下几点:</p><ul><li>不要将私密信息放在 Token 中;</li><li>最好结合 SSL 使用(我也没试过)</li><li>如果 Token 存在 Cookie 中,服务器要同时验证cookie或header中是否有token<ul><li>Token 的大小是否超过 Cookie 的限制</li><li>请使用HttpOnly标志。若有可能,使用Secure标志。(没使用过)</li><li>采用同步令牌(Synchronize Token)来防止CSRF【这是因为,在A站点上发起向B站点的请求时,B站点的Cookie同样会被发送给B。若不使用另一个Token来防护,则无法得知cookie中的JWT是否属于从A->B,还是从B->B。目前,大部分现有的框架已经支持】</li><li>为了<a href="https://baike.baidu.com/item/%E9%87%8D%E6%94%BE%E6%94%BB%E5%87%BB/2229240?fr=aladdin" target="_blank" rel="noopener">重放攻击(replay attack)</a>,可以加上jti、exp和iat声明来验证 Token</li></ul></li></ul><h2 id="5、JWT-优缺点"><a href="#5、JWT-优缺点" class="headerlink" title="5、JWT 优缺点"></a>5、JWT 优缺点</h2><p>由于HTTP协议是无状态的,所以,我们已经认证的用户,在下一次请求的时候,服务器并不知道他是谁,我们必须再次认证。</p><h3 id="5-1、传统的认证方式"><a href="#5-1、传统的认证方式" class="headerlink" title="5.1、传统的认证方式"></a>5.1、传统的认证方式</h3><p>传统的做法是将已经认证过的用户信息存储在服务器上,比如Session。用户下次请求的时候带着Session ID,然后服务器以此检查用户是否认证过。</p><p>这种传统的认证方式存在一些问题:</p><ul><li><p>Sessions : 每次用户认证通过以后,服务器需要创建一条记录保存用户信息,通常是在内存中,随着认证通过的用户越来越多,服务器的在这里的开销就会越来越大。</p></li><li><p>CORS : 当我们想要扩展我们的应用,让我们的数据被多个移动设备使用时,我们必须考虑跨资源共享问题。当使用AJAX调用从另一个域名下获取资源时,我们可能会遇到禁止请求的问题。</p></li></ul><h3 id="5-2、JWT-与-Session-的差异"><a href="#5-2、JWT-与-Session-的差异" class="headerlink" title="5.2、JWT 与 Session 的差异"></a>5.2、JWT 与 Session 的差异</h3><p>Session是在服务器端的,而JWT是在客户端的。</p><p>Session方式存储用户信息的最大问题在于要占用大量服务器内存,增加服务器的开销。</p><p>而JWT方式将用户状态分散到了客户端中,可以明显减轻服务端的内存压力。</p><h3 id="5-3、使用-Token-的优缺点"><a href="#5-3、使用-Token-的优缺点" class="headerlink" title="5.3、使用 Token 的优缺点"></a>5.3、使用 Token 的优缺点</h3><p>优点:</p><ul><li><p>无状态和可扩展性:Tokens存储在客户端。完全无状态,可扩展。我们的负载均衡器可以将用户传递到任意服务器,因为在任何地方都没有状态或会话信息。</p></li><li><p>安全:Token不是Cookie。(The token, not a cookie.)每次请求的时候Token都会被发送。而且,由于没有Cookie被发送,还有助于防止CSRF攻击。即使在你的实现中将token存储到客户端的Cookie中,这个Cookie也只是一种存储机制,而非身份认证机制。没有基于会话的信息可以操作,因为我们没有会话!</p></li><li><p>token在一段时间以后会过期,这个时候用户需要重新登录。这有助于我们保持安全。还有一个概念叫token撤销,它允许我们根据相同的授权许可使特定的token甚至一组token无效。</p></li><li><p>减少服务器的内存压力</p></li></ul><p>缺点:</p><ul><li><p>我自己感觉还是不够很安全,因为 Payload 中的信息都是可以看到的</p></li><li><p>Token 会随着 Payload 中的数据增多而增大,数据太大,可能会超过 Cookie 或者 localstorage 的限制</p></li></ul><h2 id="6、使用场景"><a href="#6、使用场景" class="headerlink" title="6、使用场景"></a>6、使用场景</h2><p>从上面可以了解到,JWT 适合用于向 Web 应用传递一些非敏感信息。JWT 还经常用于设计用户认证和授权系统,以及实现 Web 应用的单点登录。</p><h2 id="7、参考资料"><a href="#7、参考资料" class="headerlink" title="7、参考资料"></a>7、参考资料</h2><p>由于自己还是菜鸟,所以之上部分有从别人博客复制过来的,以备之后复习,下面是参考的博客(谢谢大佬们的博客):</p><ul><li><a href="https://segmentfault.com/a/1190000008250581" target="_blank" rel="noopener">JWT必知必会</a></li><li><a href="https://www.cnblogs.com/cjsblog/p/9277677.html" target="_blank" rel="noopener">认识JWT</a></li><li><a href="http://blog.leapoahead.com/2015/09/06/understanding-jwt/" target="_blank" rel="noopener">JSON Web Token - 在Web应用间安全地传递信息</a></li></ul>]]></content>
<summary type="html">
<p><img src="/images/jwt-php2.jpg" alt="JWT小结"><br>通过 <a href="https://jwt.io/introduction" target="_blank" rel="noopener">官方文档</a> 对 JWT 做了初步的 <a href="/2019/04/11/jwt/">了解</a>,又参考了一些好的文章总结了一下。<br>
</summary>
<category term="用户认证" scheme="http://blog.feifan.news/categories/%E7%94%A8%E6%88%B7%E8%AE%A4%E8%AF%81/"/>
<category term="JWT" scheme="http://blog.feifan.news/tags/JWT/"/>
</entry>
<entry>
<title>PHP 新特性</title>
<link href="http://blog.feifan.news/2019/04/13/php-new-features/"/>
<id>http://blog.feifan.news/2019/04/13/php-new-features/</id>
<published>2019-04-13T06:24:07.000Z</published>
<updated>2019-05-06T15:38:02.754Z</updated>
<content type="html"><![CDATA[<p><img src="/images/php_new_feature.png" alt="PHP"><br><!-- ![PHP](/images/php.png) --><br><a id="more"></a><br><a href="https://www.php.net/manual/zh/appendices.php" target="_blank" rel="noopener">官方连接</a><br>PHP7 具有很多的用于编写高性能、高效代码的新特性,同时也移除了一些历史版本中过时的特性,下面是各版本中一些比较常用的新特性:</p><h2 id="5-6-X-7-0-X-新特性"><a href="#5-6-X-7-0-X-新特性" class="headerlink" title="5.6.X - 7.0.X 新特性"></a><a href="/php-new-features/70.html">5.6.X - 7.0.X 新特性</a></h2><p>标量类型声明有两种模式: 强制 (默认) 和 严格模式。 现在可以使用下列类型参数(无论用强制模式还是严格模式): 字符串(string), 整数 (int), 浮点数 (float), 以及布尔值 (bool)。它们扩充了PHP5中引入的其他类型:类名,接口,数组和 回调类型。 </p>]]></content>
<summary type="html">
<p><img src="/images/php_new_feature.png" alt="PHP"><br><!-- ![PHP](/images/php.png) --><br>
</summary>
<category term="PHP" scheme="http://blog.feifan.news/categories/PHP/"/>
</entry>
<entry>
<title>JWT 简介</title>
<link href="http://blog.feifan.news/2019/04/11/jwt/"/>
<id>http://blog.feifan.news/2019/04/11/jwt/</id>
<published>2019-04-11T07:33:56.000Z</published>
<updated>2019-05-06T15:38:02.752Z</updated>
<content type="html"><![CDATA[<p><img src="/images/jwt.jpg" alt="JWT"><br>原文:<a href="https://jwt.io/introduction/" target="_blank" rel="noopener">https://jwt.io/introduction</a><br><a id="more"></a></p><h2 id="1、什么是JWT"><a href="#1、什么是JWT" class="headerlink" title="1、什么是JWT"></a>1、什么是JWT</h2><p>JSON Web Token (JWT) 是一个开放标准 (<a href="https://tools.ietf.org/html/rfc7519" target="_blank" rel="noopener">RFC 7519</a>),它定义了一种紧凑并且独立的方式,用于在各方之间作为 JSON 对象安全的传输信息。此信息可以通过数字签名进行验证和信任。JWT 可以使用加密(使用 <a href="https://tools.ietf.org/html/rfc2104" target="_blank" rel="noopener">HMAC</a> 算法)或者使用 RSA 或者 ECDSA 的公钥/私钥对进行签名。</p><p>虽然 JWT 可以通过加密在各方之间提供保密,但 JWT 将专注于「签名令牌」。「签名令牌」可以验证其中包含的声明的完整性,而「加密令牌」则隐藏在其他地方的声明。当使用公钥/私钥对签名令牌时,签名还证明只有持有私钥的一方是签署它的一方。</p><h2 id="2、什么时候应该使用-JWT"><a href="#2、什么时候应该使用-JWT" class="headerlink" title="2、什么时候应该使用 JWT"></a>2、什么时候应该使用 JWT</h2><p>以下是 JSON Web Token 的一些使用场景:</p><ul><li><p>Authorization(授权):这是使用 JWT 的最常见方案。一旦用户登录,之后的每个请求都将包括 JWT,允许用户访问该令牌允许访问的路由、服务和资源。Single Sign On(单点登录) 是一种现在防范使用 JWT 的功能,应为它的开销很小,并且能够在不同的域中轻松使用。</p></li><li><p>Information Exchange(信息交换):JWT 是在各端之间安全传输信息的好方法。因为 JWT 可以签名 - 例如,使用公钥/私钥时,你可以确定发送人是否准确,此外,由于使用标头和有效负载计算签名,你还可以验证内容是否被篡改。</p></li></ul><h2 id="3、什么是-JWT-结构"><a href="#3、什么是-JWT-结构" class="headerlink" title="3、什么是 JWT 结构"></a>3、什么是 JWT 结构</h2><p>在紧凑形式中,JSON Web Token 由三部分组成,各部分之间用圆点(.)连接,它们是:</p><ul><li>Header(头信息)</li><li>Payload(有效荷载)</li><li>Signature(签名)</li></ul><p>因此,JWT 格式通常如下:</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">xxxxx.yyyyy.zzzzz</span><br></pre></td></tr></table></figure><p><strong><em>接下来,具体看一下各个部分:</em></strong></p><h3 id="3-1、Header"><a href="#3-1、Header" class="headerlink" title="3.1、Header"></a>3.1、Header</h3><p>Header 通常由两部分组成:<strong>签名类型</strong>(即“JWT”) 和 <strong>签名算法</strong>(例如 HMAC SHA256 或 RSA )。<br>例如:</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">{</span><br><span class="line"> <span class="string">"alg"</span>: <span class="string">"HS256"</span>,</span><br><span class="line"> <span class="string">"typ"</span>: <span class="string">"JWT"</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>然后,这个 JSON 被编码为 Base64Url ,形成 JWT 的第一部分。</p><h3 id="3-2、Payload"><a href="#3-2、Payload" class="headerlink" title="3.2、Payload"></a>3.2、Payload</h3><p>令牌的第二部分是 payload,其中包含声明。声明是关于实体(通常是指用户)和其他数据的声明,声明有三种类型:registered、public 和 private。</p><ul><li><p>Registered claims: 这是一组预先定义的声明,这些声明不是强制,但是建议提供一组有用的、可相互操作的声明。其中包括:iss (issuer), exp (expiration time), sub(subject), aud (audience) 等。</p></li><li><p>Public claims: 可以随意定义。但是为避免冲突,应在 <a href="https://www.iana.org/assignments/jwt/jwt.xhtml" target="_blank" rel="noopener">IANA JSON Web Token 注册表</a> 中定义它们,或者将其定义为包含防冲突命名空间的URI。</p></li><li><p>Private claims: 用于在同意使用它们的各方之间共享信息,并且不是注册的或公开的声明。</p></li></ul><p>例如:</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">{</span><br><span class="line"> <span class="string">"sub"</span>: <span class="string">"1234567890"</span>,</span><br><span class="line"> <span class="string">"name"</span>: <span class="string">"John Doe"</span>,</span><br><span class="line"> <span class="string">"admin"</span>: <span class="keyword">true</span></span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>然后,payload 经过 Base64Url 编码,形成 JSON Web Token 的第二部分。</p><p><strong>⚠️注意:对于签名令牌,虽然可以防止信息被篡改,但是任何人都可以读取。除非加密,否则不要将私密信息放在 JWT 的 payload 或者 header 中。</strong></p><h3 id="3-3、Signature"><a href="#3-3、Signature" class="headerlink" title="3.3、Signature"></a>3.3、Signature</h3><p>要创建签名部分,你必须有编码过的 header、编码过的 payload、密钥,签名算法是 header 中指定的那个算法(HS256),然后对其进行签名。形成 JSON Web Token 的第三部分。<br>例如,如果要使用 HMAC SHA256 算法,将按以下方式创建签名:</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">HMACSHA256(</span><br><span class="line"> base64UrlEncode(header) + <span class="string">"."</span> + base64UrlEncode(payload), </span><br><span class="line"> secret</span><br><span class="line">)</span><br></pre></td></tr></table></figure><p>签名是用于验证消息在传递过程中是否被修改,并且,对于使用私钥签名的 token,还可以验证 JWT 的发件方是否是它所声称的发送方。</p><h3 id="3-4、Putting-all-together"><a href="#3-4、Putting-all-together" class="headerlink" title="3.4、Putting all together"></a>3.4、Putting all together</h3><p>JWT 最后结果由三个部分用点(.)连接起来的 Base64-URL 字符串,可以在 HTML 和 HTTP 环境中轻松传递,而与基于 XML 的标准(如 SAML)相比更加紧凑。</p><p>下面显示了一个 JWT 的例子,它包括 header 和 payload,以及加密的签名。<br><img src="/images/jwt2.png" alt="JWT2"></p><p>你可以使用 <a href="http://jwt.io/" target="_blank" rel="noopener">jwt.io Debugger</a> 来解码,验证和生成 JWT。<br><img src="/images/jwt3.png" alt="JWT3"></p><h2 id="4、JWT-如何工作"><a href="#4、JWT-如何工作" class="headerlink" title="4、JWT 如何工作"></a>4、JWT 如何工作</h2><p>在身份验证中,当用户登录成功后,将返回 JSON Web Token。由于 Token 是凭证,因此必须非常小心以防止出现安全问题。一般情况下,不应该将 Token 保留的时间超过要求。</p><p>每当用户想要访问受保护的路由或资源时,用户代理应该使用<strong>承载模式</strong>发送 JWT,通常在 <strong>Authorization</strong> 标头中,标题的内容应该如下所示:</p><pre><code>Authorization: Bearer <token></code></pre><p>在某些情况下,这可以是无状态授权机制。服务器中受保护的路由将检查 <code style="color:#c7254e">Authorization</code> 标头中有效的 JWT,如果存在,则允许用户访问受保护的资源。如果 JWT 中包含必要的数据,则可以减少查询数据库以减少某些操作的需要,尽管可能并非如此。</p><p>如果在头信息 <code style="color:#c7254e">Authorization</code> 中发送 Token,则跨域资源共享(CORS)将不会成为问题,因为它不使用 cookie。</p><p>下图展示了如何获取 JWT 并使用访问 API 或资源:<br><img src="/images/jwt4.png" alt="JWT4"><br>1、应用程序或客户端向授权服务器请求授权。这是通过其中一个不同的授权流程执行的。例如,典型的 <a href="http://openid.net/connect/" target="_blank" rel="noopener">OpenID Connect</a> 兼容Web应用程序将/oauth/authorize使用<a href="http://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth" target="_blank" rel="noopener">授权代码</a>流通过端点;<br>2、给予授权后,授权服务器会向应用程序返回访问令牌;<br>3、应用程序使用访问令牌来访问受保护的资源(如API)。</p><p><strong>⚠️注意:使用签名令牌,令牌中包含的所有信息都会向用户或其他方公开,即使他们无法更改,这意味着你不应该在令牌中放置一些私秘的信息。</strong></p><h2 id="5、为什么使用-JWT"><a href="#5、为什么使用-JWT" class="headerlink" title="5、为什么使用 JWT"></a>5、为什么使用 JWT</h2><p>让我们来谈谈JSON Web Tokens(JWT)与Simple Web Tokens(SWT)和Security Assertion Markup Language Tokens(SAML)相比的好处。</p><p>由于 JSON 比 XML 更简洁,因此在编码时它的大小也更小,使得 JWT 比 SAML 更紧凑,这也使得 JWT 成为在 HTML 和 HTTP 传递信息的不错选择。</p><p>在安全方面,SWT 只能使用 HMAC 算法通过共享密钥对称签名。但是,JWT 和 SAML 令牌可以使用 X.509 证书形式的公钥/私钥对进行签名,与简单的 JSON 签名相比,使用 XML 数字签名对 XML 进行签名而不会引入模糊的安全漏洞非常困难。</p><p>JSON 解析器在大多数语言中很常见,因为它们直接映射到对象。相反,XML 没有自然的文档到对象映射。这使得使用 JWT 比使用 SAML 断言更容易。</p><p>关于使用,JWT 用于互联网规模。这突出了在多个平台(尤其是移动平台)上轻松进行JSON Web Token 的客户端处理。<br><img src="/images/jwt5.png" alt="JWT5"><br>比较编码的JWT和编码的SAML的长度。</p><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>这篇文章是对 <a href="https://jwt.io/introduction" target="_blank" rel="noopener">官方文章</a> 的粗略(有些地方不太通顺)翻译,有助于自己对 JWT 有了初步的了解,接下来会结合各方资料学习使用一下。</p>]]></content>
<summary type="html">
<p><img src="/images/jwt.jpg" alt="JWT"><br>原文:<a href="https://jwt.io/introduction/" target="_blank" rel="noopener">https://jwt.io/introduction</a><br>
</summary>
<category term="用户认证" scheme="http://blog.feifan.news/categories/%E7%94%A8%E6%88%B7%E8%AE%A4%E8%AF%81/"/>
<category term="JWT" scheme="http://blog.feifan.news/tags/JWT/"/>
</entry>
<entry>
<title>VundleVim 安装 NERDTree</title>
<link href="http://blog.feifan.news/2019/04/02/vundle-vim/"/>
<id>http://blog.feifan.news/2019/04/02/vundle-vim/</id>
<published>2019-04-02T10:09:25.000Z</published>
<updated>2019-05-06T15:38:02.749Z</updated>
<content type="html"><![CDATA[<p>Vim 配置 NERDTree 效果展示如下:<br><img src="/images/vim.jpg" alt="vim"><br><a id="more"></a></p><h2 id="1、安装-VundleVim"><a href="#1、安装-VundleVim" class="headerlink" title="1、安装 VundleVim"></a>1、<a href="https://github.com/muahao/Vundle.vim" target="_blank" rel="noopener">安装 VundleVim</a></h2><h3 id="1-1、下载Vundle"><a href="#1-1、下载Vundle" class="headerlink" title="1.1、下载Vundle"></a>1.1、下载Vundle</h3><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ git <span class="keyword">clone</span> https:<span class="comment">//github.com/VundleVim/Vundle.vim.git ~/.vim/bundle/Vundle.vim</span></span><br></pre></td></tr></table></figure><h3 id="1-2、插件配置"><a href="#1-2、插件配置" class="headerlink" title="1.2、插件配置"></a>1.2、插件配置</h3><p>在 <code>~/.vimrc</code> 中添加配置<br><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><span class="line">set nocompatible <span class="string">" be iMproved, required</span></span><br><span class="line"><span class="string">filetype off "</span> required</span><br><span class="line"></span><br><span class="line"><span class="string">" set the runtime path to include Vundle and initialize</span></span><br><span class="line"><span class="string">set rtp+=~/.vim/bundle/Vundle.vim</span></span><br><span class="line"><span class="string">call vundle#begin()</span></span><br><span class="line"><span class="string">"</span> alternatively, pass a path where Vundle should install plugins</span><br><span class="line"><span class="string">"call vundle#begin('~/some/path/here')</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">"</span> let Vundle manage Vundle, required</span><br><span class="line">Plugin <span class="string">'VundleVim/Vundle.vim'</span></span><br><span class="line"></span><br><span class="line"><span class="string">" The following are examples of different formats supported.</span></span><br><span class="line"><span class="string">"</span> Keep Plugin commands between vundle<span class="comment">#begin/end.</span></span><br><span class="line"><span class="string">" plugin on GitHub repo</span></span><br><span class="line"><span class="string">"</span> Plugin <span class="string">'tpope/vim-fugitive'</span></span><br><span class="line"><span class="string">" plugin from http://vim-scripts.org/vim/scripts.html</span></span><br><span class="line"><span class="string">"</span> Plugin <span class="string">'L9'</span></span><br><span class="line"><span class="string">" Git plugin not hosted on GitHub</span></span><br><span class="line"><span class="string">Plugin 'git://git.wincent.com/command-t.git'</span></span><br><span class="line"><span class="string">Plugin 'https://github.com/scrooloose/nerdtree.git'</span></span><br><span class="line"><span class="string">"</span> git repos on your local machine (i.e. when working on your own plugin)</span><br><span class="line"><span class="string">" Plugin 'file:///home/gmarik/path/to/plugin'</span></span><br><span class="line"><span class="string">"</span> The sparkup vim script is in a subdirectory of this repo called vim.</span><br><span class="line"><span class="string">" Pass the path to set the runtimepath properly.</span></span><br><span class="line"><span class="string">"</span> Plugin <span class="string">'rstacruz/sparkup'</span>, {<span class="string">'rtp'</span>: <span class="string">'vim/'</span>}</span><br><span class="line"><span class="string">" Install L9 and avoid a Naming conflict if you've already installed a</span></span><br><span class="line"><span class="string">"</span> different version somewhere <span class="keyword">else</span>.</span><br><span class="line"><span class="string">" Plugin 'ascenator/L9', {'name': 'newL9'}</span></span><br><span class="line"><span class="string"></span></span><br><span class="line"><span class="string">"</span> All of your Plugins must be added before the following line</span><br><span class="line">call vundle<span class="comment">#end() " required</span></span><br><span class="line">filetype plugin indent on <span class="string">" required</span></span><br><span class="line"><span class="string">"</span> To ignore plugin indent changes, instead <span class="keyword">use</span>:</span><br><span class="line">"<span class="title">filetype</span> <span class="title">plugin</span> <span class="title">on</span></span><br><span class="line">"</span><br><span class="line">" <span class="title">Brief</span> <span class="title">help</span></span><br><span class="line">" :<span class="title">PluginList</span> - <span class="title">lists</span> <span class="title">configured</span> <span class="title">plugins</span></span><br><span class="line">" :<span class="title">PluginInstall</span> - <span class="title">installs</span> <span class="title">plugins</span>; append `!` to update <span class="keyword">or</span> just :PluginUpdate</span><br><span class="line"><span class="string">" :PluginSearch foo - searches for foo; append `!` to refresh local cache</span></span><br><span class="line"><span class="string">"</span> :PluginClean - confirms removal of unused plugins; append `!` to auto-approve removal</span><br><span class="line"><span class="string">"</span></span><br><span class="line"><span class="string">"</span> see :h vundle <span class="keyword">for</span> more details <span class="keyword">or</span> wiki <span class="keyword">for</span> FAQ</span><br><span class="line"><span class="string">" Put your non-Plugin stuff after this line</span></span><br></pre></td></tr></table></figure></p><h3 id="1-2、安装插件"><a href="#1-2、安装插件" class="headerlink" title="1.2、安装插件"></a>1.2、安装插件</h3><p>打开 Vim 执行:<br><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">:PluginInstall</span><br></pre></td></tr></table></figure></p><p>或者在命令行执行:<br><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">vim +PluginInstall +qall</span><br></pre></td></tr></table></figure></p><p>安装之后在 <code>~/.vim/bundle</code> 文件夹下有以下文件<br><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">├── Vundle.vim</span><br><span class="line">├── command-t</span><br><span class="line">├── nerdtree</span><br><span class="line">└── nerdtree-git-plugin</span><br></pre></td></tr></table></figure></p><h2 id="2、NERDTree-配置"><a href="#2、NERDTree-配置" class="headerlink" title="2、NERDTree 配置"></a>2、<a href="https://github.com/scrooloose/nerdtree" target="_blank" rel="noopener">NERDTree 配置</a></h2><p>修改 <code>~/.vimrc</code> 文件</p><h3 id="2-1、vim启动时自动打开NERDTree"><a href="#2-1、vim启动时自动打开NERDTree" class="headerlink" title="2.1、vim启动时自动打开NERDTree"></a>2.1、vim启动时自动打开NERDTree</h3><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">autocmd vimenter * NERDTree</span><br></pre></td></tr></table></figure><h3 id="2-2、映射特定键或快捷方式以打开NERDTree"><a href="#2-2、映射特定键或快捷方式以打开NERDTree" class="headerlink" title="2.2、映射特定键或快捷方式以打开NERDTree"></a>2.2、映射特定键或快捷方式以打开NERDTree</h3><p>配置快捷键 Ctrl+n(你可以设置你想要的任何键)<br><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">map <C-n> :NERDTreeToggle<CR></span><br></pre></td></tr></table></figure></p><h3 id="2-3、更多配置"><a href="#2-3、更多配置" class="headerlink" title="2.3、更多配置"></a>2.3、更多配置</h3><p><a href="https://github.com/scrooloose/nerdtree" target="_blank" rel="noopener">https://github.com/scrooloose/nerdtree</a></p><h2 id="3、NERDTree-快捷键"><a href="#3、NERDTree-快捷键" class="headerlink" title="3、NERDTree 快捷键"></a>3、NERDTree 快捷键</h2><p>NERDTree 快捷键如下:</p><pre><code>ctrl + w + h 光标 focus 左侧树形目录ctrl + w + l 光标 focus 右侧文件显示窗口ctrl + w + w 光标自动在左右侧窗口切换ctrl + w + r 移动当前窗口的布局位置o 在已有窗口中打开文件、目录或书签,并跳到该窗口go 在已有窗口 中打开文件、目录或书签,但不跳到该窗口t 在新 Tab 中打开选中文件/书签,并跳到新 TabT 在新 Tab 中打开选中文件/书签,但不跳到新 Tabi split 一个新窗口打开选中文件,并跳到该窗口gi split 一个新窗口打开选中文件,但不跳到该窗口s vsplit 一个新窗口打开选中文件,并跳到该窗口gs vsplit 一个新 窗口打开选中文件,但不跳到该窗口! 执行当前文件O 递归打开选中 结点下的所有目录x 合拢选中结点的父目录X 递归 合拢选中结点下的所有目录e Edit the current dif双击 相当于 NERDTree-o中键 对文件相当于 NERDTree-i,对目录相当于 NERDTree-eD 删除当前书签P 跳到根结点p 跳到父结点K 跳到当前目录下同级的第一个结点J 跳到当前目录下同级的最后一个结点k 跳到当前目录下同级的前一个结点j 跳到当前目录下同级的后一个结点C 将选中目录或选中文件的父目录设为根结点u 将当前根结点的父目录设为根目录,并变成合拢原根结点U 将当前根结点的父目录设为根目录,但保持展开原根结点r 递归刷新选中目录R 递归刷新根结点m 显示文件系统菜单cd 将 CWD 设为选中目录I 切换是否显示隐藏文件f 切换是否使用文件过滤器F 切换是否显示文件B 切换是否显示书签q 关闭 NerdTree 窗口? 切换是否显示 Quick Help</code></pre><p>切换标签页</p><pre><code>:tabnew [++opt选项] [+cmd] 文件 建立对指定文件新的tab:tabc 关闭当前的 tab:tabo 关闭所有其他的 tab:tabs 查看所有打开的 tab:tabp 前一个 tab:tabn 后一个 tab</code></pre><p>标准模式下: </p><pre><code>gT 前一个 tab gt 后一个 tab MacVim 还可以借助快捷键来完成 tab 的关闭、切换cmd+w 关闭当前的 tabcmd+{ 前一个 tab cmd+} 后一个 tab </code></pre><p>NerdTree 在 .vimrc 中的常用配置<br><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="string">" 在 vim 启动的时候默认开启 NERDTree(autocmd 可以缩写为 au) </span></span><br><span class="line"><span class="string">autocmd VimEnter * NERDTree </span></span><br><span class="line"><span class="string">"</span> 按下 F2 调出/隐藏 NERDTree </span><br><span class="line">map :silent! NERDTreeToggle </span><br><span class="line"><span class="string">" 将 NERDTree 的窗口设置在 vim 窗口的右侧(默认为左侧) </span></span><br><span class="line"><span class="string">let NERDTreeWinPos="</span>right<span class="string">" </span></span><br><span class="line"><span class="string">"</span> 当打开 NERDTree 窗口时,自动显示 Bookmarks </span><br><span class="line">let NERDTreeShowBookmarks=<span class="number">1</span></span><br></pre></td></tr></table></figure></p>]]></content>
<summary type="html">
<p>Vim 配置 NERDTree 效果展示如下:<br><img src="/images/vim.jpg" alt="vim"><br>
</summary>
<category term="Vim" scheme="http://blog.feifan.news/categories/Vim/"/>
<category term="Vim" scheme="http://blog.feifan.news/tags/Vim/"/>
</entry>
<entry>
<title>phpDocumentor 标签</title>
<link href="http://blog.feifan.news/2019/03/14/phpdoc/"/>
<id>http://blog.feifan.news/2019/03/14/phpdoc/</id>
<published>2019-03-14T05:29:06.000Z</published>
<updated>2019-05-06T15:38:02.755Z</updated>
<content type="html"><![CDATA[<p>phpDocumentor 标签与 JavaDoc 很相似。只有位于文本块(DocBlock)新行开头的标签才会被解析,并且在单行范围内,@ character后面的文本可以保持任意长度。例如:</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"><?php</span></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * tags demonstration</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> this tag is parsed, but this <span class="doctag">@version</span> tag is ignored</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@version</span> 1.0 this version tag is parsed</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">?></span></span><br></pre></td></tr></table></figure><a id="more"></a><p>任何 phpDocumentor 无法识别的标签将不会被解析,但会将其以文本的形式作为文本快的一部分进行输出。以下是 phpDocumentor 支持的标签列表:</p><div class="table-container"><table><thead><tr><th>标签</th><th>适用</th><th>描述</th></tr></thead><tbody><tr><td>api</td><td>方法</td><td>声明此元素适用于第三方</td></tr><tr><td>author</td><td>任何</td><td>记录相关作者</td></tr><tr><td>copyright</td><td>任何</td><td>记录相关版权信息</td></tr><tr><td>deprecated</td><td>任何</td><td>声明次此元素不推荐使用,以后的版本中将会弃用</td></tr><tr><td>exmaple</td><td>任何</td><td>显示一部分代码</td></tr><tr><td>filesource</td><td>文件</td><td>在解析结果中包含当前文件的源</td></tr><tr><td>global</td><td>变量</td><td>全局变量及其用法</td></tr><tr><td>ignore</td><td>任何</td><td>忽略的元素</td></tr><tr><td>internal</td><td>任何</td><td>说明此元素是相关程序或库的内部元素,默认隐藏</td></tr><tr><td>licence</td><td>文件,类</td><td>(开源)许可证</td></tr><tr><td>link</td><td>任何</td><td>相关链接</td></tr><tr><td>method</td><td>类</td><td>声明可调用的魔术方法</td></tr><tr><td>package</td><td>文件,类</td><td>所属包</td></tr><tr><td>param</td><td>方法,函数</td><td>声明程序或者方法所用到的参数</td></tr><tr><td>property</td><td>类</td><td>声明类存在的魔术属性</td></tr><tr><td>property-read</td><td>类</td><td>声明类存在的只读的魔术属性</td></tr><tr><td>property-write</td><td>类</td><td>声明类存在的只写的魔法属性</td></tr><tr><td>return</td><td>方法,函数</td><td>方法或者函数返回的值</td></tr><tr><td>see</td><td>任何</td><td>相关参数</td></tr><tr><td>since</td><td>任何</td><td>声明可用版本</td></tr><tr><td>source</td><td>任何(除了文件)</td><td>参考来源</td></tr><tr><td>subpackage</td><td>文件,类</td><td>所属子包</td></tr><tr><td>throws</td><td>方法,函数</td><td>声明特定异常的类型</td></tr><tr><td>todo</td><td>任何</td><td>功能不完善,计划还要开发的任务</td></tr><tr><td>uses</td><td>任何</td><td>表示对单个关联元素的引用</td></tr><tr><td>var</td><td>属性</td><td>方法或者函数的属性</td></tr><tr><td>version</td><td>任何</td><td>当前版本</td></tr></tbody></table></div><p>此以上常规标签(regular tags)外,phpDocumentor 中还有一种行内标签(inline tags)。与常规标签不同,行内标签不要求出现在新行的开头,而可以出现在文本流中。以下几个常用的行内标签:</p><pre><code>inline {@internal}inline {@inheritdoc}inline {@link}</code></pre><p>看一下各个标签的例子:</p><h1 id="author"><a href="#author" class="headerlink" title="author"></a>author</h1><p><strong>语法</strong>:<code>@author [name] [<email address>]</code></p><p><strong>描述</strong>:@author标记可用于指示谁创建了结构元素 或已对其进行了重大修改。此标记还可以包含电子邮件地址。</p><p><strong>适用</strong>:全局变量(global variable)、引用(include)、常量(constant)、函数(function)、定义(define)、类(class)、变量(variable)、方法(method)、页面(page)</p><p><strong>示例</strong>:<br><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"><?php</span></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 函数的描述 - 显示作者的例子函数</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> LiuShuaicai <[email protected]></span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> LiuShuaicai</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">authorFunction</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><h1 id="copyright"><a href="#copyright" class="headerlink" title="copyright"></a>copyright</h1><p><strong>语法</strong>:<code>@copyright [description]</code></p><p><strong>描述</strong>:@copyright 元素的版权声明。v1.2 新特性:@copyright 属性可以从父类直接遗传到子类,详情请参考 inline {inheritdoc}</p><p><strong>适用</strong>:全局变量(global variable)、引用(include)、常量(constant)、函数(function)、定义(define)、类(class)、变量(variable)、方法(method)、页面(page)</p><p><strong>示例</strong>:<br><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"><?php</span></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 函数描述 - 显示版权的例子</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> LiuShauicai <[email protected]></span></span><br><span class="line"><span class="comment"> * <span class="doctag">@copyright</span> Copyright (c) 2019, HaoWeiLai</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">copyrightFunnction</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><h1 id="deprecated"><a href="#deprecated" class="headerlink" title="deprecated"></a>deprecated</h1><p><strong>语法</strong>:<code>@deprecated [<version>] [<description]>]</code></p><p><strong>描述</strong>:<br>@deprecated标记声明在将来的版本中将删除关联的结构元素,因为它已过时,或者不建议使用它。</p><p>此标记还可以包含一个版本号,直到它被保证包含在软件中为止。从给定的版本开始,函数将被删除,或者可以在不另行通知的情况下删除。如果指定,版本号必须遵循与@version标记向量相同的规则。</p><p>建议(但不是必需)提供一个附加说明,说明为什么不推荐使用关联元素。如果它被另一个方法取代,建议在指向新元素的同一phpdoc中添加一个@see标记。</p><p><strong>适用</strong>:全局变量(global variable)、引用(include)、常量(constant)、函数(function)、定义(define)、类(class)、变量 (variable)、方法(method)</p><p><strong>示例</strong>:<br><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"><?php</span></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@deprecated</span></span></span><br><span class="line"><span class="comment"> * <span class="doctag">@deprecated</span> 1.0.0</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@deprecated</span> No longer used by internal code and not recommended.</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@deprecated</span> 1.0.0 No longer used by internal code and not recommended.</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="function"><span class="keyword">function</span> <span class="title">deprecatedFunction</span><span class="params">()</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"> }</span><br></pre></td></tr></table></figure></p><h1 id="example"><a href="#example" class="headerlink" title="example"></a>example</h1><p><strong>语法</strong>:<code>@example [location] [<start-line> [<number-of-line>]] [<description>]</code><br> or inline:<code>{@example [location] [<start-line> [<number-of-line>]] [<description>]}</code></p><p><strong>描述</strong>:<br>@example标记可用于通过显示使用它们的文件的内容来演示结构元素的使用。</p><p>必须指定文件的位置。它可以指定为相对或绝对URI,或指定为相对或绝对文件路径。在位置周围使用双引号来明确指定它是文件路径。</p><p>如果指定,起始行必须是正整数。它指定了显示示例的行号;如果未指定起始行,则完整显示示例文件。<br>该行号可以可选地后跟另一个正整数,指定从起始行开始呈现的行数。如果省略,则示例文件从起始行显示到文件末尾。</p><p>建议(但不要求)提供附加说明以提供有关所呈现代码的更详细说明。</p><p><strong>示例</strong>:<br><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"><?php</span></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@example</span> example1.php Counting in action.</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@example</span> http://example.com/example2.phps Counting in action by a 3rd party.</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@example</span> "My Own Example.php" My counting.</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="function"><span class="keyword">function</span> <span class="title">exampleFunction</span><span class="params">()</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line"> }</span><br></pre></td></tr></table></figure></p><h1 id="global"><a href="#global" class="headerlink" title="global"></a>global</h1><p><strong>语法</strong>:<code>@global [type] [name]</code> or <code>@global [type] [description]</code></p><p><strong>描述</strong>:@global语法可用于记录函数中全局变量的使用<br><a href="http://manual.phpdoc.org/HTMLframesConverter/default/?spm=a2c4e.11153940.blogcont691719.9.12921de8uyH6wq" target="_blank" rel="noopener">http://manual.phpdoc.org/HTMLframesConverter/default/?spm=a2c4e.11153940.blogcont691719.9.12921de8uyH6wq</a></p><p><strong>示例</strong>:<br><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"><?php</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">test</span></span></span><br><span class="line"><span class="class"></span>{</span><br><span class="line">}</span><br><span class="line"> </span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@global</span> test $GLOBALS['baz'] </span></span><br><span class="line"><span class="comment"> * <span class="doctag">@name</span> $bar</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line">$GLOBALS[<span class="string">'bar'</span>] = <span class="keyword">new</span> test</span><br><span class="line"> </span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * example of basic <span class="doctag">@global</span> usage in a function</span></span><br><span class="line"><span class="comment"> * assume global variables "$foo" and "$bar" are already documented</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@global</span> bool used to control the weather</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@global</span> test used to calculate the division tables</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> bool $baz </span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> mixed </span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">function1</span><span class="params">($baz)</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="keyword">global</span> $foo,$bar;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> ($baz)</span><br><span class="line"> {</span><br><span class="line"> $a = <span class="number">5</span>;</span><br><span class="line"> } <span class="keyword">else</span></span><br><span class="line"> {</span><br><span class="line"> $a = <span class="keyword">array</span>(<span class="number">1</span>,<span class="number">4</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> $a;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><h1 id="ignore"><a href="#ignore" class="headerlink" title="ignore"></a>ignore</h1><p><strong>语法</strong>:<code>@ignore [<description>]</code><br><strong>描述</strong>:@ignore标记告诉phpDocumentor 不要处理与标记关联的结构元素。使用的一个示例可能是防止重复记录条件常量。<br>建议(但不要求)提供附加说明,说明为什么要忽略相关元素。</p><p><strong>示例</strong>:<br><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"><?php</span></span><br><span class="line"> <span class="keyword">if</span> ($ostest) {</span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * This define will either be 'Unix' or 'Windows'</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> define(<span class="string">"OS"</span>,<span class="string">"Unix"</span>);</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@ignore</span></span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> define(<span class="string">"OS"</span>,<span class="string">"Windows"</span>);</span><br><span class="line"> }</span><br></pre></td></tr></table></figure></p><h1 id="license"><a href="#license" class="headerlink" title="license"></a>license</h1><p><strong>语法</strong>:<code>@license [<url>] [name]</code><br><strong>描述</strong>:@license标记为用户提供元素的许可证名称和URL<br><strong>适用</strong>:引用(include)、页面(page)、函数(function)、定义(define)、类(class)、变量 (variable)、方法(method)<br><strong>示例</strong>:<br><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"><?php</span></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@license</span> GPL</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@license</span> http://opensource.org/licenses/gpl-license.php GNU Public License</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Test</span></span></span><br><span class="line"><span class="class"></span>{</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><h1 id="link"><a href="#link" class="headerlink" title="link"></a>link</h1><p><strong>语法</strong>:<code>@link [URI] [<description>]</code> or inline <code>{@link [URI] [<description>]}</code><br><strong>描述</strong>:@link标记可用于定义结构元素之间的关系或链接,或者在内联使用时将长描述的一部分定义 到URI<br><strong>适用</strong>:引用(include)、页面(page)、类(class)、函数(function)、定义(define)、方法(method)、变量 (variable)<br><strong>示例</strong>:<br>普通标签:<br><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"><?php</span></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@link</span> http://example.com/my/bar Documentation of Foo.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> integer Indicates the number of items.</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="function"><span class="keyword">function</span> <span class="title">count</span><span class="params">()</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <...></span><br><span class="line"> }</span><br></pre></td></tr></table></figure></p><p>内联标签:<br><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"><?php</span></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * This method counts the occurrences of Foo.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * When no more Foo ({<span class="doctag">@link</span> http://example.com/my/bar}) are given this</span></span><br><span class="line"><span class="comment"> * function will add one as there must always be one Foo.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> integer Indicates the number of items.</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="function"><span class="keyword">function</span> <span class="title">count</span><span class="params">()</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <...></span><br><span class="line"> }</span><br></pre></td></tr></table></figure></p><h1 id="method"><a href="#method" class="headerlink" title="method"></a>method</h1><p><strong>语法</strong>:<code>@method [return type] [name]([[type] [parameter]<, …>]) [<description>]</code><br><strong>描述</strong>:@method标记用于类包含 __call() 魔术方法并定义一些确定用途的情况。<br><strong>适用</strong>:类(class)、接口(interface)<br><strong>示例</strong>:<br><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"><?php</span></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* show off <span class="doctag">@method</span></span></span><br><span class="line"><span class="comment">*</span></span><br><span class="line"><span class="comment">* <span class="doctag">@method</span> int borp() borp(int $int1, int $int2) multiply two integers</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Magician</span></span></span><br><span class="line"><span class="class"></span>{</span><br><span class="line"> <span class="function"><span class="keyword">function</span> <span class="title">__call</span><span class="params">($method, $params)</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="keyword">if</span> ($method == <span class="string">'borp'</span>) {</span><br><span class="line"> <span class="keyword">if</span> (count($params) == <span class="number">2</span>) {</span><br><span class="line"> <span class="keyword">return</span> $params[<span class="number">0</span>] * $params[<span class="number">1</span>];</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><h1 id="package"><a href="#package" class="headerlink" title="package"></a>package</h1><p><strong>语法</strong>:<code>@package [level 1]\[level 2]\[etc.]</code><br><strong>描述</strong>:<br>@package标记可以用作命名空间的对应物或补充。命名空间提供了结构元素的功能细分,其中@package标记可以提供逻辑细分,以哪种方式可以将元素与不同的层次结构分组。<br><strong>适用</strong>:类(class)、页面(page)<br><strong>示例</strong>:<br>文件级示例:<br><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"><?php</span></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * Page-Level DocBlock example.</span></span><br><span class="line"><span class="comment"> * This DocBlock precedes another DocBlock and will be parsed as the page-level.</span></span><br><span class="line"><span class="comment"> * Put your <span class="doctag">@package</span> and <span class="doctag">@subpackage</span> tags here</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@package</span> pagelevel_package</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * function bluh</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">bluh</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><p>类级示例:<br><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"><?php</span></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* class bluh</span></span><br><span class="line"><span class="comment">* class-level DocBlock example.</span></span><br><span class="line"><span class="comment">* <span class="doctag">@package</span> applies_to_bluh</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">bluh</span></span></span><br><span class="line"><span class="class"></span>{</span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * This variable is parsed as part of package applies_to_bluh</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">var</span> $foo;</span><br><span class="line"> </span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * So is this function</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="function"><span class="keyword">function</span> <span class="title">bar</span><span class="params">()</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><h1 id="param"><a href="#param" class="headerlink" title="param"></a>param</h1><p><strong>语法</strong>:<code>@param [type] [name] [<description>]</code><br><strong>描述</strong>:<br>使用@param标记,可以记录函数或方法的单个参数的类型和功能。如果提供它必须包含一个 类型来表明预期的内容; 另一方面,描述是可选的,但在复杂结构的情况下,例如关联数组,则推荐使用。<br><strong>适用</strong>:方法(method)、函数(function)<br><strong>示例</strong>:<br><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"><?php</span></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * Counts the number of items in the provided array.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> mixed[] $items Array structure to count the elements of.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> int Returns the number of elements.</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="function"><span class="keyword">function</span> <span class="title">count</span><span class="params">(array $items)</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <...></span><br><span class="line"> }</span><br></pre></td></tr></table></figure></p><h1 id="property"><a href="#property" class="headerlink" title="property"></a>property</h1><p><strong>语法</strong>:<code>@property [type] [name] [<description>]</code><br><strong>描述</strong>:@property标记用于类包含 <strong>get()和</strong>set()魔术方法并允许特定名称的情况。<br><strong>适用</strong>:类(class)、接口(interface)<br><strong>示例</strong>:<br><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"><?php</span></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * show off <span class="doctag">@property</span>, <span class="doctag">@property</span>-read, <span class="doctag">@property</span>-write</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@property</span> mixed $regular regular read/write property</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@property</span>-read int $foo the foo prop</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@property</span>-write string $bar the bar prop</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Magician</span></span></span><br><span class="line"><span class="class"></span>{</span><br><span class="line"> <span class="keyword">private</span> $_thingy;</span><br><span class="line"> <span class="keyword">private</span> $_bar;</span><br><span class="line"> </span><br><span class="line"> <span class="function"><span class="keyword">function</span> <span class="title">__get</span><span class="params">($var)</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="keyword">switch</span> ($var) {</span><br><span class="line"> <span class="keyword">case</span> <span class="string">'foo'</span> :</span><br><span class="line"> <span class="keyword">return</span> <span class="number">45</span>;</span><br><span class="line"> <span class="keyword">case</span> <span class="string">'regular'</span> :</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">$this</span>->_thingy;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="function"><span class="keyword">function</span> <span class="title">__set</span><span class="params">($var, $val)</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="keyword">switch</span> ($var) {</span><br><span class="line"> <span class="keyword">case</span> <span class="string">'bar'</span> :</span><br><span class="line"> <span class="keyword">$this</span>->_bar = $val;</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> <span class="keyword">case</span> <span class="string">'regular'</span> :</span><br><span class="line"> <span class="keyword">if</span> (is_string($val)) {</span><br><span class="line"> <span class="keyword">$this</span>->_thingy = $val;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><h1 id="return"><a href="#return" class="headerlink" title="return"></a>return</h1><p><strong>语法</strong>:<code>@return [type] [<description>]</code><br><strong>描述</strong>:@return标记用于记录函数或方法的返回值。<br><strong>适用</strong>:方法(method)、函数(function)<br><strong>示例</strong>:<br>返回多种类型:<br><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"><?php</span></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> string|null The label's text or null if none provided.</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="function"><span class="keyword">function</span> <span class="title">getLabel</span><span class="params">()</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <...></span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * example of basic <span class="doctag">@return</span> usage</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> mixed </span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">function1</span><span class="params">($baz)</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="keyword">if</span> ($baz)</span><br><span class="line"> {</span><br><span class="line"> $a = <span class="number">5</span>;</span><br><span class="line"> } <span class="keyword">else</span></span><br><span class="line"> {</span><br><span class="line"> $a = <span class="keyword">array</span>(<span class="number">1</span>,<span class="number">4</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> $a;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><p>Type表示的值可以是数组。必须按照以下选项之一的格式定义类型:</p><ul><li><p>未指定,没有给出所表示数组的内容的定义。例:@return array</p></li><li><p>如果指定包含单个类型,则Type定义会通知读者每个数组元素的类型。然后只需要一个Type作为给定数组的元素。<br>例: @return int[]</p></li><li><p>请注意,mixed也是单一类型,使用此关键字可以指示每个数组元素包含任何可能的类型。</p></li><li><p>如果指定包含多个类型,则Type定义会通知读者每个数组元素的类型。每个元素可以是任何给定类型。例:@return (int|string)[]</p></li></ul><h1 id="see"><a href="#see" class="headerlink" title="see"></a>see</h1><p><strong>语法</strong>:<code>@see [URI | FQSEN] [<description>]</code> or online <code>{@see [URI | FQSEN] [<description>]}</code><br><strong>描述</strong>:<br>@see标记可用于定义对其他结构元素或URI 的引用 。</p><p>定义对另一个结构元素的引用时,可以通过附加双冒号并提供该元素的名称(也称为FQSEN)来提供特定元素。</p><p>@see仅显示元素文档的链接。如果要显示超链接,请使用@link或inline@link</p><p><strong>适用</strong>:全局变量(global variable)、引用(include)、函数(function)、定义(define)、类(class)、变量(variable)、方法(method)、页面(page)</p><p><strong>示例</strong>:<br><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"><?php</span></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* class 1</span></span><br><span class="line"><span class="comment">* </span></span><br><span class="line"><span class="comment">* example of use of the :: scope operator</span></span><br><span class="line"><span class="comment">* <span class="doctag">@see</span> subclass::method()</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">main_class</span></span></span><br><span class="line"><span class="class"></span>{</span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * example of linking to same class, outputs <u>main_class::parent_method()</u></span></span><br><span class="line"><span class="comment"> * <span class="doctag">@see</span> parent_method</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">var</span> foo = <span class="number">3</span>;</span><br><span class="line"> </span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * subclass inherits this method.</span></span><br><span class="line"><span class="comment"> * example of a word which is either a constant or class name, in this case a classname</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@see</span> subclass</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@see</span> subclass::$foo</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="function"><span class="keyword">function</span> <span class="title">parent_method</span><span class="params">()</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="keyword">if</span> (<span class="keyword">$this</span>->foo==<span class="number">9</span>) <span class="keyword">die</span>;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"> </span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* this class extends main_class.</span></span><br><span class="line"><span class="comment">* example of linking to a constant, and of putting more than one element on the same line</span></span><br><span class="line"><span class="comment">* <span class="doctag">@see</span> main_class, TEST_CONST</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line">subclass extends main_class</span><br><span class="line">{</span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * example of same class lookup - see will look through parent hierarchy to</span></span><br><span class="line"><span class="comment"> * find the method in { <span class="doctag">@link</span> main_class}</span></span><br><span class="line"><span class="comment"> * the above inline link tag will parse as <u>main_class</u></span></span><br><span class="line"><span class="comment"> * <span class="doctag">@see</span> parent_method()</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">var</span> $foo = <span class="number">9</span>;</span><br><span class="line">}</span><br><span class="line"> </span><br><span class="line"> define(<span class="string">"TEST_CONST"</span>,<span class="string">"foobar"</span>);</span><br></pre></td></tr></table></figure></p><h1 id="since"><a href="#since" class="headerlink" title="since"></a>since</h1><p><strong>语法</strong>:<code>@since [version] [<description>]</code><br><strong>描述</strong>:@since标记可用于指示特定结构元素的版本可用。<br><strong>适用</strong>:全局变量(global variable)、引用(include)、常量(constant)、函数(function)、定义(define)、类(class)、变量 (variable)、方法(method)、页面(page)<br><strong>示例</strong>:<br><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"><?php</span></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* Page-level DocBlock</span></span><br><span class="line"><span class="comment">* <span class="doctag">@package</span> BigImportantProjectWithLotsofVersions</span></span><br><span class="line"><span class="comment">* <span class="doctag">@version</span> 72.5</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* function datafunction</span></span><br><span class="line"><span class="comment">* <span class="doctag">@since</span> Version 21.1</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">datafunction</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> ...</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><h1 id="source"><a href="#source" class="headerlink" title="source"></a>source</h1><p><strong>语法</strong>:<code>@source [<start-line> [<number-of-lines>]] [<description>]</code><br><strong>描述</strong>:<br>@source标记可以用于通过呈现源代码来传达结构元素的实现 ,或者更典型地 - 它的一部分。</p><p>如果指定,起始行必须是正整数。计数从结构元素的主体开始的线(即带有开口支撑的线)开始;如果未指定起始行,则结构元素的来源将完整呈现。</p><p>该行号可以可选地后跟另一个正整数,指定从起始行开始呈现的行数。如果省略,则结构元素的源从起始线到其末端(即具有右括号的线)呈现。</p><p><strong>示例</strong>:<br><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"><?php</span></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@source</span> 2 1 Check that ensures lazy counting.</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">count</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="keyword">if</span> (<span class="keyword">null</span> === <span class="keyword">$this</span>->count) {</span><br><span class="line"> <...></span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><h1 id="throws"><a href="#throws" class="headerlink" title="throws"></a>throws</h1><p><strong>语法</strong>:<code>@throws [Type] [<description>]</code><br><strong>描述</strong>:@throws标记可用于指示结构元素可能抛出特定类型的错误,提供的类型必须表示类Exception或其任何子类的对象。<br><strong>示例</strong>:<br><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"><?php</span></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * Counts the number of items in the provided array.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> mixed[] $array Array structure to count the elements of.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@throws</span> InvalidArgumentException if the provided argument is not of type</span></span><br><span class="line"><span class="comment"> * 'array'.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> int Returns the number of elements.</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="function"><span class="keyword">function</span> <span class="title">count</span><span class="params">($items)</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <...></span><br><span class="line"> }</span><br></pre></td></tr></table></figure></p><h1 id="todo"><a href="#todo" class="headerlink" title="todo"></a>todo</h1><p><strong>语法</strong>:<code>@todo [description]</code><br><strong>描述</strong>:@todo记录对尚未实现的元素的计划更改。<br><strong>适用</strong>:任何<br><strong>示例</strong>:<br><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"><?php</span></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * Page-level DocBlock</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@package</span> unfinished</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@todo</span> finish the functions on this page</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * function datafunction</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@todo</span> make it do something</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">datafunction</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><h1 id="uses"><a href="#uses" class="headerlink" title="uses"></a>uses</h1><p><strong>语法</strong>:<code>@uses [ FQSEN ] [<description>]</code><br><strong>描述</strong>:<br>@uses标签用于描述当前元素与任何其他结构元素之间的消费关系 。</p><p>@uses类似于@see(有关格式和结构的详细信息,请参阅@see的文档)。@uses标记与@see的不同之处在于@see是单向链接,这意味着包含@see标记的文档包含指向其他结构元素或URI的链接,但不暗示链接。</p><p>文档生成器应该在接收元素的文档中创建一个@ used-by标记,该标记链接回与@uses标记关联的元素。</p><p>定义对另一个结构元素的引用时,您可以通过提供FQSEN来引用特定元素 。</p><p>@uses标签COULD附加了一个描述,以提供有关目标元素用法的更多信息。</p><p><strong>示例</strong>:<br>示例一:<br><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"><?php</span></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* class 1</span></span><br><span class="line"><span class="comment">* </span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">main_class</span></span></span><br><span class="line"><span class="class"></span>{</span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@var</span> integer </span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">var</span> foo = <span class="number">3</span>;</span><br><span class="line"> </span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * subclass inherits this method.</span></span><br><span class="line"><span class="comment"> * example of a word which is either a constant or class name,</span></span><br><span class="line"><span class="comment"> * in this case a classname</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@uses</span> subclass sets a temporary variable</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@uses</span> subclass::$foo this is compared to TEST_CONST</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@uses</span> TEST_CONST compared to subclass::$foo, we</span></span><br><span class="line"><span class="comment"> * die() if not found</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="function"><span class="keyword">function</span> <span class="title">parent_method</span><span class="params">()</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="keyword">if</span> (<span class="keyword">$this</span>->foo==<span class="number">9</span>) <span class="keyword">die</span>;</span><br><span class="line"> $test = <span class="keyword">new</span> subclass;</span><br><span class="line"> $a = $test->foo;</span><br><span class="line"> <span class="keyword">if</span> ($a == TEST_CONST) <span class="keyword">die</span>;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"> </span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* this class extends main_class.</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line">subclass extends main_class</span><br><span class="line">{</span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@var</span> integer </span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">var</span> $foo = <span class="number">9</span>;</span><br><span class="line">}</span><br><span class="line"> </span><br><span class="line">define(<span class="string">"TEST_CONST"</span>,<span class="string">"foobar"</span>);</span><br></pre></td></tr></table></figure></p><p>示例二:<br><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"><?php</span></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* class 1</span></span><br><span class="line"><span class="comment">* </span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">main_class</span></span></span><br><span class="line"><span class="class"></span>{</span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@var</span> integer </span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">var</span> foo = <span class="number">3</span>;</span><br><span class="line"> </span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * subclass inherits this method.</span></span><br><span class="line"><span class="comment"> * example of a word which is either a constant or class name,</span></span><br><span class="line"><span class="comment"> * in this case a classname</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@uses</span> subclass sets a temporary variable</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@uses</span> subclass::$foo this is compared to TEST_CONST</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@uses</span> TEST_CONST compared to subclass::$foo, we</span></span><br><span class="line"><span class="comment"> * die() if not found</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="function"><span class="keyword">function</span> <span class="title">parent_method</span><span class="params">()</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="keyword">if</span> (<span class="keyword">$this</span>->foo==<span class="number">9</span>) <span class="keyword">die</span>;</span><br><span class="line"> $test = <span class="keyword">new</span> subclass;</span><br><span class="line"> $a = $test->foo;</span><br><span class="line"> <span class="keyword">if</span> ($a == TEST_CONST) <span class="keyword">die</span>;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"> </span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* this class extends main_class.</span></span><br><span class="line"><span class="comment">* <span class="doctag">@usedby</span> main_class::parent_method() sets a temporary variable</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line">subclass extends main_class</span><br><span class="line">{</span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@var</span> integer </span></span><br><span class="line"><span class="comment"> * <span class="doctag">@usedby</span> main_class::parent_method() this is compared to TEST_CONST</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">var</span> $foo = <span class="number">9</span>;</span><br><span class="line">}</span><br><span class="line"> </span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">* <span class="doctag">@usedby</span> main_class::parent_method() compared to subclass::$foo, we</span></span><br><span class="line"><span class="comment">* die() if not found</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line">define(<span class="string">"TEST_CONST"</span>,<span class="string">"foobar"</span>);</span><br></pre></td></tr></table></figure></p><h1 id="var"><a href="#var" class="headerlink" title="var"></a>var</h1><p><strong>语法</strong>:<code>@var [“Type”] [$element_name] [<description>]</code><br><strong>描述</strong>:<br>@var标记定义了属性值表示的数据类型。</p><p>@var标记必须包含它所记录的元素的名称。例外情况是属性声明仅引用单个属性。在这种情况下,可以省略属性的名称。</p><p>当复合语句用于定义一系列属性时使用此方法。这样的复合语句只能有一个DocBlock,而表示几个项目。</p><p><strong>示例</strong>:<br><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Foo</span></span></span><br><span class="line"><span class="class"></span>{</span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@var</span> string|null Should contain a description </span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">protected</span> $description = <span class="keyword">null</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><p>记录复合语句:<br><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Foo</span></span></span><br><span class="line"><span class="class"></span>{</span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@var</span> string $name Should contain a description</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@var</span> string $description Should contain a description</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">protected</span> $name, $description;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><h1 id="version"><a href="#version" class="headerlink" title="version"></a>version</h1><p><strong>语法</strong>:<code>@version [<vector>] [<description>]</code><br><strong>描述</strong>:@version标记表示结构元素的当前版本<br><strong>示例</strong>:<br><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * example of <span class="doctag">@version</span> tag with CVS tag</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@version</span> $Id: tags.version.pkg,v 1.2 2006-04-29 04:08:27 cellog Exp $;</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">datafunction</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="number">0</span>;</span><br><span class="line">}</span><br><span class="line"> </span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * Custom version string</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@version</span> customversionstring1.0</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">blah</span></span></span><br><span class="line"><span class="class"></span>{</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><h1 id="更多标签内容查看"><a href="#更多标签内容查看" class="headerlink" title="更多标签内容查看"></a>更多标签内容查看</h1><p><a href="http://manual.phpdoc.org/HTMLframesConverter/default/?spm=a2c4e.11153940.blogcont691719.9.12921de8uyH6wq" target="_blank" rel="noopener">http://manual.phpdoc.org/HTMLframesConverter/default/?spm=a2c4e.11153940.blogcont691719.9.12921de8uyH6wq</a></p><p><a href="https://docs.phpdoc.org/references/phpdoc/index.html" target="_blank" rel="noopener">https://docs.phpdoc.org/references/phpdoc/index.html</a></p>]]></content>
<summary type="html">
<p>phpDocumentor 标签与 JavaDoc 很相似。只有位于文本块(DocBlock)新行开头的标签才会被解析,并且在单行范围内,@ character后面的文本可以保持任意长度。例如:</p>
<figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&lt;?php</span></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * tags demonstration</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> this tag is parsed, but this <span class="doctag">@version</span> tag is ignored</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@version</span> 1.0 this version tag is parsed</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="meta">?&gt;</span></span><br></pre></td></tr></table></figure>
</summary>
<category term="PHP" scheme="http://blog.feifan.news/categories/PHP/"/>
<category term="PHP" scheme="http://blog.feifan.news/tags/PHP/"/>
</entry>
<entry>
<title>phptrace 简单使用</title>
<link href="http://blog.feifan.news/2019/03/02/phptrace/"/>
<id>http://blog.feifan.news/2019/03/02/phptrace/</id>
<published>2019-03-02T06:29:16.000Z</published>
<updated>2019-05-06T15:38:02.761Z</updated>
<content type="html"><![CDATA[<h2 id="1、介绍"><a href="#1、介绍" class="headerlink" title="1、介绍"></a>1、介绍</h2><p>phptrace 是一个 <code>Qihoo360</code> 开源的一个低开销的用于跟踪(trace)、分析PHP运行情况的工具。</p><p>它可以跟踪PHP在运行时的函数调用、请求信息、执行流程,并且提供有过滤器、统计信息、当前状态等实用功能。 在任何环境下,它都能很好的定位阻塞问题以及在高负载下Debug,尤其是线上生产环境。<br><a id="more"></a><br>具有以下特性:</p><pre><code>低开销,在只加载模块不开启Trace功能时对性能影响极低稳定性,已经稳定运行在Qihoo 360线上服务中,并针对主流框架进行测试易用性,对于未安装trace扩展的环境,也能够追踪运行状态</code></pre><p>phptrace是类strace的一个实现,不同的是,strace用来追踪系统调用,而phptrace用来追踪PHP函数调用。无论是开发测试 还是线上追查问题,代码执行流程往往会提供许多有用的信息,大大提高了开发人员的工作效率;</p><h2 id="2、安装"><a href="#2、安装" class="headerlink" title="2、安装"></a>2、安装</h2><h3 id="2-1、下载地址:"><a href="#2-1、下载地址:" class="headerlink" title="2.1、下载地址:"></a>2.1、下载地址:</h3><ul><li>GitHub: <a href="https://github.com/Qihoo360/phptrace" target="_blank" rel="noopener">https://github.com/Qihoo360/phptrace</a></li><li>PECL: <a href="https://pecl.php.net/package/trace" target="_blank" rel="noopener">https://pecl.php.net/package/trace</a></li></ul><h3 id="2-2、下载解压"><a href="#2-2、下载解压" class="headerlink" title="2.2、下载解压"></a>2.2、下载解压</h3><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">curl -LOk https:<span class="comment">//github.com/Qihoo360/phptrace/archive/master.zip</span></span><br><span class="line">unzip master.zip <span class="comment">// unzip解压</span></span><br><span class="line">cd phptrace-master/extension/ <span class="comment">// 进入解压后的扩展目录</span></span><br></pre></td></tr></table></figure><h3 id="2-3、源码编译"><a href="#2-3、源码编译" class="headerlink" title="2.3、源码编译"></a>2.3、源码编译</h3><p>2.3.1、PHP 扩展安装(以下命令是在 phptrace-master/extension/ 目录中执行的)<br><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">phpize</span><br><span class="line">./configure --with-php-config=/usr/<span class="built_in">local</span>/php7/bin/php-config</span><br><span class="line">make</span><br></pre></td></tr></table></figure></p><p>php-config 的路径要根据自己的位置进行修改。</p><p>2.3.2、命令行工具<br><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">make cli</span><br></pre></td></tr></table></figure></p><p>2.3.3、安装PHP扩展、命令行工具至PHP目录<br><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">make install-all</span><br></pre></td></tr></table></figure></p><h3 id="2-4、添加扩展"><a href="#2-4、添加扩展" class="headerlink" title="2.4、添加扩展"></a>2.4、添加扩展</h3><p>编辑配置文件php.ini(如果没有 php.ini 文件,复制源码中的 php.ini-development 或者 php.ini-production 到安装目录的 etc文件夹下,命名为 php.ini ),增加下面配置信息。<br><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">[phptrace]</span><br><span class="line">extension=trace.so</span><br><span class="line">phptrace.enabled = <span class="number">1</span></span><br></pre></td></tr></table></figure></p><p>php-fpm需要手动重启。<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">kill -USR2 24612</span><br></pre></td></tr></table></figure></p><p>master进程可以理解以下信号</p><pre><code>INT, TERM 立刻终止QUIT 平滑终止USR1 重新打开日志文件USR2 平滑重载所有worker进程并重新载入配置和二进制模块</code></pre><p>查看扩展安装:<br><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">root@VM_173_23_centos:/usr/local/php7<span class="comment"># php -m | grep trace</span></span><br><span class="line">trace</span><br></pre></td></tr></table></figure></p><p>或者查看 phpinfo(),查看 /usr/local/php7/bin 下已经有了 phptrace<br><figure class="highlight sh"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">root@VM_173_23_centos:/usr/<span class="built_in">local</span>/php7/bin<span class="comment"># ls</span></span><br><span class="line">pear peardev pecl phar phar.phar php php-cgi php-config phpdbg phpize phptrace</span><br></pre></td></tr></table></figure></p><p>创建一个软连接:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ln -s /usr/local/php7/bin/phptrace /usr/local/bin/phptrace</span><br></pre></td></tr></table></figure></p><h2 id="3、使用"><a href="#3、使用" class="headerlink" title="3、使用"></a>3、使用</h2><h3 id="3-1、查看命令参数"><a href="#3-1、查看命令参数" class="headerlink" title="3.1、查看命令参数"></a>3.1、查看命令参数</h3><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">root@VM_173_23_centos:/usr/local/php7/bin# phptrace -h</span><br><span class="line">phptrace - A low-overhead tracing tool for PHP</span><br><span class="line"></span><br><span class="line">Usage: phptrace -p <pid>...</span><br><span class="line"> phptrace -h | --help</span><br><span class="line"></span><br><span class="line">Commands:</span><br><span class="line"> trace Trace a running PHP process [default]</span><br><span class="line"> status Display current status of specified PHP process</span><br><span class="line"> version Show version</span><br><span class="line"></span><br><span class="line">Options:</span><br><span class="line"> --ptrace Fetch data using ptrace, only in status mode</span><br><span class="line"> -p, --pid Process id</span><br><span class="line"> -h, --help Show this screen</span><br><span class="line"> -v, --verbose</span><br><span class="line"> -f, --filter Filter data by type [url,function,class] and content</span><br><span class="line"> -l, --limit Limit output count</span><br></pre></td></tr></table></figure><pre><code>trace 追踪运行的PHP进程(默认)status 展示PHP进程的运行状态version 版本-p 指定php进程id('all'追踪所有的进程)-h 帮助-v 同version-f 通过类型(url,function,class)和内容过滤数据-l 限制输出次数--ptrace 在追踪状态的模式下通过ptrace获取数据</code></pre><h3 id="3-2、官方实例"><a href="#3-2、官方实例" class="headerlink" title="3.2、官方实例"></a>3.2、官方实例</h3><p>phptrace 官方实例 example.php 文件如下:<br><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"><?php</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Me</span></span></span><br><span class="line"><span class="class"></span>{</span><br><span class="line"> <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">say</span><span class="params">($words)</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="keyword">echo</span> $words.<span class="string">"\n"</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">sleep</span><span class="params">()</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="keyword">$this</span>->say(<span class="string">'sleeping...'</span>);</span><br><span class="line"> sleep(<span class="number">2</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">run</span><span class="params">()</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="keyword">$this</span>->say(<span class="string">'good night'</span>);</span><br><span class="line"> <span class="keyword">$this</span>->sleep();</span><br><span class="line"> <span class="keyword">$this</span>->say(<span class="string">'wake up'</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line">$pid = getmypid();</span><br><span class="line"><span class="keyword">echo</span> <span class="string">"**phptrace sample**\n"</span>;</span><br><span class="line"><span class="keyword">echo</span> <span class="string">"Type these command in a new console:\n"</span>;</span><br><span class="line"><span class="keyword">echo</span> <span class="string">"\n"</span>;</span><br><span class="line"><span class="keyword">echo</span> <span class="string">"trace: phptrace -p $pid\n"</span>;</span><br><span class="line"><span class="keyword">echo</span> <span class="string">"trace with filter: phptrace -p $pid -f type=function,content=sleep\n"</span>;</span><br><span class="line"><span class="keyword">echo</span> <span class="string">"trace with filter: phptrace -p $pid -f type=class,content=Me\n"</span>;</span><br><span class="line"><span class="keyword">echo</span> <span class="string">"trace with count limit: phptrace -p $pid -l 2\n"</span>;</span><br><span class="line"><span class="keyword">echo</span> <span class="string">"view status: phptrace status -p $pid\n"</span>;</span><br><span class="line"><span class="keyword">echo</span> <span class="string">"view status by ptrace: phptrace status -p $pid --ptrace\n"</span>;</span><br><span class="line"><span class="keyword">echo</span> <span class="string">"\n"</span>;</span><br><span class="line">printf(<span class="string">"Press enter to continue...\n"</span>);</span><br><span class="line">$fp = fopen(<span class="string">'php://stdin'</span>, <span class="string">'r'</span>);</span><br><span class="line">fgets($fp);</span><br><span class="line">fclose($fp);</span><br><span class="line">usleep(<span class="number">100000</span>);</span><br><span class="line">(<span class="keyword">new</span> Me)->run();</span><br></pre></td></tr></table></figure></p><p><code>php example.php</code> 运行结果<br><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line">root@VM_173_23_centos:~/phptrace-master<span class="comment"># php example.php</span></span><br><span class="line">**phptrace sample**</span><br><span class="line">Type these command in a <span class="keyword">new</span> console:</span><br><span class="line"></span><br><span class="line">trace: phptrace -p <span class="number">32194</span></span><br><span class="line">trace with filter: phptrace -p <span class="number">32194</span> -f type=<span class="function"><span class="keyword">function</span>,<span class="title">content</span>=<span class="title">sleep</span></span></span><br><span class="line"><span class="function"><span class="title">trace</span> <span class="title">with</span> <span class="title">filter</span>: <span class="title">phptrace</span> -<span class="title">p</span> 32194 -<span class="title">f</span> <span class="title">type</span>=<span class="title">class</span>,<span class="title">content</span>=<span class="title">Me</span></span></span><br><span class="line"><span class="function"><span class="title">trace</span> <span class="title">with</span> <span class="title">count</span> <span class="title">limit</span>: <span class="title">phptrace</span> -<span class="title">p</span> 32194 -<span class="title">l</span> 2</span></span><br><span class="line"><span class="function"><span class="title">view</span> <span class="title">status</span>: <span class="title">phptrace</span> <span class="title">status</span> -<span class="title">p</span> 32194</span></span><br><span class="line"><span class="function"><span class="title">view</span> <span class="title">status</span> <span class="title">by</span> <span class="title">ptrace</span>: <span class="title">phptrace</span> <span class="title">status</span> -<span class="title">p</span> 32194 --<span class="title">ptrace</span></span></span><br><span class="line"><span class="function"></span></span><br><span class="line"><span class="function"><span class="title">Press</span> <span class="title">enter</span> <span class="title">to</span> <span class="title">continue</span>...</span></span><br></pre></td></tr></table></figure></p><p>可以看到上面的几个追踪(trace)命令,再开一个窗口,运行 trace 命令</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line"> root@VM_173_23_centos:~<span class="comment"># phptrace -p 32194</span></span><br><span class="line">process attached</span><br><span class="line">[pid <span class="number">32194</span>] > Me->run() called at [/root/phptrace-master/example.php:<span class="number">57</span>]</span><br><span class="line">[pid <span class="number">32194</span>] > Me->say(<span class="string">"good night"</span>) called at [/root/phptrace-master/example.php:<span class="number">33</span>]</span><br><span class="line">[pid <span class="number">32194</span>] < Me->say(<span class="string">"good night"</span>) = <span class="keyword">NULL</span> called at [/root/phptrace-master/example.php:<span class="number">33</span>] ~ <span class="number">0.000</span>s <span class="number">0.000</span>s</span><br><span class="line">[pid <span class="number">32194</span>] > Me->sleep() called at [/root/phptrace-master/example.php:<span class="number">34</span>]</span><br><span class="line">[pid <span class="number">32194</span>] > Me->say(<span class="string">"sleeping..."</span>) called at [/root/phptrace-master/example.php:<span class="number">27</span>]</span><br><span class="line">[pid <span class="number">32194</span>] < Me->say(<span class="string">"sleeping..."</span>) = <span class="keyword">NULL</span> called at [/root/phptrace-master/example.php:<span class="number">27</span>] ~ <span class="number">0.000</span>s <span class="number">0.000</span>s</span><br><span class="line">[pid <span class="number">32194</span>] > sleep(<span class="number">2</span>) called at [/root/phptrace-master/example.php:<span class="number">28</span>]</span><br><span class="line">[pid <span class="number">32194</span>] < sleep(<span class="number">2</span>) = <span class="number">0</span> called at [/root/phptrace-master/example.php:<span class="number">28</span>] ~ <span class="number">2.000</span>s <span class="number">2.000</span>s</span><br><span class="line">[pid <span class="number">32194</span>] < Me->sleep() = <span class="keyword">NULL</span> called at [/root/phptrace-master/example.php:<span class="number">34</span>] ~ <span class="number">2.000</span>s <span class="number">0.000</span>s</span><br><span class="line">[pid <span class="number">32194</span>] > Me->say(<span class="string">"wake up"</span>) called at [/root/phptrace-master/example.php:<span class="number">35</span>]</span><br><span class="line">[pid <span class="number">32194</span>] < Me->say(<span class="string">"wake up"</span>) = <span class="keyword">NULL</span> called at [/root/phptrace-master/example.php:<span class="number">35</span>] ~ <span class="number">0.000</span>s <span class="number">0.000</span>s</span><br><span class="line">[pid <span class="number">32194</span>] < Me->run() = <span class="keyword">NULL</span> called at [/root/phptrace-master/example.php:<span class="number">57</span>] ~ <span class="number">2.000</span>s <span class="number">0.000</span>s</span><br><span class="line">[pid <span class="number">32194</span>]< cli php example.php</span><br><span class="line">process detached</span><br></pre></td></tr></table></figure><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"> root@VM_173_23_centos:~<span class="comment"># phptrace status -p 5368</span></span><br><span class="line">------------------------------- Status --------------------------------</span><br><span class="line">PHP Version: <span class="number">7.3</span><span class="number">.2</span></span><br><span class="line">SAPI: cli</span><br><span class="line">script: /root/phptrace-master/example.php</span><br><span class="line">elapse: <span class="number">11.902</span>s</span><br><span class="line">memory: <span class="number">0.40</span>m</span><br><span class="line">memory peak: <span class="number">0.44</span>m</span><br><span class="line">real-memory: <span class="number">2.00</span>m</span><br><span class="line">real-memory peak <span class="number">2.00</span>m</span><br><span class="line">------------------------------ Arguments ------------------------------</span><br><span class="line">$<span class="number">0</span> example.php</span><br><span class="line">------------------------------ Backtrace ------------------------------</span><br><span class="line"><span class="comment">#0 Me->run() called at [/root/phptrace-master/example.php:57]</span></span><br><span class="line"><span class="comment">#1 {main}() called at [/root/phptrace-master/example.php:57]</span></span><br></pre></td></tr></table></figure><p>可以看到在脚本运行过程,以及各个PHP函数的调用。其他几个命令都可以试试,不过我这边运行最后一个命令会出错,没找出问题。</p><h3 id="3-3、验证-PHP-后期静态绑定"><a href="#3-3、验证-PHP-后期静态绑定" class="headerlink" title="3.3、验证 PHP 后期静态绑定"></a>3.3、验证 PHP 后期静态绑定</h3><p><a href="http://blog.feifan.news/2019/02/13/php-callstatic/#4%E3%80%81%E6%9C%80%E5%90%8E%E4%B8%80%E4%B8%AA%E4%BE%8B%E5%AD%90">PHP 后期静态绑定</a>的例子,我们验证一下两种调用方法的执行过程。<br><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line">> Model::find(<span class="number">1</span>, <span class="number">2</span>) called at [/root/php/index.php:<span class="number">39</span>]</span><br><span class="line">[pid <span class="number">7715</span>] > Model::__callStatic(<span class="string">"find"</span>, <span class="keyword">array</span>(<span class="number">2</span>)) called at [/root/php/index.php:<span class="number">39</span>]</span><br><span class="line">[pid <span class="number">7715</span>] > Model->find(<span class="number">1</span>) called at [/root/php/index.php:<span class="number">23</span>]</span><br><span class="line">[pid <span class="number">7715</span>] < Model->find(<span class="number">1</span>) = <span class="string">"php"</span> called at [/root/php/index.php:<span class="number">23</span>] ~ <span class="number">0.000</span>s <span class="number">0.000</span>s</span><br><span class="line">[pid <span class="number">7715</span>] > Model->find(<span class="number">2</span>) called at [/root/php/index.php:<span class="number">23</span>]</span><br><span class="line">[pid <span class="number">7715</span>] < Model->find(<span class="number">2</span>) = <span class="string">"python"</span> called at [/root/php/index.php:<span class="number">23</span>] ~ <span class="number">0.000</span>s <span class="number">0.000</span>s</span><br><span class="line">[pid <span class="number">7715</span>] < Model::__callStatic(<span class="string">"find"</span>, <span class="keyword">array</span>(<span class="number">2</span>)) = <span class="keyword">NULL</span> called at [/root/php/index.php:<span class="number">39</span>] ~ <span class="number">0.000</span>s <span class="number">0.000</span>s</span><br><span class="line">[pid <span class="number">7715</span>] < Model::find(<span class="number">1</span>, <span class="number">2</span>) = <span class="keyword">NULL</span> called at [/root/php/index.php:<span class="number">39</span>] ~ <span class="number">0.000</span>s <span class="number">0.000</span>s</span><br><span class="line">[pid <span class="number">7715</span>] > Model->find(<span class="number">3</span>, <span class="number">4</span>) called at [/root/php/index.php:<span class="number">42</span>]</span><br><span class="line">[pid <span class="number">7715</span>] > Model->__call(<span class="string">"find"</span>, <span class="keyword">array</span>(<span class="number">2</span>)) called at [/root/php/index.php:<span class="number">42</span>]</span><br><span class="line">[pid <span class="number">7715</span>] > Model->find(<span class="number">3</span>) called at [/root/php/index.php:<span class="number">16</span>]</span><br><span class="line">[pid <span class="number">7715</span>] < Model->find(<span class="number">3</span>) = <span class="string">"go"</span> called at [/root/php/index.php:<span class="number">16</span>] ~ <span class="number">0.000</span>s <span class="number">0.000</span>s</span><br><span class="line">[pid <span class="number">7715</span>] > Model->find(<span class="number">4</span>) called at [/root/php/index.php:<span class="number">16</span>]</span><br><span class="line">[pid <span class="number">7715</span>] < Model->find(<span class="number">4</span>) = <span class="string">"c"</span> called at [/root/php/index.php:<span class="number">16</span>] ~ <span class="number">0.000</span>s <span class="number">0.000</span>s</span><br><span class="line">[pid <span class="number">7715</span>] < Model->__call(<span class="string">"find"</span>, <span class="keyword">array</span>(<span class="number">2</span>)) = <span class="keyword">NULL</span> called at [/root/php/index.php:<span class="number">42</span>] ~ <span class="number">0.000</span>s <span class="number">0.000</span>s</span><br><span class="line">[pid <span class="number">7715</span>] < Model->find(<span class="number">3</span>, <span class="number">4</span>) = <span class="keyword">NULL</span> called at [/root/php/index.php:<span class="number">42</span>] ~ <span class="number">0.000</span>s <span class="number">0.000</span>s</span><br><span class="line">[pid <span class="number">7715</span>] > sleep(<span class="number">2</span>) called at [/root/php/index.php:<span class="number">44</span>]</span><br><span class="line">[pid <span class="number">7715</span>] < sleep(<span class="number">2</span>) = <span class="number">0</span> called at [/root/php/index.php:<span class="number">44</span>] ~ <span class="number">2.000</span>s <span class="number">2.000</span>s</span><br></pre></td></tr></table></figure></p><p>可以看到在执行 <code>Product::find(1,2);</code> 的时候,先调用 <code>__callStatic</code> 方法,随后调用 find() 方法;<br>执行 <code>$p = new Product(); $p->find(3,4);</code> 先调用 <code>__call</code> 方法,随后调用 find() 方法;</p><p>官方教程:<a href="https://github.com/Qihoo360/phptrace/blob/master/README_ZH.md" target="_blank" rel="noopener">https://github.com/Qihoo360/phptrace/blob/master/README_ZH.md</a></p>]]></content>
<summary type="html">
<h2 id="1、介绍"><a href="#1、介绍" class="headerlink" title="1、介绍"></a>1、介绍</h2><p>phptrace 是一个 <code>Qihoo360</code> 开源的一个低开销的用于跟踪(trace)、分析PHP运行情况的工具。</p>
<p>它可以跟踪PHP在运行时的函数调用、请求信息、执行流程,并且提供有过滤器、统计信息、当前状态等实用功能。 在任何环境下,它都能很好的定位阻塞问题以及在高负载下Debug,尤其是线上生产环境。<br>
</summary>
<category term="PHP" scheme="http://blog.feifan.news/categories/PHP/"/>
<category term="PHP" scheme="http://blog.feifan.news/tags/PHP/"/>
<category term="调试工具" scheme="http://blog.feifan.news/tags/%E8%B0%83%E8%AF%95%E5%B7%A5%E5%85%B7/"/>
</entry>
<entry>
<title>PHP 后期静态绑定</title>
<link href="http://blog.feifan.news/2019/02/13/php-callstatic/"/>
<id>http://blog.feifan.news/2019/02/13/php-callstatic/</id>
<published>2019-02-13T13:53:45.000Z</published>
<updated>2019-05-06T15:38:02.747Z</updated>
<content type="html"><![CDATA[<p>从 PHP 5.3.0 开始,PHP 增加了一个叫做<code>后期静态绑定</code>的功能,用于在继承范围内引用静态调用的类。简单的说就是:使用 <code>static::</code> 关键字时,类名称不是当前方法所在的类,而是当前对象实例所属的类或者当前调用的类。<br>使用(static)关键字来表示这个别名,和静态方法,静态类没有半毛钱的关系,static::不仅支持静态类,还支持对象(动态类)。<br><a id="more"></a></p><h2 id="工作原理"><a href="#工作原理" class="headerlink" title="工作原理"></a>工作原理</h2><p>后期静态绑定工作原理是存储了在上一个 “非转发调用” (non-forwarding call)的类名。</p><h2 id="转发调用"><a href="#转发调用" class="headerlink" title="转发调用"></a>转发调用</h2><p>“转发调用”(forwarding call)指的是通过以下几种方式进行的静态调用:self::,parent::,static:: 以及 forward_static_call()</p><h2 id="非转发调用"><a href="#非转发调用" class="headerlink" title="非转发调用"></a>非转发调用</h2><p>“非转发调用” (non-forwarding call)指的是:<br>1、当进行静态方法调用时,该类名即为明确指定的那个(通常在 :: 运算符左侧部分),例如:foo::bar();<br>2、当进行非静态方法调用时,即为该对象所属的类,例如:$foo->bar()。</p><h2 id="例子"><a href="#例子" class="headerlink" title="例子"></a>例子</h2><h3 id="1、self-的限制"><a href="#1、self-的限制" class="headerlink" title="1、self 的限制"></a>1、self 的限制</h3><p>使用 <code>self</code> 或者 <code>__CLASS__</code> 对当前类的静态引用,取决去定义当前方法所在的类。<br>官方实例:<br><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"><?php</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">A</span></span></span><br><span class="line"><span class="class"></span>{</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="function"><span class="keyword">function</span> <span class="title">who</span><span class="params">()</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="keyword">echo</span> <span class="keyword">__CLASS__</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="function"><span class="keyword">function</span> <span class="title">test</span><span class="params">()</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="keyword">self</span>::who();</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">B</span> <span class="keyword">extends</span> <span class="title">A</span></span></span><br><span class="line"><span class="class"></span>{</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="function"><span class="keyword">function</span> <span class="title">who</span><span class="params">()</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="keyword">echo</span> <span class="keyword">__CLASS__</span>;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">B::test();</span><br></pre></td></tr></table></figure></p><p>结果如下:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">A</span><br></pre></td></tr></table></figure></p><h3 id="2、后期静态绑定用法"><a href="#2、后期静态绑定用法" class="headerlink" title="2、后期静态绑定用法"></a>2、后期静态绑定用法</h3><p>从上面的官方小例子也可以看到,self 限制了对象为方法自身所属的类,后期静态绑定就是想绕过这种限制,简单的说,就是想让上面的输出结果是 B ,而不是 A,但并没有引入什么新的关键字或者函数,而是使用已经预留的 static 关键字。<br>下面就是把 self 换成 static,看一下输出结果。<br><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"><?php</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">A</span></span></span><br><span class="line"><span class="class"></span>{</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="function"><span class="keyword">function</span> <span class="title">who</span><span class="params">()</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="keyword">echo</span> <span class="keyword">__CLASS__</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="function"><span class="keyword">function</span> <span class="title">test</span><span class="params">()</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="keyword">static</span>::who(); <span class="comment">// 后期静态绑定从这里开始</span></span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">B</span> <span class="keyword">extends</span> <span class="title">A</span></span></span><br><span class="line"><span class="class"></span>{</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="function"><span class="keyword">function</span> <span class="title">who</span><span class="params">()</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="keyword">echo</span> <span class="keyword">__CLASS__</span>;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">B::test();</span><br></pre></td></tr></table></figure></p><p>输出结果:<br><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">B</span><br></pre></td></tr></table></figure></p><p>输出结果就是我们预期的B。上面我们都是使用的静态方法,在非静态方法下,我们看一下 $this 和 static 的差别。<br><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"><?php</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">A</span></span></span><br><span class="line"><span class="class"></span>{</span><br><span class="line"> <span class="keyword">private</span> <span class="function"><span class="keyword">function</span> <span class="title">foo</span><span class="params">()</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="keyword">echo</span> <span class="keyword">__method__</span>.<span class="string">"\n"</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">test</span><span class="params">()</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="keyword">$this</span>->foo();</span><br><span class="line"> <span class="keyword">static</span>::foo();</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> </span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">B</span> <span class="keyword">extends</span> <span class="title">A</span></span></span><br><span class="line"><span class="class"></span>{</span><br><span class="line"> <span class="comment">// foo()将被复制到b,因此它的作用域仍然是a,调用将成功</span></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">C</span> <span class="keyword">extends</span> <span class="title">B</span></span></span><br><span class="line"><span class="class"></span>{</span><br><span class="line"> <span class="keyword">private</span> <span class="function"><span class="keyword">function</span> <span class="title">foo</span><span class="params">()</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="comment">// 替换原有方法;新方法的范围为C</span></span><br><span class="line"> <span class="keyword">echo</span> <span class="keyword">__method__</span>.<span class="string">"\n"</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 方法重载,调用不存在或者不可见的属性或者方法</span></span><br><span class="line"><span class="comment"> * 不加这个方法,调用$c->test(),static::foo()时会报错,因为类C的foo()不可以被访问</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="function"><span class="keyword">function</span> <span class="title">__callStatic</span><span class="params">($name, $arguments)</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> (<span class="keyword">new</span> <span class="keyword">static</span>)->$name($arguments);</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">$b = <span class="keyword">new</span> B();</span><br><span class="line">$b->test();</span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 输出结果</span></span><br><span class="line"><span class="comment"> * A::foo</span></span><br><span class="line"><span class="comment"> * A::foo</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"></span><br><span class="line">$c = <span class="keyword">new</span> C();</span><br><span class="line">$c->test();</span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 输出结果</span></span><br><span class="line"><span class="comment"> * A::foo</span></span><br><span class="line"><span class="comment"> * C::foo</span></span><br><span class="line"><span class="comment"> */</span></span><br></pre></td></tr></table></figure></p><p>从结果可以看到 <code>$this-></code> 调用的是类A的foo(),而 static 调用的是类C的foo()方法,所以 <code>$this</code> 的作用范围只限于当前类,而 static 是对象的实例所属的类。</p><pre><code>官方注解 Note:在非静态环境下,所调用的类即为该对象实例所属的类。由于 $this-> 会在同一作用范围内尝试调用私有方法,而 static:: 则可能给出不同结果。另一个区别是 static:: 只能用于静态属性。 </code></pre><h3 id="3、转发和非转发调用"><a href="#3、转发和非转发调用" class="headerlink" title="3、转发和非转发调用"></a>3、转发和非转发调用</h3><p>后期静态绑定的解析会一直到取得一个完全解析的静态调用为止。另一方面,如果静态调用使用 parent:: ,self:: , static:: 或者 forward_static_call() 将转发调用信息。<br><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"><?php</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">A</span></span></span><br><span class="line"><span class="class"></span>{</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="function"><span class="keyword">function</span> <span class="title">foo</span><span class="params">()</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="keyword">static</span>::who(); <span class="comment">// 后期静态绑定</span></span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="function"><span class="keyword">function</span> <span class="title">who</span><span class="params">()</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="keyword">echo</span> <span class="keyword">__method__</span>.<span class="string">"\n"</span>;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">B</span> <span class="keyword">extends</span> <span class="title">A</span></span></span><br><span class="line"><span class="class"></span>{</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="function"><span class="keyword">function</span> <span class="title">test</span><span class="params">()</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> A::foo();</span><br><span class="line"> <span class="keyword">self</span>::foo();</span><br><span class="line"> <span class="keyword">parent</span>::foo();</span><br><span class="line"> <span class="keyword">static</span>::foo();</span><br><span class="line"> forward_static_call([<span class="string">'A'</span>,<span class="string">'foo'</span>]);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="function"><span class="keyword">function</span> <span class="title">who</span><span class="params">()</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="keyword">echo</span> <span class="keyword">__method__</span>.<span class="string">"\n"</span>;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">C</span> <span class="keyword">extends</span> <span class="title">B</span></span></span><br><span class="line"><span class="class"></span>{</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="function"><span class="keyword">function</span> <span class="title">who</span><span class="params">()</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="keyword">echo</span> <span class="keyword">__method__</span>.<span class="string">"\n"</span>;</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">C::test();</span><br></pre></td></tr></table></figure></p><p>输出结果:<br><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">A::who</span><br><span class="line">C::who</span><br><span class="line">C::who</span><br><span class="line">C::who</span><br><span class="line">C::who</span><br></pre></td></tr></table></figure></p><h3 id="4、最后一个例子"><a href="#4、最后一个例子" class="headerlink" title="4、最后一个例子"></a>4、最后一个例子</h3><p>我们经常使用 sql 查询 find 方法,我们来模拟一下:<br><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"><?php</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Model</span></span></span><br><span class="line"><span class="class"></span>{</span><br><span class="line"> <span class="keyword">protected</span> <span class="function"><span class="keyword">function</span> <span class="title">find</span><span class="params">(int $id)</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> $data = <span class="keyword">static</span>::$datas;</span><br><span class="line"> $result = $data[$id] ?? <span class="string">''</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">echo</span> $result.<span class="string">"\n"</span>;</span><br><span class="line"> <span class="keyword">return</span> $result;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__call</span><span class="params">($name, $arguments)</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="keyword">foreach</span>($arguments <span class="keyword">as</span> $argv){</span><br><span class="line"> <span class="keyword">$this</span>->$name($argv);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">static</span> <span class="function"><span class="keyword">function</span> <span class="title">__callStatic</span><span class="params">($name, $arguments)</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="keyword">foreach</span>($arguments <span class="keyword">as</span> $argv){</span><br><span class="line"> (<span class="keyword">new</span> <span class="keyword">static</span>)->$name($argv);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Product</span> <span class="keyword">extends</span> <span class="title">Model</span></span></span><br><span class="line"><span class="class"></span>{</span><br><span class="line"> <span class="keyword">protected</span> <span class="keyword">static</span> $datas = <span class="keyword">array</span>(</span><br><span class="line"> <span class="number">1</span> => <span class="string">'php'</span>,</span><br><span class="line"> <span class="number">2</span> => <span class="string">'python'</span>,</span><br><span class="line"> <span class="number">3</span> => <span class="string">'go'</span>,</span><br><span class="line"> <span class="number">4</span> => <span class="string">'c'</span></span><br><span class="line"> );</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">Product::find(<span class="number">1</span>,<span class="number">2</span>);</span><br><span class="line"></span><br><span class="line">$p = <span class="keyword">new</span> Product();</span><br><span class="line">$p->find(<span class="number">3</span>,<span class="number">4</span>);</span><br></pre></td></tr></table></figure></p><p>输出结果:<br><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">php</span><br><span class="line">python</span><br><span class="line">go</span><br><span class="line">c</span><br></pre></td></tr></table></figure></p><h2 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h2><p>后期静态绑定大致就这些了,都是参考 <a href="http://php.net/manual/zh/language.oop5.late-static-bindings.php" target="_blank" rel="noopener">官方网站</a> 学习的,大家想了解更多,可以去看一下。</p>]]></content>
<summary type="html">
<p>从 PHP 5.3.0 开始,PHP 增加了一个叫做<code>后期静态绑定</code>的功能,用于在继承范围内引用静态调用的类。简单的说就是:使用 <code>static::</code> 关键字时,类名称不是当前方法所在的类,而是当前对象实例所属的类或者当前调用的类。<br>使用(static)关键字来表示这个别名,和静态方法,静态类没有半毛钱的关系,static::不仅支持静态类,还支持对象(动态类)。<br>
</summary>
<category term="PHP" scheme="http://blog.feifan.news/categories/PHP/"/>
<category term="PHP" scheme="http://blog.feifan.news/tags/PHP/"/>
</entry>
<entry>
<title>ElasticSearch集群搭建</title>
<link href="http://blog.feifan.news/2018/09/13/es-cluster/"/>
<id>http://blog.feifan.news/2018/09/13/es-cluster/</id>
<published>2018-09-13T10:04:05.000Z</published>
<updated>2019-05-06T15:38:02.750Z</updated>
<content type="html"><![CDATA[<h2 id="1、需要下载的文件"><a href="#1、需要下载的文件" class="headerlink" title="1、需要下载的文件"></a>1、需要下载的文件</h2><p>文件安装包</p><pre><code>* elasticsearch-head-master* elasticsearch</code></pre><a id="more"></a><p>下载地址:</p><pre><code>* https://www.elastic.co/downloads/elasticsearch * https://github.com/mobz/elasticsearch-head</code></pre><p>文件列表:</p><pre><code>* elasticsearch-head-master* elasticsearch1* elasticsearch2</code></pre><h2 id="2、修改host文件"><a href="#2、修改host文件" class="headerlink" title="2、修改host文件"></a>2、修改host文件</h2><p>127.0.0.1 host1<br>127.0.0.1 host2</p><h2 id="3、修改ES的配置文件"><a href="#3、修改ES的配置文件" class="headerlink" title="3、修改ES的配置文件"></a>3、修改ES的配置文件</h2><p>修改elasticsearch.yml文件<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line">#配置文件中未改动的位置我就不展示了</span><br><span class="line"></span><br><span class="line"> #第一个配置文件改动如下</span><br><span class="line"> #集群名称(必须一样)</span><br><span class="line"> cluster.name: carryless-es</span><br><span class="line"> #节点名称(必须不一样)</span><br><span class="line"> node.name: node-1</span><br><span class="line"> #本机的IP地址</span><br><span class="line"> network.host: host1</span><br><span class="line"> #服务的端口号(在本地配置多个时,请注意修改为不一样的端口)</span><br><span class="line"> http.port: 9201</span><br><span class="line"> #服务发现端口</span><br><span class="line"> transport.tcp.port: 9301</span><br><span class="line"> #集群发现IP集合</span><br><span class="line"> discovery.zen.ping.unicast.hosts: ["host1:9301", "host2:9302"]</span><br><span class="line"></span><br><span class="line"> #第二个配置文件改动如下</span><br><span class="line"> cluster.name: carryless-es</span><br><span class="line"> node.name: node-2</span><br><span class="line"> network.host: host2</span><br><span class="line"> http.port: 9202</span><br><span class="line"> transport.tcp.port: 9302</span><br><span class="line"> discovery.zen.ping.unicast.hosts: ["host1:9301", "host2:9302"]</span><br></pre></td></tr></table></figure></p><p>解决elasticsearch服务与elasticsearch-head之间的跨域问题,在各自的配置文件中添加如下两行:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">http.cors.enabled: true</span><br><span class="line">http.cors.allow-origin: "*"</span><br></pre></td></tr></table></figure></p><h2 id="4、elasticsearch-head插件安装"><a href="#4、elasticsearch-head插件安装" class="headerlink" title="4、elasticsearch-head插件安装"></a>4、elasticsearch-head插件安装</h2><p>elasticsearch-head是一个用来浏览、与elasticsearch进行交互的web前端展示插件,使用node.js编写,要使用elasticsearch-head插件,需要有node环境,node.js的安装在此不做赘述,不明白的小伙伴请自行搜索。</p><ul><li><p>首先我们使用命令窗口cmd,进入elasticsearch-head插件的目录中,执行以下代码</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install</span><br></pre></td></tr></table></figure></li><li><p>执行完成后,在当前目录下会多出一个名为node_modules的目录,此目录为自动下载所需模块的文件</p></li><li><p>运行head插件</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm run start</span><br></pre></td></tr></table></figure></li><li><p>然后在浏览器中访问 <a href="http://localhost:9100" target="_blank" rel="noopener">http://localhost:9100</a><br><img src="/images/es_cluster.png" alt="es_cluster"></p></li></ul>]]></content>
<summary type="html">
<h2 id="1、需要下载的文件"><a href="#1、需要下载的文件" class="headerlink" title="1、需要下载的文件"></a>1、需要下载的文件</h2><p>文件安装包</p>
<pre><code>* elasticsearch-head-master
* elasticsearch
</code></pre>
</summary>
<category term="ElasticSearch" scheme="http://blog.feifan.news/categories/ElasticSearch/"/>
<category term="ES" scheme="http://blog.feifan.news/tags/ES/"/>
</entry>
<entry>
<title>自然语言处理(一)</title>
<link href="http://blog.feifan.news/2018/09/10/nlp-v1/"/>
<id>http://blog.feifan.news/2018/09/10/nlp-v1/</id>
<published>2018-09-10T07:17:34.000Z</published>
<updated>2019-05-06T15:38:02.759Z</updated>
<content type="html"><![CDATA[<p>自然语言处理(Natural Language Processing,NLP)是研究能够实现人与计算机之间用自然语言进行有效通信的各种理论和方法,也是人工智能领域中一个最重要、最艰难的方向。</p><p>近些年NLP的突破:中文分词、词性标注、词汇语义、语法解析<br><a id="more"></a></p><p>文本方面:基于自然语言理解的智能搜索引擎、智能搜索、机器翻译、自动摘要、文本综合、文本分类、信息过滤、垃圾邮件处理、文本数据挖掘等</p><p>语音方面:智能客服、聊天机器人、多媒体信息提取与文本转化</p><h2 id="现在自然语言系统"><a href="#现在自然语言系统" class="headerlink" title="现在自然语言系统"></a>现在自然语言系统</h2><p>自然语言系统基础模块:语言的解析、语义的理解、语言的生成<br><img src="/images/nlp-1.png" alt="nlp-1"><br>自然语言处理的一般构架:<br><img src="/images/nlp-2.png" alt="nlp-2"><br>左侧是语法层面的模块:中文分词、词性标注、句法解析<br>右侧侧重于语义层面:命名实体识别主要用来识别语料中专有名词和未登录词的成词情况,如人名、地名、组织结构名等。受到左侧的中文分词和此行标注的影响。</p><h2 id="开源的中文NLP系统"><a href="#开源的中文NLP系统" class="headerlink" title="开源的中文NLP系统"></a>开源的中文NLP系统</h2><div class="table-container"><table><thead><tr><th>名称</th><th>包含模块</th><th>开发语言</th></tr></thead><tbody><tr><td><a href="https://www.ltp-cloud.com/" target="_blank" rel="noopener">哈工大LTP</a></td><td>中文分词、词性标注、未登录词识别、句法分析、语义角色标注、关键字提取<br>文档:<a href="https://ltp.readthedocs.io/zh_CN/latest/index.html" target="_blank" rel="noopener">https://ltp.readthedocs.io/zh_CN/latest/index.html</a><br>Python文档:<a href="https://pyltp.readthedocs.io/zh_CN/latest/" target="_blank" rel="noopener">https://pyltp.readthedocs.io/zh_CN/latest/</a></td><td>C++</td></tr><tr><td><a href="https://nlp.stanford.edu/software/index.html" target="_blank" rel="noopener">Stanford</a></td><td>中文分词、词性标注、未登录词识别、句法分析、关键词提取</td><td>Java</td></tr><tr><td><a href="https://github.com/fxsjy/jieba" target="_blank" rel="noopener">jieba</a></td><td>中文分词、关键词提取、词性标注、并行分词</td><td>Python</td></tr></tbody></table></div><h2 id="整合中文分词模块"><a href="#整合中文分词模块" class="headerlink" title="整合中文分词模块"></a>整合中文分词模块</h2><p>汉语自然语言处理的第一步就是中文分词,按照算法的不同,介绍两大类中文分词模块:</p><ul><li>基于条件随机场(CRF)的中文分词算法开源系统(哈工大的HIT LTP)</li><li>基于张华平NShort的中文分词算法开源系统(结巴分词)</li></ul><h2 id="整合词性标注模块"><a href="#整合词性标注模块" class="headerlink" title="整合词性标注模块"></a>整合词性标注模块</h2><p>词性标注(Port-Of-Speech Tagging),又称为词类标注,是指判断出在一个句子中每一词所扮演的语法角色。例如:表示人、事物、地点或抽象概念的名称等,词性标注算法比较统一。</p><ul><li>大多数使用HMM(隐马尔科夫模型)或者最大熵算法(如:结巴分词的词性实现)</li><li>使用CRF算法实现(例如:哈工大的LTP3.3中的词性标注)<br>目前最流行的中文词性标签有两大类:北大词性标注集和宾州词性标注集</li></ul>]]></content>
<summary type="html">
<p>自然语言处理(Natural Language Processing,NLP)是研究能够实现人与计算机之间用自然语言进行有效通信的各种理论和方法,也是人工智能领域中一个最重要、最艰难的方向。</p>
<p>近些年NLP的突破:中文分词、词性标注、词汇语义、语法解析<br>
</summary>
<category term="机器学习" scheme="http://blog.feifan.news/categories/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/"/>
<category term="NLP" scheme="http://blog.feifan.news/tags/NLP/"/>
</entry>
<entry>
<title>ElasticSearch学习笔记(一)</title>
<link href="http://blog.feifan.news/2018/09/06/elasticsearch/"/>
<id>http://blog.feifan.news/2018/09/06/elasticsearch/</id>
<published>2018-09-06T00:43:11.000Z</published>
<updated>2019-05-06T15:38:02.758Z</updated>
<content type="html"><![CDATA[<h2 id="(一)ES的安装"><a href="#(一)ES的安装" class="headerlink" title="(一)ES的安装"></a>(一)ES的安装</h2><h3 id="1、安装前准备"><a href="#1、安装前准备" class="headerlink" title="1、安装前准备"></a>1、安装前准备</h3><p>elasticsearch是使用java开发的,所以必须安装Java环境<br><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">[root@iZ2zee30op42zedrik59weZ ~]<span class="comment"># yum install java</span></span><br></pre></td></tr></table></figure></p><a id="more"></a><h3 id="2、直接下载安装包后,解压即可"><a href="#2、直接下载安装包后,解压即可" class="headerlink" title="2、直接下载安装包后,解压即可"></a>2、直接下载安装包后,解压即可</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">[root@iZ2zee30op42zedrik59weZ ~]<span class="comment"># https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-5.5.0.zip</span></span><br><span class="line">[root@iZ2zee30op42zedrik59weZ ~]<span class="comment"># unzip elasticsearch-5.5.0.zip</span></span><br></pre></td></tr></table></figure><h3 id="3、运行elasticsearch"><a href="#3、运行elasticsearch" class="headerlink" title="3、运行elasticsearch"></a>3、运行elasticsearch</h3><p>进入elasticsearch目录,运行 bin/elasticsearch (or bin\elasticsearch.bat on Windows)</p><h3 id="4、验证"><a href="#4、验证" class="headerlink" title="4、验证"></a>4、验证</h3><p>在shell中输入 curl <a href="http://localhost:9200/" target="_blank" rel="noopener">http://localhost:9200/</a> or Invoke-RestMethod <a href="http://localhost:9200" target="_blank" rel="noopener">http://localhost:9200</a> </p><h3 id="5、遇到的问题"><a href="#5、遇到的问题" class="headerlink" title="5、遇到的问题"></a>5、遇到的问题</h3><p>问题一:OpenJDK 64-Bit Server VM warning: INFO: os::commit_memory(0x0000000085330000, 2060255232, 0) failed; error=’Cannot allocate memory’ (errno=12)</p><pre><code>解决办法:由于elasticsearch5.0默认分配jvm空间大小为2g,修改jvm空间分配<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="number">22</span> <span class="comment"># -Xms2g</span></span><br><span class="line"><span class="number">23</span> <span class="comment"># -Xmx2g</span></span><br><span class="line"><span class="number">24</span> -Xms512m</span><br><span class="line"><span class="number">25</span> -Xmx512m</span><br></pre></td></tr></table></figure></code></pre><p>问题二:Caused by: java.lang.RuntimeException: can not run elasticsearch as root</p><pre><code>解决办法:+ 异常描述为不能以root权限运行Elasticsearch.解决办法是运行时加上参数:<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">bin/elasticsearch -Des.insecure.allow.root=true</span><br></pre></td></tr></table></figure>+ 或者修改bin/elasticsearch,加上ES_JAVA_OPTS属性:<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ES_JAVA_OPTS=<span class="string">"-Des.insecure.allow.root=true"</span></span><br></pre></td></tr></table></figure></code></pre><p>问题三:ERROR: D is not a recognized option</p><pre><code>解决办法:其实上一个错误可以忽略,直接运行下面即可+ 创建用户组和用户<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">[root@iZ2zee30op42zedrik59weZ bin]<span class="comment"># groupadd es</span></span><br><span class="line">[root@iZ2zee30op42zedrik59weZ bin]<span class="comment"># useradd liushuaicai -g es -p liushuaicai</span></span><br><span class="line">[root@iZ2zee30op42zedrik59weZ local]<span class="comment"># chown -R liushuaicai:es elasticsearch-5.5.0/</span></span><br><span class="line">[root@iZ2zee30op42zedrik59weZ local]<span class="comment"># su liushuaicai</span></span><br><span class="line">[liushuaicai@iZ2zee30op42zedrik59weZ local]$ cd elasticsearch<span class="number">-5.5</span><span class="number">.0</span>/</span><br><span class="line">[liushuaicai@iZ2zee30op42zedrik59weZ elasticsearch<span class="number">-5.5</span><span class="number">.0</span>]$ ./bin/elasticsearch</span><br></pre></td></tr></table></figure></code></pre><blockquote><p>安装结束。。。</p></blockquote><hr><h2 id="(二)Python连接ES"><a href="#(二)Python连接ES" class="headerlink" title="(二)Python连接ES"></a>(二)Python连接ES</h2><p>这里主要是使用Python来操作ElasticSearch,先介绍一下Python怎样连接ES。</p><h3 id="1、安装elasticsearch扩展包"><a href="#1、安装elasticsearch扩展包" class="headerlink" title="1、安装elasticsearch扩展包"></a>1、安装elasticsearch扩展包</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">pip3 install elasticsearch</span><br></pre></td></tr></table></figure><h3 id="2、连接方式"><a href="#2、连接方式" class="headerlink" title="2、连接方式"></a>2、连接方式</h3><p>有以下几种连接方式:<br>a)、本地连接方式<br><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> elasticsearch <span class="keyword">import</span> Elasticsearch</span><br><span class="line"></span><br><span class="line">es = Elasticsearch()</span><br></pre></td></tr></table></figure></p><p>b)、连接多个ES<br><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> elasticsearch <span class="keyword">import</span> Elasticsearch</span><br><span class="line"></span><br><span class="line">es = Elasticsearch([<span class="string">'localhost:443'</span>, <span class="string">'other_host:443'</span>])</span><br></pre></td></tr></table></figure></p><p>b)、用户密码连接方式<br><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> elasticsearch <span class="keyword">import</span> Elasticsearch</span><br><span class="line"></span><br><span class="line"><span class="comment"># you can use RFC-1738 to specify the url</span></span><br><span class="line">es = Elasticsearch([<span class="string">'https://user:secret@localhost:443'</span>])</span><br><span class="line"></span><br><span class="line"><span class="comment"># ... or specify common parameters as kwargs</span></span><br><span class="line">es = Elasticsearch(</span><br><span class="line"> [<span class="string">'localhost'</span>, <span class="string">'otherhost'</span>],</span><br><span class="line"> http_auth=(<span class="string">'user'</span>, <span class="string">'secret'</span>),</span><br><span class="line"> scheme=<span class="string">"https"</span>,</span><br><span class="line"> port=<span class="number">443</span>,</span><br><span class="line">)</span><br><span class="line"></span><br><span class="line"><span class="comment"># SSL client authentication using client_cert and client_key</span></span><br><span class="line"><span class="keyword">from</span> ssl <span class="keyword">import</span> create_default_context</span><br><span class="line">context = create_default_context(cafile=<span class="string">"path/to/cert.pem"</span>)</span><br><span class="line">es = Elasticsearch(</span><br><span class="line"> [<span class="string">'localhost'</span>, <span class="string">'otherhost'</span>],</span><br><span class="line"> http_auth=(<span class="string">'user'</span>, <span class="string">'secret'</span>),</span><br><span class="line"> scheme=<span class="string">"https"</span>,</span><br><span class="line"> port=<span class="number">443</span>,</span><br><span class="line"> ssl_context=context,</span><br><span class="line">)</span><br></pre></td></tr></table></figure></p><p>更多的连接方式,可以查看 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html" target="_blank" rel="noopener">官方文档</a>或者<a href="https://elasticsearch-py.readthedocs.io/en/master/" target="_blank" rel="noopener">elasticsearch-py</a></p><p>⚠️ 警告</p><pre><code>elasticsearch-py不附带默认的根证书集。有工作的SSL证书验证您需要可以指定自己的作为cafile或capath或cadata 或安装CERTIFI将被自动拾取。</code></pre><h2 id="(三)创建索引"><a href="#(三)创建索引" class="headerlink" title="(三)创建索引"></a>(三)创建索引</h2><p>ES的索引和MySql的作用是一样的,优化索引可以提高搜索速度</p><h3 id="1、非正规创建"><a href="#1、非正规创建" class="headerlink" title="1、非正规创建"></a>1、非正规创建</h3><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> elasticsearch <span class="keyword">import</span> Elasticsearch</span><br><span class="line">es = Elasticsearch()</span><br><span class="line">doc = {</span><br><span class="line"> <span class="string">'name'</span>: <span class="string">'lsc'</span>,</span><br><span class="line"> <span class="string">'age'</span>: <span class="number">23</span>,</span><br><span class="line"> <span class="string">'sex'</span>: <span class="number">1</span>,</span><br><span class="line"> <span class="string">'job'</span>: <span class="string">'php'</span>,</span><br><span class="line"> <span class="string">'other'</span>: {</span><br><span class="line"> <span class="string">'from'</span>: <span class="string">'henan'</span>,</span><br><span class="line"> <span class="string">'city'</span>: <span class="string">'beijing'</span></span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">res = es.index(index=<span class="string">'crm'</span>, doc_type=<span class="string">'user'</span>, id=<span class="number">1</span>, body=doc)</span><br><span class="line">print(res[<span class="string">'result'</span>])</span><br></pre></td></tr></table></figure><h2 id="(最后)ES小笔记"><a href="#(最后)ES小笔记" class="headerlink" title="(最后)ES小笔记"></a>(最后)ES小笔记</h2><h4 id="ES和关系型数据库的区别"><a href="#ES和关系型数据库的区别" class="headerlink" title="ES和关系型数据库的区别"></a>ES和关系型数据库的区别</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">Relational DB -> Databases -> Tables -> Rows -> Columns</span><br><span class="line">ElasticSearch -> Indices -> Types -> Documents -> Fields</span><br></pre></td></tr></table></figure><h4 id="集群健康"><a href="#集群健康" class="headerlink" title="集群健康"></a>集群健康</h4><blockquote><p>ES根据status判断集群的健康状态,status包括:green|yellow|red 三种颜色</p></blockquote><div class="table-container"><table><thead><tr><th>颜色</th><th>意义</th></tr></thead><tbody><tr><td>green</td><td>所有主分片和副分片都可用</td></tr><tr><td>yellow</td><td>所有主分片都可用,但不是所有的副分片都可用</td></tr><tr><td>red</td><td>不是所有的主分片都可用</td></tr></tbody></table></div><h4 id="分片"><a href="#分片" class="headerlink" title="分片"></a>分片</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">1、一个分片是一个最小级别的“工作单元”,只是保存索引中所有数据的一小片;</span><br><span class="line">2、是一个单一的Lucene实例</span><br><span class="line">3、本身就是一个完整的搜素引擎</span><br></pre></td></tr></table></figure><h6 id="作用"><a href="#作用" class="headerlink" title="作用"></a>作用</h6><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">1、在集群中分配数据</span><br><span class="line">2、文档存储在分片上,分片分配给你的集群节点上</span><br><span class="line">3、索引中的每个文档都属于一个单独的主分片,主分片的数量决定了你最多存储多少数据(理论上主分片对存储多少数据并没有限制,限制取决于实际的使用情况)</span><br></pre></td></tr></table></figure><h6 id="主分片、复制分片"><a href="#主分片、复制分片" class="headerlink" title="主分片、复制分片"></a>主分片、复制分片</h6><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line">1、复制分片只是主分片的一个副本</span><br><span class="line">2、主分片的数量会在其索引创建完成后修正,但是复制分片的数量会随时变化的</span><br><span class="line">3、下面就是创建的3个主分片1个复制分片(每一个主分片有一个复制分片对应,也就是相当于有3个复制分片)</span><br><span class="line">{</span><br><span class="line"> "settings" : {</span><br><span class="line"> "number_of_shards" : 3,</span><br><span class="line"> "number_of_replicas" : 1</span><br><span class="line"> }</span><br><span class="line">}</span><br><span class="line">4、同一个节点上保存相同的数据副本是没用的,如果这个节点故障了,所有的数据也就丢失了</span><br></pre></td></tr></table></figure><h4 id="数据"><a href="#数据" class="headerlink" title="数据"></a>数据</h4><h6 id="请求方法"><a href="#请求方法" class="headerlink" title="请求方法"></a>请求方法</h6><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">GET:获取数据</span><br><span class="line">POST:新增数据</span><br><span class="line">PUT:更新|新增指定数据,也就是带上ID</span><br><span class="line">DELETE:删除文档</span><br><span class="line">HEAD:判断数据是否存在</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
<h2 id="(一)ES的安装"><a href="#(一)ES的安装" class="headerlink" title="(一)ES的安装"></a>(一)ES的安装</h2><h3 id="1、安装前准备"><a href="#1、安装前准备" class="headerlink" title="1、安装前准备"></a>1、安装前准备</h3><p>elasticsearch是使用java开发的,所以必须安装Java环境<br><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">[root@iZ2zee30op42zedrik59weZ ~]<span class="comment"># yum install java</span></span><br></pre></td></tr></table></figure></p>
</summary>
<category term="ElasticSearch" scheme="http://blog.feifan.news/categories/ElasticSearch/"/>
<category term="ES" scheme="http://blog.feifan.news/tags/ES/"/>
</entry>
<entry>
<title>常用激活函数</title>
<link href="http://blog.feifan.news/2018/08/30/active_funcation/"/>
<id>http://blog.feifan.news/2018/08/30/active_funcation/</id>
<published>2018-08-30T06:06:08.000Z</published>
<updated>2019-05-06T15:38:02.748Z</updated>
<content type="html"><![CDATA[<h2 id="1、激活函数介绍"><a href="#1、激活函数介绍" class="headerlink" title="1、激活函数介绍"></a>1、激活函数介绍</h2><h3 id="1-1、什么是激活函数"><a href="#1-1、什么是激活函数" class="headerlink" title="1.1、什么是激活函数"></a>1.1、什么是激活函数</h3><p>如下图,在神经元中,输入的 inputs 通过加权,求和后,还被作用了一个函数,这个函数就是激活函数 Activation Function。<br><img src="/images/active.png" alt="activate"><br><a id="more"></a></p><h3 id="1-2、激活函数的特点"><a href="#1-2、激活函数的特点" class="headerlink" title="1.2、激活函数的特点"></a>1.2、激活函数的特点</h3><p>非线性: 当激活函数是线性的时候,一个两层的神经网络就可以逼近基本上所有的函数了。<br>可微: 当优化方法是基于梯度的时候,这个性质是必须的。<br>单调性: 当激活函数是单调的时候,单层网络能够保证是凸函数。<br>_ : 当激活函数满足这个性质的时候,如果参数的初始化是random的很小的值,那么神经网络的训练将会很高效。<br>输出值范围: 当激活函数输出值是 有限 的时候,基于梯度的优化方法会更加 稳定,因为特征的表示受有限权值的影响更显著;当激活函数的输出是 无限 的时候,模型的训练会更加高效,不过在这种情况小,一般需要更小的学习率。</p><h3 id="1-3、为什么要用激活函数"><a href="#1-3、为什么要用激活函数" class="headerlink" title="1.3、为什么要用激活函数"></a>1.3、为什么要用激活函数</h3><p>如果不用激励函数,每一层输出都是上层输入的线性函数,无论神经网络有多少层,输出都是输入的线性组合。<br>如果使用的话,激活函数给神经元引入了非线性因素,使得神经网络可以任意逼近任何非线性函数,这样神经网络就可以应用到众多的非线性模型中。</p><h2 id="2、sigmoid函数"><a href="#2、sigmoid函数" class="headerlink" title="2、sigmoid函数"></a>2、sigmoid函数</h2><p>公式:<script type="math/tex">\sigma(x) = \frac{1}{1 + e^{-x}}</script></p><p><img src="/images/sigmoid.png" alt="sigmoid"><br>在sigmod函数中我们可以看到,其输出是在(0,1)这个开区间内,这点很有意思,可以联想到概率,但是严格意义上讲,不要当成概率。sigmod函数曾经是比较流行的,它可以想象成一个神经元的放电率,在中间斜率比较大的地方是神经元的敏感区,在两边斜率很平缓的地方是神经元的抑制区。<br>当然,流行也是曾经流行,这说明函数本身是有一定的缺陷的。</p><h3 id="2-1、sigmoid函数作用"><a href="#2-1、sigmoid函数作用" class="headerlink" title="2.1、sigmoid函数作用"></a>2.1、sigmoid函数作用</h3><p>sigmoid函数也叫 Logistic 函数,用于隐层神经元输出,取值范围为(0,1),它可以将一个实数映射到(0,1)的区间,可以用来做二分类。<br>在特征相差比较复杂或是相差不是特别大时效果比较好。</p><h3 id="2-2、sigmoid缺点"><a href="#2-2、sigmoid缺点" class="headerlink" title="2.2、sigmoid缺点"></a>2.2、sigmoid缺点</h3><p>1) 当输入稍微远离了坐标原点,函数的梯度就变得很小了,几乎为零。在神经网络反向传播的过程中,我们都是通过微分的链式法则来计算各个权重w的微分的。当反向传播经过了sigmod函数,这个链条上的微分就很小很小了,况且还可能经过很多个sigmod函数,最后会导致权重w对损失函数几乎没影响,这样不利于权重的优化,这个问题叫做梯度饱和,也可以叫梯度弥散。<br>2) 函数输出不是以0为中心的,这样会使权重更新效率降低。对于这个缺陷,在斯坦福的课程里面有详细的解释。<br>3) Sigmoids函数收敛缓慢;sigmod函数要进行指数运算,这个对于计算机来说是比较慢的。</p><h3 id="2-3、sigmoid函数求导"><a href="#2-3、sigmoid函数求导" class="headerlink" title="2.3、sigmoid函数求导"></a>2.3、sigmoid函数求导</h3><p>下面解释为何会出现梯度消失:<br>反向传播算法中,要对激活函数求导,sigmoid 的导数表达式为:<script type="math/tex">\Phi'(x) = \Phi(x)(1-\Phi(x))</script><br>求导推理:<script type="math/tex">\sigma'(x) = (\frac {1}{1 + e^{-x}})'</script><br>=> <script type="math/tex">= \frac {e^{-x}}{(1 + e^{-x})^2}</script><br>=> <script type="math/tex">= \frac {1+e^{-x}-1}{(1+e^{-x})^2}</script><br>=> <script type="math/tex">= \frac {1}{1+e^{-x}}(1-\frac {1}{1+e^{-x}})</script><br><br><br>=> <script type="math/tex">= f(x)(1-f(x))</script></p><p>求导图像如下:<br><img src="/images/sigmoid_re.png" alt="sigmoid"><br>由图可知,导数从 0 开始很快就又趋近于 0 了,易造成“梯度消失”现象</p><p>python代码:<br><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">from</span> matplotlib <span class="keyword">import</span> pyplot <span class="keyword">as</span> plt</span><br><span class="line"><span class="keyword">import</span> numpy <span class="keyword">as</span> np</span><br><span class="line"></span><br><span class="line"><span class="comment"># sigmoid函数公式</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">sigmoid</span><span class="params">(x)</span>:</span></span><br><span class="line"> y = <span class="number">1</span> / (<span class="number">1</span> + np.exp(-x))</span><br><span class="line"> <span class="keyword">return</span> y</span><br><span class="line"><span class="comment"># sigmoid函数导数</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">re_sigmoid</span><span class="params">(y)</span>:</span></span><br><span class="line"> y_ = y * (<span class="number">1</span>-y)</span><br><span class="line"> <span class="keyword">return</span> y_</span><br><span class="line"></span><br><span class="line"><span class="comment"># sigmoid 显示</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">plot_sigmoid</span><span class="params">()</span>:</span></span><br><span class="line"> x = np.arange(<span class="number">-8</span>, <span class="number">8</span>, <span class="number">0.2</span>)</span><br><span class="line"> y = sigmoid(x)</span><br><span class="line"> y_ = re_sigmoid(y)</span><br><span class="line"></span><br><span class="line"> <span class="comment"># 设置坐标原点</span></span><br><span class="line"> fig, ax = plt.subplots()</span><br><span class="line"> <span class="comment"># 隐藏上、右边</span></span><br><span class="line"> ax.spines[<span class="string">'right'</span>].set_color(<span class="string">'none'</span>)</span><br><span class="line"> ax.spines[<span class="string">'top'</span>].set_color(<span class="string">'none'</span>)</span><br><span class="line"> <span class="comment"># 设置左下边为轴</span></span><br><span class="line"> ax.xaxis.set_ticks_position(<span class="string">'bottom'</span>)</span><br><span class="line"> ax.spines[<span class="string">'bottom'</span>].set_position((<span class="string">'data'</span>, <span class="number">0</span>))</span><br><span class="line"> ax.yaxis.set_ticks_position(<span class="string">'left'</span>)</span><br><span class="line"> ax.spines[<span class="string">'left'</span>].set_position((<span class="string">'data'</span>, <span class="number">0</span>))</span><br><span class="line"> ax.plot(x, y)</span><br><span class="line"> ax.plot(y, y_)</span><br><span class="line"> <span class="comment"># 设置边距</span></span><br><span class="line"> ax.set_xticks(np.arange(<span class="number">-5</span>, <span class="number">5.1</span>, <span class="number">2</span>))</span><br><span class="line"> ax.set_yticks(np.arange(<span class="number">-0.5</span>, <span class="number">1.1</span>, <span class="number">0.5</span>))</span><br><span class="line"> </span><br><span class="line"> </span><br><span class="line">plot_sigmoid()</span><br></pre></td></tr></table></figure></p><h2 id="3、正切函数(tanh函数)"><a href="#3、正切函数(tanh函数)" class="headerlink" title="3、正切函数(tanh函数)"></a>3、正切函数(tanh函数)</h2><p>公式:<script type="math/tex">\tanh(x) = \frac {\sinh(x)}{\cosh(x)} = \frac {e^x - e^{-x}}{e^x + e^{-x}}</script><br><img src="/images/tanh.png" alt="tanh"><br>tanh是双曲正切函数,tanh函数和sigmod函数的曲线是比较相近的,咱们来比较一下看看。首先相同的是,这两个函数在输入很大或是很小的时候,输出都几乎平滑,梯度很小,不利于权重更新;不同的是输出区间,tanh的输出区间是在(-1,1)之间,而且整个函数是以0为中心的,这个特点比sigmod的好。</p><p>一般二分类问题中,隐藏层用tanh函数,输出层用sigmod函数。不过这些也都不是一成不变的,具体使用什么激活函数,还是要根据具体的问题来具体分析,还是要靠调试的。</p><p>python 代码:<br><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># tanh函数公式</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">tanh</span><span class="params">(x=<span class="number">0</span>, bool=False)</span>:</span></span><br><span class="line"> <span class="keyword">if</span> bool==<span class="keyword">False</span>:</span><br><span class="line"> y = (np.exp(x) - <span class="number">1</span>/np.exp(x)) / (np.exp(x) + <span class="number">1</span>/np.exp(x))</span><br><span class="line"> <span class="keyword">else</span>:</span><br><span class="line"> y = np.tanh((<span class="number">0</span>, np.pi*<span class="number">1j</span>, np.pi*<span class="number">1j</span>/<span class="number">2</span>))</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">return</span> y</span><br><span class="line"> </span><br><span class="line"><span class="comment"># tanh函数显示</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">plot_tanh</span><span class="params">()</span>:</span></span><br><span class="line"> x = np.arange(<span class="number">-8</span>, <span class="number">8</span>, <span class="number">0.2</span>)</span><br><span class="line"> y = tanh(x)</span><br><span class="line"> <span class="comment"># 设置坐标原点</span></span><br><span class="line"> fig, ax = plt.subplots()</span><br><span class="line"> <span class="comment"># 隐藏上、右边</span></span><br><span class="line"> ax.spines[<span class="string">'right'</span>].set_color(<span class="string">'none'</span>)</span><br><span class="line"> ax.spines[<span class="string">'top'</span>].set_color(<span class="string">'none'</span>)</span><br><span class="line"> <span class="comment"># 设置左下边为轴</span></span><br><span class="line"> ax.xaxis.set_ticks_position(<span class="string">'bottom'</span>)</span><br><span class="line"> ax.spines[<span class="string">'bottom'</span>].set_position((<span class="string">'data'</span>, <span class="number">0</span>))</span><br><span class="line"> ax.yaxis.set_ticks_position(<span class="string">'left'</span>)</span><br><span class="line"> ax.spines[<span class="string">'left'</span>].set_position((<span class="string">'data'</span>, <span class="number">0</span>))</span><br><span class="line"> ax.plot(x, y)</span><br><span class="line"> <span class="comment"># 设置边距</span></span><br><span class="line"> ax.set_xticks(np.arange(<span class="number">-5</span>, <span class="number">5.1</span>, <span class="number">1</span>))</span><br><span class="line"> ax.set_yticks(np.arange(<span class="number">-1.0</span>, <span class="number">1.1</span>, <span class="number">0.5</span>))</span><br><span class="line">plot_tanh()</span><br></pre></td></tr></table></figure></p><h2 id="4、线性整流函数(ReLU函数)"><a href="#4、线性整流函数(ReLU函数)" class="headerlink" title="4、线性整流函数(ReLU函数)"></a>4、线性整流函数(ReLU函数)</h2><h3 id="4-1、定义(来自wiki)"><a href="#4-1、定义(来自wiki)" class="headerlink" title="4.1、定义(来自wiki)"></a>4.1、定义(来自<a href="https://zh.wikipedia.org/wiki/%E7%BA%BF%E6%80%A7%E6%95%B4%E6%B5%81%E5%87%BD%E6%95%B0" target="_blank" rel="noopener">wiki</a>)</h3><p>线性整流函数(Rectified Linear Unit, ReLU),又称修正线性单元, 是一种人工神经网络中常用的激活函数(activation function),通常指代以斜坡函数及其变种为代表的非线性函数。<br>通常意义下,线性整流函数指代数学中的斜坡函数,即</p><script type="math/tex; mode=display">f(x)=max(0,x)</script><p>而在神经网络中,线性整流作为神经元的激活函数,定义了该神经元在线性变换 <script type="math/tex">\mathbf {w} ^{T}\mathbf {x} +b</script>之后的非线性输出结果。换言之,对于进入神经元的来自上一层神经网络的输入向量 x,使用线性整流激活函数的神经元会输出</p><script type="math/tex; mode=display">\max(0,\mathbf {w} ^{T}\mathbf {x} +b)</script><p>至下一层神经元或作为整个神经网络的输出(取决现神经元在网络结构中所处位置)。<br><img src="/images/relu.png" alt="relu"></p><h3 id="4-2、优、缺点"><a href="#4-2、优、缺点" class="headerlink" title="4.2、优、缺点"></a>4.2、优、缺点</h3><p>优点:<br>1) 在输入为正数的时候,不存在梯度饱和问题,相比之下,逻辑函数在输入为0时达到 <script type="math/tex">\frac {1}{2}</script>,即已经是半饱和的稳定状态。<br>2) 计算速度要快很多。ReLU函数只有线性关系,不管是前向传播还是反向传播,都比sigmod和tanh要快很多。(sigmod和tanh要计算指数,计算速度会比较慢)<br>3)更加有效率的梯度下降以及反向传播:避免了梯度爆炸和梯度消失问题</p><p>缺点:<br>1) 当输入是负数的时候,ReLU是完全不被激活的,这就表明一旦输入到了负数,ReLU就会死掉。这样在前向传播过程中,还不算什么问题,有的区域是敏感的,有的是不敏感的。但是到了反向传播过程中,输入负数,梯度就会完全到0,这个和sigmod函数、tanh函数有一样的问题。<br>2) 我们发现ReLU函数的输出要么是0,要么是正数,这也就是说,ReLU函数也不是以0为中心的函数。</p><h3 id="4-3、ReLU的几种变形"><a href="#4-3、ReLU的几种变形" class="headerlink" title="4.3、ReLU的几种变形"></a>4.3、ReLU的几种变形</h3><p>4.3.1、带泄露线性整流(Leaky ReLU)<br>在输入值 x 为负的时候,带泄露线性整流函数(Leaky ReLU)的梯度为一个常数 <script type="math/tex">\lambda \in (0,1)</script>,而不是0。在输入值为正的时候,带泄露线性整流函数和普通斜坡函数保持一致。</p><script type="math/tex; mode=display">f(x)={\begin{cases}x&{\mbox{if }}x>0\\\lambda x&{\mbox{if }}x\leq 0\end{cases}}</script><p>4.3.2、参数线性整流(Parametric ReLU)<br>在深度学习中,如果设定 <script type="math/tex">\lambda</script> 为一个可通过<a href="https://zh.wikipedia.org/wiki/%E5%8F%8D%E5%90%91%E4%BC%A0%E6%92%AD%E7%AE%97%E6%B3%95" target="_blank" rel="noopener">反向传播算法</a>(Backpropagation)学习的变量,那么带泄露线性整流又被称为参数线性整流(Parametric ReLU)</p><p>4.3.3、带泄露随机线性整流(Randomized Leaky ReLU, RReLU)<br>带泄露随机线性整流(Randomized Leaky ReLU, RReLU)最早是在Kaggle全美数据科学大赛(NDSB)中被首先提出并使用的。相比于普通带泄露线性整流函数,带泄露随机线性整流在负输入值段的函数梯度 <script type="math/tex">\lambda</script> 是一个取自连续性均匀分布 <script type="math/tex">U(l,u)</script>概率模型的随机变量,即</p><script type="math/tex; mode=display">f(x)={\begin{cases}x&{\mbox{if }}x>0\\\lambda x&{\mbox{if }}x\leq 0\end{cases}}</script><p>其中 <script type="math/tex">\lambda \sim U(l,u),l<u</script> 且 <script type="math/tex">l,u\in [0,1)</script>。</p><p>ReLU函数的python 代码:<br><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># ReLU函数公式</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">relu</span><span class="params">(x)</span>:</span></span><br><span class="line"> <span class="keyword">if</span> x < <span class="number">0</span>:</span><br><span class="line"> y = <span class="number">0</span></span><br><span class="line"> <span class="keyword">else</span>:</span><br><span class="line"> y = x</span><br><span class="line"> <span class="keyword">return</span> y</span><br><span class="line"></span><br><span class="line"><span class="comment"># ReLU函数显示</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">plot_relu</span><span class="params">()</span>:</span></span><br><span class="line"> x = np.arange(<span class="number">-10</span>,<span class="number">10</span>,<span class="number">0.1</span>)</span><br><span class="line"> y = list(map(relu,x))</span><br><span class="line"> </span><br><span class="line"> <span class="comment"># 设置坐标原点</span></span><br><span class="line"> fig, ax = plt.subplots()</span><br><span class="line"> <span class="comment"># 隐藏上、右边</span></span><br><span class="line"> ax.spines[<span class="string">'right'</span>].set_color(<span class="string">'none'</span>)</span><br><span class="line"> ax.spines[<span class="string">'top'</span>].set_color(<span class="string">'none'</span>)</span><br><span class="line"> <span class="comment"># 设置左下边为轴</span></span><br><span class="line"> ax.xaxis.set_ticks_position(<span class="string">'bottom'</span>)</span><br><span class="line"> ax.spines[<span class="string">'bottom'</span>].set_position((<span class="string">'data'</span>, <span class="number">0</span>))</span><br><span class="line"> ax.yaxis.set_ticks_position(<span class="string">'left'</span>)</span><br><span class="line"> ax.spines[<span class="string">'left'</span>].set_position((<span class="string">'data'</span>, <span class="number">0</span>))</span><br><span class="line"> ax.plot(x, y)</span><br><span class="line"></span><br><span class="line">plot_relu()</span><br></pre></td></tr></table></figure></p><h2 id="5、softmax函数(wiki)"><a href="#5、softmax函数(wiki)" class="headerlink" title="5、softmax函数(wiki)"></a>5、softmax函数(<a href="https://zh.wikipedia.org/wiki/Softmax%E5%87%BD%E6%95%B0" target="_blank" rel="noopener">wiki</a>)</h2><p>在数学,尤其是概率论和相关领域中,Softmax函数,或称归一化指数函数,是逻辑函数的一种推广。它能将一个含任意实数的K维向量 <script type="math/tex">\mathbf {z}</script> “压缩”到另一个K维实向量 <script type="math/tex">\sigma (\mathbf {z} )</script> 中,使得每一个元素的范围都在 (0,1) 之间,并且所有元素的和为1。该函数的形式通常按下面的式子给出:</p><script type="math/tex; mode=display">\sigma (\mathbf {z} )_{j}={\frac {e^{z_{j}}}{\sum _{k=1}^{K}e^{z_{k}}}} j \in (1,k)</script><p>如图所示:<br><img src="/images/softmax.png" alt="softmax"></p><p>Softmax函数实际上是有限项离散概率分布的梯度对数归一化。因此,Softmax函数在包括 多项逻辑回归[1]:206–209 ,多项线性判别分析,朴素贝叶斯分类器和人工神经网络等的多种基于概率的多分类问题方法中都有着广泛应用。[2] 特别地,在多项逻辑回归和线性判别分析中,函数的输入是从K个不同的线性函数得到的结果,而样本向量 x 属于第 j 个分类的概率为:</p><script type="math/tex; mode=display">P(y=j|\mathbf {x} )={\frac {e^{\mathbf {x} ^{\mathsf {T}}\mathbf {w} _{j}}}{\sum _{k=1}^{K}e^{\mathbf {x} ^{\mathsf {T}}\mathbf {w} _{k}}}}</script><p>这可以被视作K个线性函数 <script type="math/tex">\mathbf {x} \mapsto \mathbf {x} ^{\mathsf {T}}\mathbf {w} _{1},\ldots ,\mathbf {x} \mapsto \mathbf {x} ^{\mathsf {T}}\mathbf {w} _{K}</script> Softmax函数的复合( <script type="math/tex">{\displaystyle \mathbf {x} ^{\mathsf {T}}\mathbf {w} } {\displaystyle \mathbf {x} } {\displaystyle \mathbf {w} }</script> )。</p><p>python 代码:<br><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"># softmax函数</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">softmax</span><span class="params">(x)</span>:</span></span><br><span class="line"> y = np.exp(x)/sum(np.exp(x))</span><br><span class="line"> <span class="keyword">return</span> y</span><br><span class="line"></span><br><span class="line"><span class="comment"># softmax函数显示</span></span><br><span class="line"><span class="function"><span class="keyword">def</span> <span class="title">plot_softmax</span><span class="params">()</span>:</span></span><br><span class="line"> x = np.arange(<span class="number">-5</span>, <span class="number">5</span>, <span class="number">0.1</span>)</span><br><span class="line"> y = softmax(x)</span><br><span class="line"> <span class="comment"># 设置坐标原点</span></span><br><span class="line"> fig, ax = plt.subplots()</span><br><span class="line"> <span class="comment"># 隐藏上、右边</span></span><br><span class="line"> ax.spines[<span class="string">'right'</span>].set_color(<span class="string">'none'</span>)</span><br><span class="line"> ax.spines[<span class="string">'top'</span>].set_color(<span class="string">'none'</span>)</span><br><span class="line"> <span class="comment"># 设置左下边为轴</span></span><br><span class="line"> ax.xaxis.set_ticks_position(<span class="string">'bottom'</span>)</span><br><span class="line"> ax.spines[<span class="string">'bottom'</span>].set_position((<span class="string">'data'</span>, <span class="number">0</span>))</span><br><span class="line"> ax.yaxis.set_ticks_position(<span class="string">'left'</span>)</span><br><span class="line"> ax.spines[<span class="string">'left'</span>].set_position((<span class="string">'data'</span>, <span class="number">0</span>))</span><br><span class="line"> ax.plot(x, y)</span><br><span class="line"> <span class="comment"># 设置边距</span></span><br><span class="line"> ax.set_xticks(np.arange(<span class="number">-6</span>, <span class="number">6.1</span>, <span class="number">1</span>))</span><br><span class="line"> ax.set_yticks(np.arange(<span class="number">-0.01</span>, <span class="number">0.12</span>, <span class="number">0.01</span>))</span><br><span class="line"></span><br><span class="line">plot_softmax()</span><br></pre></td></tr></table></figure></p><h2 id="6、激活函数图"><a href="#6、激活函数图" class="headerlink" title="6、激活函数图"></a>6、激活函数图</h2><p><img src="/images/active_wiki.jpg" alt="active_wiki"></p>]]></content>
<summary type="html">
<h2 id="1、激活函数介绍"><a href="#1、激活函数介绍" class="headerlink" title="1、激活函数介绍"></a>1、激活函数介绍</h2><h3 id="1-1、什么是激活函数"><a href="#1-1、什么是激活函数" class="headerlink" title="1.1、什么是激活函数"></a>1.1、什么是激活函数</h3><p>如下图,在神经元中,输入的 inputs 通过加权,求和后,还被作用了一个函数,这个函数就是激活函数 Activation Function。<br><img src="/images/active.png" alt="activate"><br>
</summary>
<category term="机器学习" scheme="http://blog.feifan.news/categories/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/"/>
<category term="MachineLearning" scheme="http://blog.feifan.news/tags/MachineLearning/"/>
</entry>
<entry>
<title>word2vec原理分析笔记</title>
<link href="http://blog.feifan.news/2018/08/30/word2vec/"/>
<id>http://blog.feifan.news/2018/08/30/word2vec/</id>
<published>2018-08-30T03:46:09.000Z</published>
<updated>2019-05-06T15:38:02.762Z</updated>
<content type="html"><![CDATA[<h2 id="1、word2vec介绍"><a href="#1、word2vec介绍" class="headerlink" title="1、word2vec介绍"></a>1、word2vec介绍</h2><p>word2vec 是 Google 于 2013 年开源推出的一个用于获取 word vector (词向量)的工具包。<br>特点:简单、高效<br>作用:把文本转化为词向量<br><a id="more"></a></p><h2 id="2、预备知识"><a href="#2、预备知识" class="headerlink" title="2、预备知识"></a>2、预备知识</h2><p>word2vec 中用到的一些重要知识点:sigmoid函数、Beyes公式、Huffman编码</p><h4 id="2-1、sigmoid函数"><a href="#2-1、sigmoid函数" class="headerlink" title="2.1、sigmoid函数"></a>2.1、sigmoid函数</h4><p>sigmoid 函数是神经网络中常用的激活函数之一,其定义为:</p><script type="math/tex; mode=display">\overline{X} = \frac{\sum_{i=1}^{n}X_i}{n}</script><p><code>$x^{y^z} = (1+e^x)^{-2xy^w}$</code></p><script type="math/tex; mode=display">\require{enclose}\begin{array}{}\enclose{horizontalstrike}{x+y}\\\enclose{horizontalstrike}{x*y}\\\end{array}</script>]]></content>
<summary type="html">
<h2 id="1、word2vec介绍"><a href="#1、word2vec介绍" class="headerlink" title="1、word2vec介绍"></a>1、word2vec介绍</h2><p>word2vec 是 Google 于 2013 年开源推出的一个用于获取 word vector (词向量)的工具包。<br>特点:简单、高效<br>作用:把文本转化为词向量<br>
</summary>
<category term="机器学习" scheme="http://blog.feifan.news/categories/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0/"/>
<category term="Word2Vec" scheme="http://blog.feifan.news/tags/Word2Vec/"/>
</entry>
<entry>
<title>隐马尔可夫模型</title>
<link href="http://blog.feifan.news/2018/08/30/hmm-1/"/>
<id>http://blog.feifan.news/2018/08/30/hmm-1/</id>
<published>2018-08-30T01:45:06.000Z</published>
<updated>2019-05-06T15:38:02.761Z</updated>
<content type="html"><![CDATA[<p>隐马尔可夫模型(Hidden Markov Model,HMM)是统计模型,</p><h2 id="1、HMM原理"><a href="#1、HMM原理" class="headerlink" title="1、HMM原理"></a>1、HMM原理</h2><p>ab是apachebench的缩写<br>ab命令会创建多个并发访问线程,对同一个URL访问来测试apache的负载压力。测试目标是URL。、Lighthttp、Tomcat、IIS等其它服务器</p><a id="more"></a>]]></content>
<summary type="html">
<p>隐马尔可夫模型(Hidden Markov Model,HMM)是统计模型,</p>
<h2 id="1、HMM原理"><a href="#1、HMM原理" class="headerlink" title="1、HMM原理"></a>1、HMM原理</h2><p>ab是apachebench的缩写<br>ab命令会创建多个并发访问线程,对同一个URL访问来测试apache的负载压力。测试目标是URL。、Lighthttp、Tomcat、IIS等其它服务器</p>
</summary>
<category term="算法" scheme="http://blog.feifan.news/categories/%E7%AE%97%E6%B3%95/"/>
<category term="HMM" scheme="http://blog.feifan.news/tags/HMM/"/>
</entry>
<entry>
<title>在 hexo 中支持 Mathjax</title>
<link href="http://blog.feifan.news/2018/08/30/mathjax/"/>
<id>http://blog.feifan.news/2018/08/30/mathjax/</id>
<published>2018-08-29T17:57:54.000Z</published>
<updated>2019-05-06T15:38:02.758Z</updated>
<content type="html"><![CDATA[<h2 id="第一步-使用Kramed代替-Marked"><a href="#第一步-使用Kramed代替-Marked" class="headerlink" title="第一步 使用Kramed代替 Marked"></a>第一步 使用Kramed代替 Marked</h2><p><code>hexo</code> 默认的渲染引擎是 marked,但是 <code>marked</code> 不支持 <code>mathjax</code>。 <code>kramed</code> 是在 <code>marked</code> 的基础上进行修改。我们在工程目录下执行以下命令来安装 <code>kramed</code>.<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">npm uninstall hexo-renderer-marked --save</span><br><span class="line">npm install hexo-renderer-kramed --save</span><br></pre></td></tr></table></figure></p><p>然后,更改/node_modules/hexo-renderer-kramed/lib/renderer.js,更改:<br><a id="more"></a><br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line">// Change inline math rule</span><br><span class="line">function formatText(text) {</span><br><span class="line"> // Fit kramed's rule: $$ + \1 + $$</span><br><span class="line"> return text.replace(/`\$(.*?)\$`/g, '$$$$$1$$$$');</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><p>为:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">// Change inline math rule</span><br><span class="line">function formatText(text) {</span><br><span class="line"> return text;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><h2 id="第二步-停止使用-hexo-math"><a href="#第二步-停止使用-hexo-math" class="headerlink" title="第二步: 停止使用 hexo-math"></a>第二步: 停止使用 hexo-math</h2><p>首先,如果你已经安装 hexo-math, 请卸载它:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm uninstall hexo-math --save</span><br></pre></td></tr></table></figure></p><p>然后安装 hexo-renderer-mathjax 包:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install hexo-renderer-mathjax --save</span><br></pre></td></tr></table></figure></p><h2 id="第三步-更新-Mathjax-的-CDN-链接"><a href="#第三步-更新-Mathjax-的-CDN-链接" class="headerlink" title="第三步: 更新 Mathjax 的 CDN 链接"></a>第三步: 更新 Mathjax 的 CDN 链接</h2><p>首先,打开/node_modules/hexo-renderer-mathjax/mathjax.html<br>然后,把<code><script></code>更改为:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-MML-AM_CHTML"></script></span><br></pre></td></tr></table></figure></p><h2 id="第四步-更改默认转义规则"><a href="#第四步-更改默认转义规则" class="headerlink" title="第四步: 更改默认转义规则"></a>第四步: 更改默认转义规则</h2><p>因为 hexo 默认的转义规则会将一些字符进行转义,比如 _ 转为 <em>, 所以我们需要对默认的规则进行修改.<br>首先, 打开 node_modules\kramed\lib\rules\inline.js<br>把<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">escape: /^\\([\\`*{}\[\]()#$+\-.!_>])/,</span><br></pre></td></tr></table></figure></em></p><p>更改为:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">escape: /^\\([`*\[\]()# +\-.!_>])/,</span><br></pre></td></tr></table></figure></p><p>把<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">em: /^\b_((?:__|[\s\S])+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,</span><br></pre></td></tr></table></figure></p><p>更改为:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">em: /^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,</span><br></pre></td></tr></table></figure></p><h2 id="第五步-开启mathjax"><a href="#第五步-开启mathjax" class="headerlink" title="第五步: 开启mathjax"></a>第五步: 开启mathjax</h2><p>在主题 <code>_config.yml</code> 中开启 <code>Mathjax</code>, 找到 <code>mathjax</code> 字段添加如下代码:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">mathjax:</span><br><span class="line"> enable: true</span><br></pre></td></tr></table></figure></p><p>这一步可选,在博客中开启 Mathjax,, 添加以下内容:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line">---</span><br><span class="line">title: Testing Mathjax with Hexo</span><br><span class="line">category: Uncategorized</span><br><span class="line">date: 2017/05/03</span><br><span class="line">mathjax: true</span><br><span class="line">---</span><br></pre></td></tr></table></figure></p><p>重新启动hexo(先clean再generate)<br>通过以上步骤,我们就可以在 hexo 中使用 Mathjax 来书写数学公式。</p>]]></content>
<summary type="html">
<h2 id="第一步-使用Kramed代替-Marked"><a href="#第一步-使用Kramed代替-Marked" class="headerlink" title="第一步 使用Kramed代替 Marked"></a>第一步 使用Kramed代替 Marked</h2><p><code>hexo</code> 默认的渲染引擎是 marked,但是 <code>marked</code> 不支持 <code>mathjax</code>。 <code>kramed</code> 是在 <code>marked</code> 的基础上进行修改。我们在工程目录下执行以下命令来安装 <code>kramed</code>.<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">npm uninstall hexo-renderer-marked --save</span><br><span class="line">npm install hexo-renderer-kramed --save</span><br></pre></td></tr></table></figure></p>
<p>然后,更改/node_modules/hexo-renderer-kramed/lib/renderer.js,更改:<br>
</summary>
<category term="hexo" scheme="http://blog.feifan.news/categories/hexo/"/>
<category term="Hexo" scheme="http://blog.feifan.news/tags/Hexo/"/>
</entry>
<entry>
<title>python2.7学习总结</title>
<link href="http://blog.feifan.news/2017/05/03/python/"/>
<id>http://blog.feifan.news/2017/05/03/python/</id>
<published>2017-05-03T02:12:32.000Z</published>
<updated>2019-05-06T15:38:02.749Z</updated>
<content type="html"><![CDATA[<h2 id="Python基础"><a href="#Python基础" class="headerlink" title="Python基础"></a>Python基础</h2><h4 id="列表(list)"><a href="#列表(list)" class="headerlink" title=" 列表(list) "></a><strong> 列表(list) </strong></h4><ul><li>列表的截取。<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>list = [<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>];</span><br><span class="line"><span class="meta">>>> </span>list[<span class="number">0</span>]</span><br><span class="line"><span class="number">1</span></span><br><span class="line"><span class="meta">>>> </span>list[<span class="number">-1</span>]</span><br><span class="line"><span class="number">5</span></span><br><span class="line"><span class="meta">>>> </span>list[<span class="number">3</span>:<span class="number">100</span>]</span><br><span class="line">[<span class="number">4</span>, <span class="number">5</span>]</span><br></pre></td></tr></table></figure></li></ul><a id="more"></a><ul><li><p>列表的重复。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>list * <span class="number">3</span></span><br><span class="line">[<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>, <span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>, <span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>]</span><br></pre></td></tr></table></figure></li><li><p>列表的组合</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>list = [<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>]</span><br><span class="line"><span class="meta">>>> </span>list2 = [<span class="string">'a'</span>,<span class="string">'b'</span>,<span class="string">'c'</span>,<span class="string">'d'</span>,<span class="string">'e'</span>]</span><br><span class="line"><span class="meta">>>> </span>list+list2</span><br><span class="line">[<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>, <span class="string">'a'</span>, <span class="string">'b'</span>, <span class="string">'c'</span>, <span class="string">'d'</span>, <span class="string">'e'</span>]</span><br></pre></td></tr></table></figure></li></ul><ul><li><p>获取列表长度</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span><span class="keyword">print</span> len(list)</span><br><span class="line"><span class="number">5</span></span><br></pre></td></tr></table></figure></li><li><p>在列表末尾添加新的元素(append、extend、insert)</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>list.append(<span class="string">'append'</span>)</span><br><span class="line"><span class="meta">>>> </span>list</span><br><span class="line">[<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>, <span class="string">'append'</span>]</span><br></pre></td></tr></table></figure><p> 在列表末尾追加另一个列表</p> <figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>list.extend(list2)</span><br><span class="line"><span class="meta">>>> </span>list</span><br><span class="line">[<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>, <span class="string">'append'</span>, <span class="string">'a'</span>, <span class="string">'b'</span>, <span class="string">'c'</span>, <span class="string">'d'</span>, <span class="string">'e'</span>]</span><br></pre></td></tr></table></figure><p> 在指定位置添加元素</p> <figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>list.insert(<span class="number">0</span>,<span class="number">10</span>)</span><br><span class="line"><span class="meta">>>> </span>list</span><br><span class="line">[<span class="number">10</span>, <span class="number">9</span>, <span class="number">8</span>, <span class="number">7</span>, <span class="number">6</span>, <span class="number">5</span>, <span class="number">4</span>, <span class="number">3</span>, <span class="number">2</span>, <span class="number">1</span>, <span class="number">0</span>]</span><br></pre></td></tr></table></figure></li></ul><ul><li><p>删除列表元素(del命令、pop()、remove())</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span><span class="keyword">del</span> list[<span class="number">-1</span>]</span><br><span class="line"><span class="meta">>>> </span>list</span><br><span class="line">[<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>, <span class="string">'append'</span>, <span class="string">'a'</span>, <span class="string">'b'</span>, <span class="string">'c'</span>, <span class="string">'d'</span>]</span><br></pre></td></tr></table></figure><p> pop移除列表中的某个元素(默认最后一个),并返回改元素的值</p> <figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>list</span><br><span class="line">[<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>, <span class="string">'append'</span>, <span class="string">'a'</span>, <span class="string">'b'</span>, <span class="string">'c'</span>, <span class="string">'d'</span>]</span><br><span class="line"><span class="meta">>>> </span>list.pop()</span><br><span class="line"><span class="string">'d'</span></span><br><span class="line"><span class="meta">>>> </span>list</span><br><span class="line">[<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>, <span class="string">'append'</span>, <span class="string">'a'</span>, <span class="string">'b'</span>, <span class="string">'c'</span>]</span><br><span class="line"><span class="meta">>>> </span>list.pop(<span class="number">0</span>)</span><br><span class="line"><span class="number">1</span></span><br><span class="line"><span class="meta">>>> </span>list</span><br><span class="line">[<span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>, <span class="string">'append'</span>, <span class="string">'a'</span>, <span class="string">'b'</span>, <span class="string">'c'</span>]</span><br></pre></td></tr></table></figure></li><li><p>更新列表,<span style="color:red">更新一个列表中不存在的键时,会报错。</span></p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>list</span><br><span class="line">[<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>]</span><br><span class="line"><span class="meta">>>> </span>list[<span class="number">4</span>]=<span class="string">'new'</span></span><br><span class="line"><span class="meta">>>> </span>list</span><br><span class="line">[<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="string">'new'</span>]</span><br><span class="line"><span class="meta">>>> </span>list[<span class="number">10</span>]=<span class="string">'new10'</span></span><br><span class="line">Traceback (most recent call last):</span><br><span class="line"> File <span class="string">"<interactive input>"</span>, line <span class="number">1</span>, <span class="keyword">in</span> <module></span><br><span class="line">IndexError: list assignment index out of range</span><br></pre></td></tr></table></figure></li><li><p>元素是否存在列表中(in、count、index)</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>list</span><br><span class="line">[<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>, <span class="string">'append'</span>, <span class="string">'a'</span>, <span class="string">'b'</span>, <span class="string">'c'</span>, <span class="string">'d'</span>]</span><br><span class="line"><span class="meta">>>> </span><span class="string">'append'</span> <span class="keyword">in</span> list</span><br><span class="line"><span class="keyword">True</span></span><br><span class="line"><span class="meta">>>> </span><span class="string">'hello'</span> <span class="keyword">in</span> list</span><br><span class="line"><span class="keyword">False</span></span><br></pre></td></tr></table></figure> <figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>list</span><br><span class="line">[<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>, <span class="string">'append'</span>, <span class="string">'a'</span>, <span class="string">'b'</span>, <span class="string">'c'</span>, <span class="string">'d'</span>]</span><br><span class="line"><span class="meta">>>> </span>list.count(<span class="string">'count'</span>)</span><br><span class="line"><span class="number">0</span></span><br><span class="line"><span class="meta">>>> </span>list.count(<span class="string">'append'</span>)</span><br><span class="line"><span class="number">1</span></span><br></pre></td></tr></table></figure> <figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>list.index(<span class="string">'append'</span>)</span><br><span class="line"><span class="number">5</span></span><br><span class="line"><span class="meta">>>> </span>list.index(<span class="string">'index'</span>)</span><br><span class="line">Traceback (most recent call last):</span><br><span class="line"> File <span class="string">"<interactive input>"</span>, line <span class="number">1</span>, <span class="keyword">in</span> <module></span><br><span class="line">ValueError: <span class="string">'index'</span> <span class="keyword">is</span> <span class="keyword">not</span> <span class="keyword">in</span> list</span><br></pre></td></tr></table></figure></li><li><p>列表迭代</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>list</span><br><span class="line">[<span class="number">2</span>, <span class="number">3</span>, <span class="number">5</span>, <span class="string">'append'</span>, <span class="string">'a'</span>, <span class="string">'b'</span>, <span class="string">'c'</span>, <span class="string">'d'</span>]</span><br><span class="line"><span class="meta">>>> </span><span class="keyword">for</span> i <span class="keyword">in</span> list:</span><br><span class="line"><span class="meta">... </span><span class="keyword">print</span> i</span><br><span class="line"><span class="meta">... </span></span><br><span class="line"><span class="number">2</span></span><br><span class="line"><span class="number">3</span></span><br><span class="line"><span class="number">5</span></span><br><span class="line">append</span><br><span class="line">a</span><br><span class="line">b</span><br><span class="line">c</span><br><span class="line">d</span><br></pre></td></tr></table></figure></li><li><p>反向列表中的元素</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>list</span><br><span class="line">[<span class="number">2</span>, <span class="number">3</span>, <span class="number">5</span>, <span class="string">'append'</span>, <span class="string">'a'</span>, <span class="string">'b'</span>, <span class="string">'c'</span>, <span class="string">'d'</span>]</span><br><span class="line"><span class="meta">>>> </span>list.reverse()</span><br><span class="line"><span class="meta">>>> </span>list</span><br><span class="line">[<span class="string">'d'</span>, <span class="string">'c'</span>, <span class="string">'b'</span>, <span class="string">'a'</span>, <span class="string">'append'</span>, <span class="number">5</span>, <span class="number">3</span>, <span class="number">2</span>]</span><br></pre></td></tr></table></figure></li><li><p>对列表进行排序</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>list = [<span class="number">1</span>,<span class="number">9</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">6</span>,<span class="number">2</span>,<span class="number">5</span>,<span class="number">8</span>,<span class="number">7</span>,<span class="number">0</span>]</span><br><span class="line"><span class="meta">>>> </span>list.sort()</span><br><span class="line"><span class="meta">>>> </span>list</span><br><span class="line">[<span class="number">0</span>, <span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>, <span class="number">6</span>, <span class="number">7</span>, <span class="number">8</span>, <span class="number">9</span>]</span><br><span class="line"><span class="meta">>>> </span>list.reverse()</span><br><span class="line"><span class="meta">>>> </span>list</span><br><span class="line">[<span class="number">9</span>, <span class="number">8</span>, <span class="number">7</span>, <span class="number">6</span>, <span class="number">5</span>, <span class="number">4</span>, <span class="number">3</span>, <span class="number">2</span>, <span class="number">1</span>, <span class="number">0</span>]</span><br></pre></td></tr></table></figure></li><li><p>列表最值</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>list</span><br><span class="line">[<span class="number">10</span>, <span class="number">9</span>, <span class="number">8</span>, <span class="number">7</span>, <span class="number">6</span>, <span class="number">5</span>, <span class="number">4</span>, <span class="number">3</span>, <span class="number">2</span>, <span class="number">1</span>, <span class="number">0</span>]</span><br><span class="line"><span class="meta">>>> </span>max(list)</span><br><span class="line"><span class="number">10</span></span><br><span class="line"><span class="meta">>>> </span>min(list)</span><br><span class="line"><span class="number">0</span></span><br></pre></td></tr></table></figure></li></ul><h4 id="元组(tuple)"><a href="#元组(tuple)" class="headerlink" title=" 元组(tuple)"></a><strong> 元组(tuple)</strong></h4><ul><li>元组和列表基本相同,只是<span style="color:red">元组中的元素不能修改</span></li></ul><div class="table-container"><table><thead><tr><th style="text-align:left">list</th><th style="text-align:left">tuple</th></tr></thead><tbody><tr><td style="text-align:left">可以修改</td><td style="text-align:left">不可以修改</td></tr></tbody></table></div><ul><li><p>元组和列表的相互转换<br>列表转为元组</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>_list = [<span class="number">10</span>, <span class="number">9</span>, <span class="number">8</span>, <span class="number">7</span>, <span class="number">6</span>, <span class="number">5</span>, <span class="number">4</span>, <span class="number">3</span>, <span class="number">2</span>, <span class="number">1</span>, <span class="number">0</span>]</span><br><span class="line"><span class="meta">>>> </span>_tuple = tuple(_list)</span><br><span class="line"><span class="meta">>>> </span>_tuple</span><br><span class="line">(<span class="number">10</span>, <span class="number">9</span>, <span class="number">8</span>, <span class="number">7</span>, <span class="number">6</span>, <span class="number">5</span>, <span class="number">4</span>, <span class="number">3</span>, <span class="number">2</span>, <span class="number">1</span>, <span class="number">0</span>)</span><br></pre></td></tr></table></figure><p> 元组转为列表</p> <figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>t_list = list(_tuple)</span><br><span class="line"><span class="meta">>>> </span>t_list</span><br><span class="line">[<span class="number">10</span>, <span class="number">9</span>, <span class="number">8</span>, <span class="number">7</span>, <span class="number">6</span>, <span class="number">5</span>, <span class="number">4</span>, <span class="number">3</span>, <span class="number">2</span>, <span class="number">1</span>, <span class="number">0</span>]</span><br></pre></td></tr></table></figure></li><li><p>无关闭分隔符<br>任意无符号的对象,以逗号隔开,默认是元组</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>_tuple_ = <span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span></span><br><span class="line"><span class="meta">>>> </span>_tuple_</span><br><span class="line">(<span class="number">1</span>, <span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>)</span><br></pre></td></tr></table></figure></li><li><p>修改元组的方法</p><ul><li>通过元组连接</li><li>通过内嵌列表的形式</li></ul></li><li>一个元素的元组</li></ul><div class="table-container"><table><thead><tr><th style="text-align:left">错误形式</th><th style="text-align:left">正确格式</th></tr></thead><tbody><tr><td style="text-align:left">>>> _tuple = (1)<br>>>> _tuple<br>1</td><td style="text-align:left">>>> _tuple = (1,)<br>>>> _tuple<br>(1,)</td></tr></tbody></table></div><h4 id="字典(dictionary)"><a href="#字典(dictionary)" class="headerlink" title="字典(dictionary)"></a>字典(dictionary)</h4><p>也可称为map,以键值(key=>value)形式存在的可变容器</p><ul><li>字典键的特性:<ul><li>键不能相同,否则后者会覆盖前者</li><li>键必须不可变,可以用数字、字符串、元组,但不能用列表可变的对象。</li></ul></li><li><p>用字符串输出字典</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>_info = {<span class="string">'name'</span>:<span class="string">'liushuaicai'</span>,<span class="string">'age'</span>:<span class="string">'25'</span>}</span><br><span class="line"><span class="meta">>>> </span>str(_info)</span><br><span class="line"><span class="string">"{'age': '25', 'name': 'liushuaicai'}"</span></span><br></pre></td></tr></table></figure></li><li><p>查看变量的类型</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>type(_info)</span><br><span class="line"><type <span class="string">'dict'</span>></span><br><span class="line"><span class="meta">>>> </span>type(_tuple)</span><br><span class="line"><type <span class="string">'tuple'</span>></span><br><span class="line"><span class="meta">>>> </span>type(_list)</span><br><span class="line"><type <span class="string">'list'</span>></span><br></pre></td></tr></table></figure></li><li><p>创建一个字典,以序列中的值作为键,val作为值</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>dict.fromkeys(_list1,_val)</span><br><span class="line">{<span class="number">1</span>: <span class="string">'hello'</span>, <span class="number">2</span>: <span class="string">'hello'</span>, <span class="number">3</span>: <span class="string">'hello'</span>, <span class="number">4</span>: <span class="string">'hello'</span>, <span class="number">5</span>: <span class="string">'hello'</span>}</span><br></pre></td></tr></table></figure></li><li><p>浅复制字典</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>_info</span><br><span class="line">{<span class="string">'age'</span>: <span class="string">'25'</span>, <span class="string">'name'</span>: <span class="string">'liushuaicai'</span>}</span><br><span class="line"><span class="meta">>>> </span>c_info = _info.copy()</span><br><span class="line"><span class="meta">>>> </span>c_info</span><br><span class="line">{<span class="string">'age'</span>: <span class="string">'25'</span>, <span class="string">'name'</span>: <span class="string">'liushuaicai'</span>}</span><br></pre></td></tr></table></figure></li><li><p>获取字典中的值,如果不存在,返回默认值</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>_info.get(<span class="string">'name'</span>)</span><br><span class="line"><span class="string">'liushuaicai'</span></span><br><span class="line"><span class="meta">>>> </span>_info.get(<span class="string">'adress'</span>,<span class="string">'北京'</span>)</span><br><span class="line"><span class="string">'\xe5\x8c\x97\xe4\xba\xac'</span></span><br></pre></td></tr></table></figure></li><li><p>设置字典的键,如果不存在,则为默认值,如果存在,也不改变其值</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>_info.setdefault(<span class="string">'sex'</span>)</span><br><span class="line"><span class="meta">>>> </span>_info</span><br><span class="line">{<span class="string">'age'</span>: <span class="string">'25'</span>, <span class="string">'name'</span>: <span class="string">'liushuaicai'</span>, <span class="string">'sex'</span>: <span class="keyword">None</span>}</span><br><span class="line"><span class="meta">>>> </span>_info.setdefault(<span class="string">'sex'</span>,<span class="string">'man'</span>)</span><br><span class="line"><span class="meta">>>> </span>_info</span><br><span class="line">{<span class="string">'age'</span>: <span class="string">'25'</span>, <span class="string">'name'</span>: <span class="string">'liushuaicai'</span>, <span class="string">'sex'</span>: <span class="keyword">None</span>}</span><br><span class="line"><span class="meta">>>> </span>_info.setdefault(<span class="string">'phone'</span>,<span class="string">'15201557941'</span>)</span><br><span class="line"><span class="string">'15201557941'</span></span><br><span class="line"><span class="meta">>>> </span>_info</span><br><span class="line">{<span class="string">'phone'</span>: <span class="string">'15201557941'</span>, <span class="string">'age'</span>: <span class="string">'25'</span>, <span class="string">'name'</span>: <span class="string">'liushuaicai'</span>, <span class="string">'sex'</span>: <span class="keyword">None</span>}</span><br></pre></td></tr></table></figure></li><li><p>把一个字典的键值更新到另一个字典</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>_email = {<span class="string">'email'</span>:<span class="string">'[email protected]'</span>}</span><br><span class="line"><span class="meta">>>> </span>_info.update(_email)</span><br><span class="line"><span class="meta">>>> </span>_info</span><br><span class="line">{<span class="string">'phone'</span>: <span class="string">'15201557941'</span>, <span class="string">'age'</span>: <span class="string">'25'</span>, <span class="string">'email'</span>: <span class="string">'[email protected]'</span>, <span class="string">'name'</span>: <span class="string">'liushuaicai'</span>, <span class="string">'sex'</span>: <span class="keyword">None</span>}</span><br></pre></td></tr></table></figure></li><li><p>以列表返回可遍历的元组(数组)</p><figure class="highlight"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>_list = _info.items()</span><br><span class="line"><span class="meta">>>> </span>_list</span><br><span class="line">[(<span class="string">'phone'</span>, <span class="string">'15201557941'</span>), (<span class="string">'age'</span>, <span class="string">'25'</span>), (<span class="string">'email'</span>, <span class="string">'[email protected]'</span>), (<span class="string">'name'</span>, <span class="string">'liushuaicai'</span>)]</span><br><span class="line"><span class="meta">>>> </span><span class="keyword">for</span> key,value <span class="keyword">in</span> _list:</span><br><span class="line"><span class="meta">... </span><span class="keyword">print</span> key,<span class="string">'=>'</span>,value</span><br><span class="line"><span class="meta">... </span></span><br><span class="line">phone => 15201557941</span><br><span class="line">age => 25</span><br><span class="line">email => [email protected]</span><br><span class="line">name => liushuaicai</span><br></pre></td></tr></table></figure></li><li><p>获取字典中所有的键|值</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>_info.keys()</span><br><span class="line">[<span class="string">'phone'</span>, <span class="string">'age'</span>, <span class="string">'email'</span>, <span class="string">'name'</span>]</span><br><span class="line"><span class="meta">>>> </span>_info.values()</span><br><span class="line">[<span class="string">'15201557941'</span>, <span class="string">'25'</span>, <span class="string">'[email protected]'</span>, <span class="string">'liushuaicai'</span>]</span><br></pre></td></tr></table></figure></li><li><p>判断字典中是否含有某个键</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>_info.has_key(<span class="string">'name'</span>)</span><br><span class="line"><span class="keyword">True</span></span><br><span class="line"><span class="meta">>>> </span>_info.has_key(<span class="string">'height'</span>)</span><br><span class="line"><span class="keyword">False</span></span><br></pre></td></tr></table></figure></li><li><p>删除字典中的值(del命令、pop())</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span><span class="keyword">del</span> _info[<span class="string">'sex'</span>]</span><br><span class="line"><span class="meta">>>> </span>_info</span><br><span class="line">{<span class="string">'phone'</span>: <span class="string">'15201557941'</span>, <span class="string">'age'</span>: <span class="string">'25'</span>, <span class="string">'email'</span>: <span class="string">'[email protected]'</span>, <span class="string">'name'</span>: <span class="string">'liushuaicai'</span>}</span><br></pre></td></tr></table></figure> <figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>_info</span><br><span class="line">{<span class="string">'age'</span>: <span class="number">25</span>, <span class="string">'name'</span>: <span class="string">'liushuaicai'</span>, <span class="string">'sex'</span>: <span class="string">'man'</span>}</span><br><span class="line"><span class="meta">>>> </span>_info.pop(<span class="string">'sex'</span>)</span><br><span class="line"><span class="string">'man'</span></span><br><span class="line"><span class="meta">>>> </span>_info</span><br><span class="line">{<span class="string">'age'</span>: <span class="number">25</span>, <span class="string">'name'</span>: <span class="string">'liushuaicai'</span>}</span><br></pre></td></tr></table></figure></li><li><p>删除字典中的所有元素</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>_info.clear()</span><br><span class="line"><span class="meta">>>> </span>_info</span><br><span class="line">{}</span><br></pre></td></tr></table></figure></li></ul><h4 id="set序列"><a href="#set序列" class="headerlink" title="set序列"></a>set序列</h4><p>set和dict类似,也是一组key的集合,但不存储value。由于key不能重复,所以,在set中,没有重复的key,不能有空值。</p><pre><code>>>> _set = set([1,1,2,2,3,4,5,7,7])>>> _setset([1, 2, 3, 4, 5, 7])</code></pre><ul><li><p>set添加元素</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>_set</span><br><span class="line">set([<span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>, <span class="number">7</span>])</span><br><span class="line"><span class="meta">>>> </span>_set.add(<span class="string">'new'</span>)</span><br><span class="line"><span class="meta">>>> </span>_set</span><br><span class="line">set([<span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>, <span class="number">7</span>, <span class="string">'new'</span>])</span><br></pre></td></tr></table></figure></li><li><p>删除元素(pop、remove)</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>_set.remove(<span class="string">'new'</span>)</span><br><span class="line"><span class="meta">>>> </span>_set</span><br><span class="line">set([<span class="number">2</span>, <span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>, <span class="number">7</span>])</span><br></pre></td></tr></table></figure> <figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>_set.pop()</span><br><span class="line"><span class="number">2</span></span><br><span class="line"><span class="meta">>>> </span>_set</span><br><span class="line">set([<span class="number">3</span>, <span class="number">4</span>, <span class="number">5</span>, <span class="number">7</span>])</span><br></pre></td></tr></table></figure></li><li><p>字符串是不可变对象,用replace替换值时,相当于赋给了另外一个变量。</p><figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">>>> </span>_name = <span class="string">'liushuaicai'</span></span><br><span class="line"><span class="meta">>>> </span>_name.replace(<span class="string">'l'</span>,<span class="string">'L'</span>)</span><br><span class="line"><span class="string">'Liushuaicai'</span></span><br></pre></td></tr></table></figure></li></ul>]]></content>
<summary type="html">
<h2 id="Python基础"><a href="#Python基础" class="headerlink" title="Python基础"></a>Python基础</h2><h4 id="列表(list)"><a href="#列表(list)" class="headerlink" title=" 列表(list) "></a><strong> 列表(list) </strong></h4><ul>
<li>列表的截取。<figure class="highlight python"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta">&gt;&gt;&gt; </span>list = [<span class="number">1</span>,<span class="number">2</span>,<span class="number">3</span>,<span class="number">4</span>,<span class="number">5</span>];</span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span>list[<span class="number">0</span>]</span><br><span class="line"><span class="number">1</span></span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span>list[<span class="number">-1</span>]</span><br><span class="line"><span class="number">5</span></span><br><span class="line"><span class="meta">&gt;&gt;&gt; </span>list[<span class="number">3</span>:<span class="number">100</span>]</span><br><span class="line">[<span class="number">4</span>, <span class="number">5</span>]</span><br></pre></td></tr></table></figure>
</li>
</ul>
</summary>
<category term="Python" scheme="http://blog.feifan.news/categories/Python/"/>
<category term="python" scheme="http://blog.feifan.news/tags/python/"/>
</entry>
<entry>
<title>PHP进程管理pcntl</title>
<link href="http://blog.feifan.news/2017/04/24/pcntl/"/>
<id>http://blog.feifan.news/2017/04/24/pcntl/</id>
<published>2017-04-24T09:01:33.000Z</published>
<updated>2019-05-06T15:38:02.752Z</updated>
<content type="html"><![CDATA[<p>其实很早就想学习一下多进程、多线程,一直赖宇自己没用到这个东西,没认真去看过,这次有时间研究一下(了解了解-_-),PHP的扩展安装想必大家都已经很熟悉了,这里就不在叙述了。如果真不知道,可以参考我的另一篇博客<a href="http://www.cnblogs.com/sweet521/p/6062859.html" target="_blank" rel="noopener">刘帅才的博客园</a>。<br>下面一块来学习一下吧(我也不会…_-_)。</p><h2 id="Pcntl函数"><a href="#Pcntl函数" class="headerlink" title="Pcntl函数"></a>Pcntl函数</h2><h4 id="pcntl-alarm"><a href="#pcntl-alarm" class="headerlink" title="pcntl_alarm"></a>pcntl_alarm</h4><ul><li>int pcntl_alarm(int $seconds):为进程设置一个alarm闹钟信号</li><li>参数$seconds:等待的秒数,为0的话不会创建信号</li><li>返回值:返回上次调用剩余的秒数</li></ul>]]></content>
<summary type="html">
<p>其实很早就想学习一下多进程、多线程,一直赖宇自己没用到这个东西,没认真去看过,这次有时间研究一下(了解了解-_-),PHP的扩展安装想必大家都已经很熟悉了,这里就不在叙述了。如果真不知道,可以参考我的另一篇博客<a href="http://www.cnblogs.com/
</summary>
<category term="PHP" scheme="http://blog.feifan.news/categories/PHP/"/>
<category term="pcntl" scheme="http://blog.feifan.news/tags/pcntl/"/>
</entry>
<entry>
<title>git 知识总结</title>
<link href="http://blog.feifan.news/2017/04/24/git/"/>
<id>http://blog.feifan.news/2017/04/24/git/</id>
<published>2017-04-24T01:32:11.000Z</published>
<updated>2019-12-17T05:41:18.585Z</updated>
<content type="html"><![CDATA[<h2 id="Git-一般使用步骤"><a href="#Git-一般使用步骤" class="headerlink" title="Git 一般使用步骤"></a>Git 一般使用步骤</h2><h2 id="1、What-is-git"><a href="#1、What-is-git" class="headerlink" title="1、What is git"></a>1、What is git</h2><p>git是一个分布式的版本控制系统。<br><a id="more"></a></p><h2 id="2、Git与SVN的区别"><a href="#2、Git与SVN的区别" class="headerlink" title="2、Git与SVN的区别"></a>2、Git与SVN的区别</h2><div class="table-container"><table><thead><tr><th style="text-align:left">Number</th><th style="text-align:left">Git</th><th style="text-align:left">SVN</th></tr></thead><tbody><tr><td style="text-align:left">1</td><td style="text-align:left">分布式</td><td style="text-align:left">集中式</td></tr><tr><td style="text-align:left">2</td><td style="text-align:left">元数据存储</td><td style="text-align:left">文件存储</td></tr><tr><td style="text-align:left">3</td><td style="text-align:left">本地服务器</td><td style="text-align:left">中央服务器</td></tr><tr><td style="text-align:left">4</td><td style="text-align:left">可以不联网</td><td style="text-align:left">必须要有网络</td></tr></tbody></table></div><h2 id="3、Git命令"><a href="#3、Git命令" class="headerlink" title="3、Git命令"></a>3、Git命令</h2><h4 id="3-1、git基本步骤"><a href="#3-1、git基本步骤" class="headerlink" title="3.1、git基本步骤"></a>3.1、git基本步骤</h4><pre><code>1、创建本地仓库git init <filename>2、检出仓库git clone <path>3、把文件添加到缓存区git add .|git add <filename>4、提交文件到本地仓库git commit -m '修改注释'5、把文件推送到远程仓库git push</code></pre><h4 id="3-2、git常用命令"><a href="#3-2、git常用命令" class="headerlink" title="3.2、git常用命令"></a>3.2、git常用命令</h4><div class="table-container"><table><thead><tr><th style="text-align:left">命令</th><th style="text-align:left">说明</th></tr></thead><tbody><tr><td style="text-align:left">git status</td><td style="text-align:left">查看修改状态<br>参数-s以简短形式输出结果</td></tr><tr><td style="text-align:left">git push</td><td style="text-align:left">把文件推送到远程仓库<br>将本地的master分支推送到origin主机的master分支。如果后者不存在,则会被新建:git push origin master<br>如果当前分支只有一个追踪分支,那么主机名都可以省略:git push</td></tr><tr><td style="text-align:left">git pull</td><td style="text-align:left">取回远程主机某个分支的更新,再与本地的指定分支合并<br>取回origin主机的next分支,与本地的master分支合并:git pull origin next:master<br>如果远程分支是与当前分支合并,则冒号后面的部分可以省略:git pull origin next<br>等同于先做git fetch origin,再做git merge origin/next<br>如果当前分支与远程分支存在追踪关系,git pull就可以省略远程分支名:git pull origin<br>如果当前分支只有一个追踪分支,连远程主机名都可以省略:git pull</td></tr><tr><td style="text-align:left">git diff</td><td style="text-align:left">查看执行 git status 的结果的详细信息<br><em> 尚未缓存的改动:git diff<br></em> 查看已缓存的改动: git diff —cached<br><em> 查看已缓存的与未缓存的所有改动:git diff HEAD<br></em> 显示摘要而非整个 diff:git diff —stat</td></tr><tr><td style="text-align:left">git config</td><td style="text-align:left">配置用户名和邮箱地址<br>git config —global user.name ‘runoob’<br>git config —global user.email [email protected]</td></tr><tr><td style="text-align:left">git reset HEAD</td><td style="text-align:left">取消已经缓存的内容<br>git reset HEAD —change.php</td></tr><tr><td style="text-align:left">git rm</td><td style="text-align:left">从缓存区删除文件<br>将文件从缓存区和你的硬盘中(工作目录)删除:git rm file<br>只删除缓存区的文件:git rm —cached</td></tr><tr><td style="text-align:left">git mv</td><td style="text-align:left">重命名磁盘文件</td></tr><tr><td style="text-align:left">git branch</td><td style="text-align:left">分支管理:<a href="http://www.runoob.com/git/git-branch.html" target="_blank" rel="noopener">http://www.runoob.com/git/git-branch.html</a></td></tr></tbody></table></div><p>_参考教程_</p><ul><li><a href="http://www.yiibai.com/git" target="_blank" rel="noopener">http://www.yiibai.com/git</a></li><li><a href="http://www.runoob.com/git" target="_blank" rel="noopener">http://www.runoob.com/git</a></li><li><a href="http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000" target="_blank" rel="noopener">廖雪峰的官方网站</a></li><li><a href="http://www.bootcss.com/p/git-guide/" target="_blank" rel="noopener">http://www.bootcss.com/p/git-guide/</a></li></ul>]]></content>
<summary type="html">
<h2 id="Git-一般使用步骤"><a href="#Git-一般使用步骤" class="headerlink" title="Git 一般使用步骤"></a>Git 一般使用步骤</h2><h2 id="1、What-is-git"><a href="#1、What-is-git" class="headerlink" title="1、What is git"></a>1、What is git</h2><p>git是一个分布式的版本控制系统。<br>
</summary>
<category term="PHP" scheme="http://blog.feifan.news/categories/PHP/"/>
<category term="git" scheme="http://blog.feifan.news/tags/git/"/>
</entry>
<entry>
<title>Memcached的工作原理及内存分配</title>
<link href="http://blog.feifan.news/2017/04/20/memcached/"/>
<id>http://blog.feifan.news/2017/04/20/memcached/</id>
<published>2017-04-20T06:41:21.000Z</published>
<updated>2019-05-06T15:38:02.757Z</updated>
<content type="html"><![CDATA[<h2 id="1、Memcached的原理"><a href="#1、Memcached的原理" class="headerlink" title="1、Memcached的原理"></a>1、Memcached的原理</h2><p>Memcache是一个高性能的分布式的内存对象缓存系统,通过在内存里维护一个统一的巨大的hash表,它能够用来存储各种格式的数据,包括图像、视频、文件以及数据库检索的结果等。简单的说就是将数据调用到内存中,然后从内存中读取,从而大大提高读取速度。<br>Memcache是项目的名称,Memcached是一个程序。<br><a id="more"></a></p><h2 id="2、Memcached的应用"><a href="#2、Memcached的应用" class="headerlink" title="2、Memcached的应用"></a>2、Memcached的应用</h2><pre><code>1>、处理数据库高并发的读写2>、对海量数据的处理</code></pre><h2 id="3、事件处理"><a href="#3、事件处理" class="headerlink" title="3、事件处理"></a>3、事件处理</h2><p>Memcached基于libevent库进行事件处理。</p><pre><code>* libevent是个事件通知库,将系统的kqueue等事件处理功能封装成一个统一的接口,这样即使对服务器的连接数增加,也能发挥O(1)的性能。</code></pre><h2 id="4、内存管理"><a href="#4、内存管理" class="headerlink" title="4、内存管理"></a>4、内存管理</h2><h4 id="4-1、基础知识(摘自)"><a href="#4-1、基础知识(摘自)" class="headerlink" title="4.1、基础知识(摘自)"></a>4.1、基础知识(<a href="http://www.cnblogs.com/coder2012/p/4458015.html" target="_blank" rel="noopener">摘自</a>)</h4><pre><code>* slab:内存块是memcached一次申请内存的最小单元,在memcached中一个slab的默认大小为1M;* slabclass:特定大小的chunk的组。 * chunk:缓存的内存空间,一个slab被划分为若干个chunk; * item:存储数据的最小单元,每一个chunk都会包含一个item; * factor:增长因子,默认为1.25,相邻slab中的item大小与factor成比例关系;</code></pre><h4 id="4-2、基本原理(摘自)"><a href="#4-2、基本原理(摘自)" class="headerlink" title="4.2、基本原理(摘自)"></a>4.2、基本原理(<a href="http://www.cnblogs.com/coder2012/p/4458015.html" target="_blank" rel="noopener">摘自</a>)</h4><ul><li><p>memcached使用预分配方法,避免频繁的调用malloc和free;</p></li><li><p>memcached通过不同的slab来管理不同chunk大小的内存块,从而满足存储不同大小的数据。</p></li><li><p>slab的申请是通过在使用item时申请slab大小的内存空间,然后再把内存切割为大小相同的item,挂在到slab的未使用链表上。</p></li><li><p>过期和被删除item并不会被free掉,memcached并不会删除已经分配的内存;</p></li><li><p>Memcached会优先使用已超时的记录空间,通过LRU算法;</p></li><li><p>memcached使用lazy expiration来判断元素是否过期,所以过期监视上不会占用cpu时间。</p></li></ul><h4 id="4-3、分配内存(可参考)"><a href="#4-3、分配内存(可参考)" class="headerlink" title="4.3、分配内存(可参考)"></a>4.3、分配内存(<a href="http://www.open-open.com/lib/view/open1376034527667.html" target="_blank" rel="noopener">可参考</a>)</h4><p>Memcached使用<a href="https://www.ibm.com/developerworks/cn/linux/l-linux-slab-allocator/#icomments" target="_blank" rel="noopener">slab</a>分配算法保存数据,分配内存。<br>Memcached 的内存分配以page为单位,默认情况下一个page是1M,可以通过-I参数在启动时指定。<br>储存变量时,Memcached根据slab算法检查是否有相同的slab类,如果有空闲的块,就把数据储存在该块上,没有则申请新的内存。<br>Memcached的存储结构:<br><img src="http://onx0p7mg5.bkt.clouddn.com/272357235313577.png" alt="结构"></p><h4 id="4-4、淘汰数据"><a href="#4-4、淘汰数据" class="headerlink" title="4.4、淘汰数据"></a>4.4、淘汰数据</h4><p>Memcached使用LRU(Least Recently Used)近期最少使用算法将数据移除内存。</p><pre><code>* LRU:内存管理的一种页面置换算法</code></pre><h4 id="4-5、memcached服务器增多"><a href="#4-5、memcached服务器增多" class="headerlink" title="4.5、memcached服务器增多"></a>4.5、memcached服务器增多</h4><p>Memcached在添加或者减少服务器的时候,服务端的缓存将会失效,Memcached采用Consistent hashing算法,当实例数量的变化将只可能导致其中的一小部分键的哈希值发生改变。</p><h4 id="4-6、虚拟节点(摘自)"><a href="#4-6、虚拟节点(摘自)" class="headerlink" title="4.6、虚拟节点(摘自)"></a>4.6、虚拟节点(<a href="http://www.111cn.net/sys/linux/58748.htm" target="_blank" rel="noopener">摘自</a>)</h4><p>Consistent hashing算法在服务节点太少时,容易因为节点分部不均匀而造成数据倾斜问题。例如我们的系统中有两台 server,其环分布如下:</p><p><img src="http://onx0p7mg5.bkt.clouddn.com/20140312125612748.png" alt="virtual"></p><p>此时必然造成大量数据集中到Server 1上,而只有极少量会定位到Server 2上。为了解决这种数据倾斜问题,一致性哈希算法引入了虚拟节点机制,即对每一个服务节点计算多个哈希,每个计算结果位置都放置一个此服务节点,称为虚拟节点。</p><p>具体做法可以在服务器ip或主机名的后面增加编号来实现。例如上面的情况,我们决定为每台服务器计算三个虚拟节点,于是可以分别计算“Memcached Server 1#1”、“Memcached Server 1#2”、“Memcached Server 1#3”、“Memcached Server 2#1”、“Memcached Server 2#2”、“Memcached Server 2#3”的哈希值,于是形成六个虚拟节点:<br><img src="http://onx0p7mg5.bkt.clouddn.com/20140312125616365.png" alt="virtual2"></p><h2 id="5、错误指令"><a href="#5、错误指令" class="headerlink" title="5、错误指令"></a>5、错误指令</h2><div class="table-container"><table><thead><tr><th style="text-align:left">指令</th><th style="text-align:left">说明</th></tr></thead><tbody><tr><td style="text-align:left">ERROR</td><td style="text-align:left">普通错误信息</td></tr><tr><td style="text-align:left">CLIENT_ERROR</td><td style="text-align:left">客户端错误</td></tr><tr><td style="text-align:left">SERVER_ERROR</td><td style="text-align:left">服务器端错误</td></tr></tbody></table></div><pre><code>以上是我搜了好多资料,不是很理解内存的分配原理,用的话大家都会用</code></pre>]]></content>
<summary type="html">
<h2 id="1、Memcached的原理"><a href="#1、Memcached的原理" class="headerlink" title="1、Memcached的原理"></a>1、Memcached的原理</h2><p>Memcache是一个高性能的分布式的内存对象缓存系统,通过在内存里维护一个统一的巨大的hash表,它能够用来存储各种格式的数据,包括图像、视频、文件以及数据库检索的结果等。简单的说就是将数据调用到内存中,然后从内存中读取,从而大大提高读取速度。<br>Memcache是项目的名称,Memcached是一个程序。<br>
</summary>
<category term="memcached" scheme="http://blog.feifan.news/tags/memcached/"/>
</entry>
<entry>
<title>了解Apache的配置http.conf</title>
<link href="http://blog.feifan.news/2017/04/18/http-conf/"/>
<id>http://blog.feifan.news/2017/04/18/http-conf/</id>
<published>2017-04-18T07:50:06.000Z</published>
<updated>2019-05-06T15:38:02.760Z</updated>
<content type="html"><![CDATA[<p>最近想研究一下Apache的配置文件,顺便记录一下。</p><h4 id="1、ServerRoot-“-xampp-apache”"><a href="#1、ServerRoot-“-xampp-apache”" class="headerlink" title="1、ServerRoot “/xampp/apache”"></a>1、ServerRoot “/xampp/apache”</h4><pre><code>Apache运行的目录,服务启动之后自动将目录改变为当前目录,在后面使用到的所有相对路径都是想对这个目录下</code></pre><a id="more"></a><h4 id="2、Listen-80"><a href="#2、Listen-80" class="headerlink" title="2、Listen 80"></a>2、Listen 80</h4><pre><code>服务器监听端口号</code></pre><h4 id="3、KeepAlive-On-Off"><a href="#3、KeepAlive-On-Off" class="headerlink" title="3、KeepAlive On|Off"></a>3、KeepAlive On|Off</h4><pre><code>保持连接活跃,大家都知道客户端和服务器端的连接是通过TCP协议三次握手创建连接,请求结束后会立即断开连接,下次请求会重新建立连接。每次请求都要新建一个连接而加重服务器的负担。On: 用户完成一次访问后,不会立即断开连接,如果还有请求,那么会继续在这一次 TCP 连接中完成,而不用重复建立新的 TCP 连接和关 闭TCP 连接,可以提高用户访问速度。Off:如上面所说</code></pre><h4 id="4、KeepAliveTimeout-5"><a href="#4、KeepAliveTimeout-5" class="headerlink" title="4、KeepAliveTimeout 5"></a>4、KeepAliveTimeout 5</h4><pre><code>保持活跃连接的时间。这个参数只有在KeepAlive开启时起作用,改值的设置影响服务器的性能。KeepAliveTimeout 太小发挥不了持续连接的作用;太大了,持续连接迟迟不断, 浪费TCP连接数不说,更糟糕的是系统中的 httpd 进程数目会因此不断增加, 使得系统负载升高,甚至会导致服务器失去响应。可以通过access_log统计出连续HTTP请求出现的次数、间隔时间、访问量, 以确定 MaxKeepAliveRequests 和 KeepAliveTimeout 的值</code></pre><h4 id="5、MaxKeepAliveRequests-100"><a href="#5、MaxKeepAliveRequests-100" class="headerlink" title="5、MaxKeepAliveRequests 100"></a>5、MaxKeepAliveRequests 100</h4><pre><code>每个连接的最大请求数量。如果设为0,将不限制请求的数量,建议设置的大一点,确保服务器的性能最优。</code></pre><h4 id="6、Timeout-300"><a href="#6、Timeout-300" class="headerlink" title="6、Timeout 300"></a>6、Timeout 300</h4><pre><code>请求超时的时间。当KeepAlive 设置为Off时起作用,当KeepAlive为On时,KeepAliveTimeout为超时时间</code></pre><h4 id="7、系统默认模块"><a href="#7、系统默认模块" class="headerlink" title="7、系统默认模块"></a>7、系统默认模块</h4><h5 id="7-1、进程模块(prefork-MPM)"><a href="#7-1、进程模块(prefork-MPM)" class="headerlink" title="7.1、进程模块(prefork MPM)"></a>7.1、进程模块(prefork MPM)</h5><pre><code><IfModule mpm_prefork_module> StartServers 5 //开始服务时启动5个进程 MinSpareServers 5 //最少空闲5个进程 MaxSpareServers 10 //最多空闲10个进程 MaxRequestWorkers 250 //允许启动的服务器进程的最大数目 MaxConnectionsPerChild 0 //每个子进程在其生存期内允许伺服的最大请求数量</IfModule></code></pre><p>表示为每个访问启动一个进程(即当有多个连接公用一个进程的时候,在同一时刻只能有一个获得服务)。如下图:</p><p><img src="http://onx0p7mg5.bkt.clouddn.com/prefork.jpg" alt="prefork"></p><pre><code>优点:成熟稳定,兼容所有新老模块。同时,不需要担心线程安全的问题。(我们常用的mod_php,PHP的拓展不需要支持线程安全)缺点:一个进程相对占用更多的系统资源,消耗更多的内存。而且,它并不擅长处理高并发请求,在这种场景下,它会将请求放进队列中,一直等到有可用进程,请求才会被处理。</code></pre><p>MaxRequestsPerChild:每个子进程在其生存期内允许伺服的最大请求数量,默认为10000.到达MaxRequestsPerChild的限制后,子进程将会结束。如果MaxRequestsPerChild为”0”,子进程将永远不会结束。将MaxRequestsPerChild设置成非零值有两个好处:<br>1.可以防止(偶然的)内存泄漏无限进行,从而耗尽内存。<br>2.给进程一个有限寿命,从而有助于当服务器负载减轻的时候减少活动进程的数量。</p><h5 id="7-2、进程、线程模块(worker-MPM)"><a href="#7-2、进程、线程模块(worker-MPM)" class="headerlink" title="7.2、进程、线程模块(worker MPM)"></a>7.2、进程、线程模块(worker MPM)</h5><pre><code><IfModule mpm_event_module> StartServers 3 MinSpareThreads 75 MaxSpareThreads 250 ThreadsPerChild 25 //每个子进程生存期间常驻执行线程数,子线程建立之后将不再增加 MaxRequestWorkers 400 MaxConnectionsPerChild 0</IfModule></code></pre><p>worker模式使用了多进程和多线程的混合模式。</p><pre><code>优点:占据更少的内存,高并发下表现更优秀,如果一个线程挂了,不会影响整个进程,只会影响局部。缺点:必须考虑线程安全的问题,因为多个子线程是共享父进程的内存地址的。如果使用keep-alive的长连接方式,某个线程会一直被占据,也许中间几乎没有请求,需要一直等待到超时才会被释放。如果过多的线程,被这样占据,也会导致在高并发场景下的无服务线程可用。(该问题在prefork模式下,同样会发生)</code></pre><p>注:keep-alive的长连接方式,是为了让下一次的socket通信复用之前创建的连接,从而,减少连接的创建和销毁的系统开销。保持连接,会让某个进程或者线程一直处于等待状态,即使没有数据过来。</p><h5 id="7-3、event-MPM"><a href="#7-3、event-MPM" class="headerlink" title="7.3、event MPM"></a>7.3、event MPM</h5><p>这个是Apache中最新的模式,在现在版本里的已经是稳定可用的模式。它和worker模式很像,最大的区别在于,它解决了keep-alive场景下,长期被占用的线程的资源浪费问题(某些线程因为被keep-alive,空挂在哪里等待,中间几乎没有请求过来,甚至等到超时)。event MPM中,会有一个专门的线程来管理这些keep-alive类型的线程,当有真实请求过来的时候,将请求传递给服务线程,执行完毕后,又允许它释放。这样增强了高并发场景下的请求处理能力。</p><p>event MPM在遇到某些不兼容的模块时,会失效,将会回退到worker模式,一个工作线程处理一个请求。官方自带的模块,全部是支持event MPM的。</p><p>注意一点,event MPM需要Linux系统(Linux 2.6+)对EPoll的支持,才能启用。</p><p>还有,需要补充的是HTTPS的连接(SSL),它的运行模式仍然是类似worker的方式,线程会被一直占用,知道连接关闭。部分比较老的资料里,说event MPM不支持SSL,那个说法是几年前的说法,现在已经支持了。</p><p>摘自: <a href="http://blog.jobbole.com/91920/" target="_blank" rel="noopener">http://blog.jobbole.com/91920/</a></p><h4 id="8、LoadModule-xxxxxx"><a href="#8、LoadModule-xxxxxx" class="headerlink" title="8、LoadModule xxxxxx"></a>8、LoadModule xxxxxx</h4><p>启动时加载的模块</p><h4 id="9、Include-conf-extra-conf"><a href="#9、Include-conf-extra-conf" class="headerlink" title="9、Include conf/extra/*.conf"></a>9、Include conf/extra/*.conf</h4><p>需要加载的配置文件</p><h4 id="10、切换身份"><a href="#10、切换身份" class="headerlink" title="10、切换身份"></a>10、切换身份</h4><pre><code>User daemonGroup daemon</code></pre><p>启动服务后转换的身份,在启动服务时通常以root身份,然后转换身份,这样增加系统安全</p><h4 id="11、ServerAdmin"><a href="#11、ServerAdmin" class="headerlink" title="11、ServerAdmin"></a>11、ServerAdmin</h4><p>ServerAdmin postmaster@localhost 管理员的邮箱</p><h4 id="12、ServerName"><a href="#12、ServerName" class="headerlink" title="12、ServerName"></a>12、ServerName</h4><p>ServerName localhost:80 服务器名称</p><hr><p>下面的比较重要了。。。</p><h4 id="13、DocumentRoot"><a href="#13、DocumentRoot" class="headerlink" title="13、DocumentRoot"></a>13、DocumentRoot</h4><p>DocumentRoot “/xampp/htdocs” //根目录</p><h4 id="14、目录的权限设置"><a href="#14、目录的权限设置" class="headerlink" title="14、目录的权限设置"></a>14、目录的权限设置</h4><pre><code><Directory "/xampp/htdocs"> Options FollowSymLinks Includes ExecCGI //不显示目录 AllowOverride All //表示允许这个目录下的访问控制文件.htaccess来改变这里的配置,None:不允许 Require all granted //允许所有用户访问 Order Deny,Allow //对页面的访问控制顺序 Allow from All</Directory></code></pre><p>是否显示文件的目录:<br>显示目录:Options Indexes FollowSymLinks<br>不显示目录:Options Includes FollowSymLinks ExecCGI<br>目录、文件的访问权限:<br>2.2</p><pre><code>Order Allow,DenyAllow from AllDeny from IP1 //禁止IP1对该目录的访问</code></pre><p>2.4</p><pre><code>Require all granted //允许所有用户访问Require all denied //拒绝所有用户访问Require host google.com //允许特定域名主机的访问Require ip 192.120 192.168.100 192.168.1.1 //允许特定IP或者IP段的访问Require not ip 192.168.1.1 //拒绝来自特定IP或IP段的访问请求</code></pre><p> 例:允许所有访问请求,但拒绝某些User-Agent的访问请求(通过User-Agent屏蔽垃圾网络爬虫)<br>使用mod_setenvif通过正则表达式匹配来访请求的User-Agent,并设置内部环境变量BADBOT,最后拒绝BADBOT的访问请求。</p><pre><code><Directory xxx/www/yoursite> SetEnvIfNoCase User-Agent ".*(FeedDemon|JikeSpider|AskTbFXTV|CrawlDaddy|Feedly|Swiftbot|ZmEu|oBot).*" BADBOT SetEnvIfNoCase User-Agent "brandwatch" BADBOT SetEnvIfNoCase User-Agent "rogerbot" BADBOT <RequireAll> Require all granted Require not env BADBOT Require not ip 192.168.100.1 </RequireAll></Directory></code></pre><h4 id="15、日志"><a href="#15、日志" class="headerlink" title="15、日志"></a>15、日志</h4><p>LogLevel warn:Apache的日志级别<br>ErrorLog “logs/error.log”:错误日志存放的位置<br>LogFormat 日志的格式:</p><pre><code>LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combinedLogFormat "%h %l %u %t \"%r\" %>s %b" common</code></pre><p>CustomLog “logs/access.log” combined :说明日志的记录位置</p><h4 id="16、ServerSignature"><a href="#16、ServerSignature" class="headerlink" title="16、ServerSignature"></a>16、ServerSignature</h4><p>ServerSignature On 定义当客户请求的网页不存在时,或者错误时是否提示apache的版本信息,Off为关闭</p><h4 id="17、别名"><a href="#17、别名" class="headerlink" title="17、别名"></a>17、别名</h4><p>Alias:定义一些不在DocumentRoot目录下的文件,而可以将其映射到网页的根目录下,这也是访问其他目录的一种方法,但声明时要在目录后面加上’/‘。</p><pre><code>Alias /webpath /full/filesystem/path</code></pre><p>ScriptAlias:对CGI(Common Gateway Interface)模块的别名,与Alias相似</p><pre><code>ScriptAlias /cgi-bin/ "/xampp/cgi-bin/"</code></pre><h4 id="18、其他"><a href="#18、其他" class="headerlink" title="18、其他"></a>18、其他</h4><p>HostnameLookups off是否进行域名的解析,一般关掉,,,会占用资源,而且一般的ip地址没有反向解析,或者不允许;apache有一个日志叫XXX,里面记录了每个客户端的访问信息,包括ip地址,那些请求,访问了那些页面···如果开启了,apache会将这些源ip地址解析到域名<br>ServerTokens Full:默认地,服务器HTTP响应头会包含apache和php版本号,Prod禁止发送版本号</p><p>以上是大致看了一下http.conf的文件,了解了一下基本的配置以及配置的作用。</p>]]></content>
<summary type="html">
<p>最近想研究一下Apache的配置文件,顺便记录一下。</p>
<h4 id="1、ServerRoot-“-xampp-apache”"><a href="#1、ServerRoot-“-xampp-apache”" class="headerlink" title="1、ServerRoot “/xampp/apache”"></a>1、ServerRoot “/xampp/apache”</h4><pre><code>Apache运行的目录,服务启动之后自动将目录改变为当前目录,在后面使用到的所有相对路径都是想对这个目录下
</code></pre>
</summary>
<category term="PHP" scheme="http://blog.feifan.news/categories/PHP/"/>
<category term="Apache" scheme="http://blog.feifan.news/tags/Apache/"/>
</entry>
<entry>
<title>apache性能测试工具ab</title>
<link href="http://blog.feifan.news/2017/04/17/ab/"/>
<id>http://blog.feifan.news/2017/04/17/ab/</id>
<published>2017-04-17T04:37:56.000Z</published>
<updated>2019-05-06T15:38:02.755Z</updated>
<content type="html"><![CDATA[<h2 id="1、ab原理"><a href="#1、ab原理" class="headerlink" title="1、ab原理"></a>1、ab原理</h2><p>ab是apachebench的缩写<br>ab命令会创建多个并发访问线程,对同一个URL访问来测试apache的负载压力。测试目标是URL。<br>同样适用于Nginx、Lighthttp、Tomcat、IIS等其它服务器<br>ab命令不会占用很高的CPU,也不会占用很多内存,但却给目标服务器造成巨大的负载,如果负载太多,可能导致目标服务器死机,其原理类似CCI攻击,所以大家测试的时候需要注意。<br><a id="more"></a></p><h2 id="2、ab的参数"><a href="#2、ab的参数" class="headerlink" title="2、ab的参数"></a>2、ab的参数</h2><p>Apache自身已经带了ab工具,所以不需要安装(Apache的安装自己可以百度了)。<br>ab的参数比较多,常用的用 -c 和 -n ,其它的自己可以去了解一下(ab —help)。<br>以下是对参数的说明</p><pre><code>-n在测试会话中所执行的请求个数。默认时,仅执行一个请求。-c一次产生的请求个数。默认是一次一个。-t测试所进行的最大秒数。其内部隐含值是-n 50000,它可以使对服务器的测试限制在一个固定的总时间以内。默认时,没有时间限制。-p包含了需要POST的数据的文件。-P对一个中转代理提供BASIC认证信任。用户名和密码由一个:隔开,并以base64编码形式发送。无论服务器是否需要(即, 是否发送了401认证需求代码),此字符串都会被发送。-T POST数据所使用的Content-type头信息。-v设置显示信息的详细程度-4或更大值会显示头信息,3或更大值可以显示响应代码(404,200等),2或更大值可以显示警告和其他信息。-V显示版本号并退出。-w以HTML表的格式输出结果。默认时,它是白色背景的两列宽度的一张表。-i执行HEAD请求,而不是GET。-x设置<table>属性的字符串。-X对请求使用代理服务器。-y设置<tr>属性的字符串。-z设置<td>属性的字符串。-C对请求附加一个Cookie:行。其典型形式是name=value的一个参数对,此参数可以重复。-H对请求附加额外的头信息。此参数的典型形式是一个有效的头信息行,其中包含了以冒号分隔的字段和值的对(如,"Accept-Encoding:zip/zop;8bit")。-A对服务器提供BASIC认证信任。用户名和密码由一个:隔开,并以base64编码形式发送。无论服务器是否需要(即,是否发送了401认证需求代码),此字符串都会被发送。-h显示使用方法。-d不显示"percentage served within XX [ms] table"的消息(为以前的版本提供支持)。-e产生一个以逗号分隔的(CSV)文件,其中包含了处理每个相应百分比的请求所需要(从1%到100%)的相应百分比的(以微妙为单位)时间。由于这种格式已经“二进制化”,所以比'gnuplot'格式更有用。-g把所有测试结果写入一个'gnuplot'或者TSV(以Tab分隔的)文件。此文件可以方便地导入到Gnuplot,IDL,Mathematica,Igor甚至Excel中。其中的第一行为标题。-i执行HEAD请求,而不是GET。-k启用HTTP KeepAlive功能,即在一个HTTP会话中执行多个请求。默认时,不启用KeepAlive功能。-q如果处理的请求数大于150,ab每处理大约10%或者100个请求时,会在stderr输出一个进度计数。此-q标记可以抑制这些信息。</code></pre><h2 id="3、ab的性能指标"><a href="#3、ab的性能指标" class="headerlink" title="3、ab的性能指标"></a>3、ab的性能指标</h2><p>在性能测试中以下几个指标比较重要:</p><h4 id="3-1吞吐率"><a href="#3-1吞吐率" class="headerlink" title="3.1吞吐率"></a>3.1吞吐率</h4><pre><code>吞吐率(Requests pre second):服务器并发处理能力的量化描述,单位reqs/s,是指在某个并发用户数下单位时间内处理的请求数。\* 吞吐率是基于并发用户数的:a、吞吐率合并发用户数相关b、不同的并发用户数下,吞吐率一般是不相同的</code></pre><h4 id="3-2、并发连接数"><a href="#3-2、并发连接数" class="headerlink" title="3.2、并发连接数"></a>3.2、并发连接数</h4><pre><code>并发连接数(The number of concurrent connections):某个时刻服务器所接受的请求数目,简单的说就是一个回话</code></pre><h4 id="3-3、并发用户数"><a href="#3-3、并发用户数" class="headerlink" title="3.3、并发用户数"></a>3.3、并发用户数</h4><pre><code>并发用户数(Concurrency Level):请求的用户数量,一个用户可能同时产生多个回话(连接数)。在HTTP/1.1下,IE7支持两个并发连接,IE8支持6个并发连接,FireFox3支持4个并发连接,所以相应的,我们的并发用户数就得除以这个基数。</code></pre><h4 id="3-4、用户平均请求的等待时间"><a href="#3-4、用户平均请求的等待时间" class="headerlink" title="3.4、用户平均请求的等待时间"></a>3.4、用户平均请求的等待时间</h4><pre><code>用户平均请求的等待时间(Time pre request)的计算方法:处理完成所有请求所花费的时间/(总请求数/并发用户数),即:Time per request=Time taken for tests/(Complete requests/Concurrency Level)</code></pre><h4 id="3-5、服务器平均请求等待时间"><a href="#3-5、服务器平均请求等待时间" class="headerlink" title="3.5、服务器平均请求等待时间"></a>3.5、服务器平均请求等待时间</h4><pre><code>服务器平均请求等待时间(Time per request:across all concurrent requests)计算方法:处理完成所有请求数所花费的时间/总请求数,即:Time taken for/testsComplete requests</code></pre><h2 id="4、ab的使用"><a href="#4、ab的使用" class="headerlink" title="4、ab的使用"></a>4、ab的使用</h2><p>常用命令: ab -c 并发数 -n 总的请求数 URL<br>下面以百度为例;来测试一下(对不住了=_=),还有就是ab不支持HTTPS。<br><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br></pre></td><td class="code"><pre><span class="line">[root@VM_161_199_centos bin]<span class="comment"># ./ab https://www.baidu.com/</span></span><br><span class="line">This is ApacheBench, Version <span class="number">2.3</span> <$Revision: <span class="number">1757674</span> $></span><br><span class="line">Copyright <span class="number">1996</span> Adam Twiss, Zeus Technology Ltd, http:<span class="comment">//www.zeustech.net/</span></span><br><span class="line">Licensed to The Apache Software Foundation, http:<span class="comment">//www.apache.org/</span></span><br><span class="line"></span><br><span class="line">Benchmarking www.baidu.com (be patient).....done</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">Server Software: bfe/<span class="number">1.0</span><span class="number">.8</span><span class="number">.18</span></span><br><span class="line">Server Hostname: www.baidu.com</span><br><span class="line">Server Port: <span class="number">443</span></span><br><span class="line">SSL/TLS Protocol: TLSv1<span class="number">.2</span>,ECDHE-RSA-AES128-GCM-SHA256,<span class="number">2048</span>,<span class="number">128</span></span><br><span class="line">TLS Server Name: www.baidu.com</span><br><span class="line"></span><br><span class="line">Document Path: /</span><br><span class="line">Document Length: <span class="number">227</span> bytes</span><br><span class="line"></span><br><span class="line">Concurrency Level: <span class="number">1</span></span><br><span class="line">Time taken <span class="keyword">for</span> tests: <span class="number">0.028</span> seconds</span><br><span class="line">Complete requests: <span class="number">1</span></span><br><span class="line">Failed requests: <span class="number">0</span></span><br><span class="line">Total transferred: <span class="number">1033</span> bytes</span><br><span class="line">HTML transferred: <span class="number">227</span> bytes</span><br><span class="line">Requests per second: <span class="number">35.17</span> [<span class="comment">#/sec] (mean)</span></span><br><span class="line">Time per request: <span class="number">28.432</span> [ms] (mean)</span><br><span class="line">Time per request: <span class="number">28.432</span> [ms] (mean, across all concurrent requests)</span><br><span class="line">Transfer rate: <span class="number">35.48</span> [Kbytes/sec] received</span><br><span class="line"></span><br><span class="line">Connection Times (ms)</span><br><span class="line"> min mean[+/-sd] median max</span><br><span class="line">Connect: <span class="number">22</span> <span class="number">22</span> <span class="number">0.0</span> <span class="number">22</span> <span class="number">22</span></span><br><span class="line">Processing: <span class="number">7</span> <span class="number">7</span> <span class="number">0.0</span> <span class="number">7</span> <span class="number">7</span></span><br><span class="line">Waiting: <span class="number">7</span> <span class="number">7</span> <span class="number">0.0</span> <span class="number">7</span> <span class="number">7</span></span><br><span class="line">Total: <span class="number">28</span> <span class="number">28</span> <span class="number">0.0</span> <span class="number">28</span> <span class="number">28</span></span><br></pre></td></tr></table></figure></p><p>在模仿10个用户,发送100条请求<br><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br></pre></td><td class="code"><pre><span class="line">[root@VM_161_199_centos bin]<span class="comment"># ./ab -c 10 -n 100 https://www.baidu.com/</span></span><br><span class="line">This is ApacheBench, Version <span class="number">2.3</span> <$Revision: <span class="number">1757674</span> $></span><br><span class="line">Copyright <span class="number">1996</span> Adam Twiss, Zeus Technology Ltd, http:<span class="comment">//www.zeustech.net/</span></span><br><span class="line">Licensed to The Apache Software Foundation, http:<span class="comment">//www.apache.org/</span></span><br><span class="line"></span><br><span class="line">Benchmarking www.baidu.com (be patient).....done</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">Server Software: bfe/<span class="number">1.0</span><span class="number">.8</span><span class="number">.18</span></span><br><span class="line">Server Hostname: www.baidu.com</span><br><span class="line">Server Port: <span class="number">443</span></span><br><span class="line">SSL/TLS Protocol: TLSv1<span class="number">.2</span>,ECDHE-RSA-AES128-GCM-SHA256,<span class="number">2048</span>,<span class="number">128</span></span><br><span class="line">TLS Server Name: www.baidu.com</span><br><span class="line"></span><br><span class="line">Document Path: /</span><br><span class="line">Document Length: <span class="number">227</span> bytes</span><br><span class="line"></span><br><span class="line"><span class="comment">#表示并发用户数,这是我们设置的参数之一</span></span><br><span class="line">Concurrency Level: <span class="number">10</span></span><br><span class="line"><span class="comment">#整个测试持续的时间</span></span><br><span class="line">Time taken <span class="keyword">for</span> tests: <span class="number">0.482</span> seconds</span><br><span class="line"><span class="comment">#完成的请求数量</span></span><br><span class="line">Complete requests: <span class="number">100</span></span><br><span class="line"><span class="comment">#失败的请求数量</span></span><br><span class="line">Failed requests: <span class="number">0</span></span><br><span class="line"><span class="comment">#整个过程中的网络传输量</span></span><br><span class="line">Total transferred: <span class="number">103296</span> bytes</span><br><span class="line"><span class="comment">#整个过程中的HTML内容传输量</span></span><br><span class="line">HTML transferred: <span class="number">22700</span> bytes</span><br><span class="line"><span class="comment">#最重要的指标之一,吞吐率-每秒请求数,后面括号中的mean表示这是一个平均值</span></span><br><span class="line">Requests per second: <span class="number">207.58</span> [<span class="comment">#/sec] (mean)</span></span><br><span class="line"><span class="comment">#最重要的指标之二,用户平均请求等待时间,后面括号中的mean表示这是一个平均值</span></span><br><span class="line">Time per request: <span class="number">48.174</span> [ms] (mean)</span><br><span class="line"><span class="comment">#最重要的指标之三,服务器平均请求等待时间</span></span><br><span class="line">Time per request: <span class="number">4.817</span> [ms] (mean, across all concurrent requests)</span><br><span class="line"><span class="comment"># 平均每秒网络上的流量,可以帮助排除是否存在网络流量过大导致响应时间延长的问题</span></span><br><span class="line">Transfer rate: <span class="number">209.40</span> [Kbytes/sec] received</span><br><span class="line"></span><br><span class="line"><span class="comment">#网络上消耗的时间的分解: </span></span><br><span class="line">Connection Times (ms)</span><br><span class="line"> min mean[+/-sd] median max</span><br><span class="line">Connect: <span class="number">20</span> <span class="number">36</span> <span class="number">8.6</span> <span class="number">35</span> <span class="number">60</span></span><br><span class="line">Processing: <span class="number">6</span> <span class="number">10</span> <span class="number">5.3</span> <span class="number">8</span> <span class="number">30</span></span><br><span class="line">Waiting: <span class="number">6</span> <span class="number">10</span> <span class="number">4.2</span> <span class="number">8</span> <span class="number">28</span></span><br><span class="line">Total: <span class="number">31</span> <span class="number">46</span> <span class="number">8.4</span> <span class="number">45</span> <span class="number">69</span></span><br><span class="line"></span><br><span class="line"> <span class="comment">#整个场景中所有请求的响应情况。在场景中每个请求都有一个响应时间,</span></span><br><span class="line"> <span class="comment">#其中50%的用户响应时间小于45毫秒,</span></span><br><span class="line"> <span class="comment">#66%的用户响应时间小于49毫秒,</span></span><br><span class="line"> <span class="comment">#最大的响应时间小于69毫秒。</span></span><br><span class="line"> <span class="comment">#对于并发请求,cpu实际上并不是同时处理的,而是按照每个请求获得的时间片逐个轮转处理的,所以基本上第一个Time per request时间约等于第二个Time per request时间乘以并发请求数。</span></span><br><span class="line">Percentage of the requests served within a certain time (ms)</span><br><span class="line"> <span class="number">50</span>% <span class="number">45</span></span><br><span class="line"> <span class="number">66</span>% <span class="number">49</span></span><br><span class="line"> <span class="number">75</span>% <span class="number">50</span></span><br><span class="line"> <span class="number">80</span>% <span class="number">52</span></span><br><span class="line"> <span class="number">90</span>% <span class="number">60</span></span><br><span class="line"> <span class="number">95</span>% <span class="number">62</span></span><br><span class="line"> <span class="number">98</span>% <span class="number">68</span></span><br><span class="line"> <span class="number">99</span>% <span class="number">69</span></span><br><span class="line"> <span class="number">100</span>% <span class="number">69</span> (longest request)</span><br></pre></td></tr></table></figure></p><p>以上是压力测试的对比,主要关注一下几个地方:</p><ul><li>整个测试持续的时间<br>Time taken for tests: 0.482 seconds</li><li>最重要的指标之一,吞吐率-每秒请求数,后面括号中的mean表示这是一个平均值<br>Requests per second: 207.58 [#/sec] (mean)</li></ul><ul><li>最重要的指标之二,用户平均请求等待时间,后面括号中的mean表示这是一个平均值<br>Time per request: 48.174 [ms] (mean)</li></ul><ul><li>最重要的指标之三,服务器平均请求等待时间<br>Time per request: 4.817 [ms] (mean, across all concurrent requests)</li></ul>]]></content>
<summary type="html">
<h2 id="1、ab原理"><a href="#1、ab原理" class="headerlink" title="1、ab原理"></a>1、ab原理</h2><p>ab是apachebench的缩写<br>ab命令会创建多个并发访问线程,对同一个URL访问来测试apache的负载压力。测试目标是URL。<br>同样适用于Nginx、Lighthttp、Tomcat、IIS等其它服务器<br>ab命令不会占用很高的CPU,也不会占用很多内存,但却给目标服务器造成巨大的负载,如果负载太多,可能导致目标服务器死机,其原理类似CCI攻击,所以大家测试的时候需要注意。<br>
</summary>
<category term="Tool" scheme="http://blog.feifan.news/categories/Tool/"/>
<category term="调试工具" scheme="http://blog.feifan.news/tags/%E8%B0%83%E8%AF%95%E5%B7%A5%E5%85%B7/"/>
</entry>
<entry>
<title>win常用命令</title>
<link href="http://blog.feifan.news/2017/04/11/win-dos/"/>
<id>http://blog.feifan.news/2017/04/11/win-dos/</id>
<published>2017-04-11T02:54:06.000Z</published>
<updated>2019-05-06T15:38:02.753Z</updated>
<content type="html"><![CDATA[<h2 id="1、win的一些常用命令"><a href="#1、win的一些常用命令" class="headerlink" title="1、win的一些常用命令"></a>1、win的一些常用命令</h2><div class="table-container"><table><thead><tr><th style="text-align:left">类型</th><th style="text-align:left">说明</th></tr></thead><tbody><tr><td style="text-align:left">md</td><td style="text-align:left">创建目录</td></tr><tr><td style="text-align:left">rd[/S /Q]</td><td style="text-align:left">删除子目录(加上参数为强制删除S:递归,Q:安静模式,强制)</td></tr><tr><td style="text-align:left">del[/p /q /f]</td><td style="text-align:left">删除文件(p:每次询问,q:不询问,f强制删除)</td></tr><tr><td style="text-align:left">tree[/f]</td><td style="text-align:left">树状显示目录下的文件及文件夹</td></tr><tr><td style="text-align:left">type</td><td style="text-align:left">查看文件内容</td></tr></tbody></table></div>]]></content>
<summary type="html">
<h2 id="1、win的一些常用命令"><a href="#1、win的一些常用命令" class="headerlink" title="1、win的一些常用命令"></a>1、win的一些常用命令</h2><div class="table-container">
<ta
</summary>
<category term="win" scheme="http://blog.feifan.news/tags/win/"/>
</entry>
<entry>
<title>三月份工作总结</title>
<link href="http://blog.feifan.news/2017/04/10/summary-3/"/>
<id>http://blog.feifan.news/2017/04/10/summary-3/</id>
<published>2017-04-10T06:58:30.000Z</published>
<updated>2020-11-22T06:07:42.344Z</updated>
<content type="html"><![CDATA[<p>终于闲下来了,趁此时间把三月份总结一下</p><h2 id="1、Ajax分页"><a href="#1、Ajax分页" class="headerlink" title="1、Ajax分页"></a>1、Ajax分页</h2><p>企业购的后台模板管理、楼层管理中用到的ajax分页(商品的选择、搜索),自己写了一下,还不是很完整,先记录一下(注:下面的数据都是修改过的,不会对我们的网站产生任何影响)。<br><a id="more"></a></p><h4 id="1-1、htnl代码"><a href="#1-1、htnl代码" class="headerlink" title="1.1、htnl代码"></a>1.1、htnl代码</h4><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment"><!--data的值要和input的name相同--></span></span><br><span class="line"><span class="tag"><<span class="name">div</span> <span class="attr">class</span>=<span class="string">"editbrand floor"</span> <span class="attr">data</span>=<span class="string">"brand_sn"</span> <span class="attr">style</span>=<span class="string">"height: 535px;"</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">span</span> <span class="attr">class</span>=<span class="string">"cancel"</span>></span>×<span class="tag"></<span class="name">span</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">div</span>></span>品牌名称:<span class="tag"><<span class="name">input</span> <span class="attr">name</span>=<span class="string">"name"</span> <span class="attr">placeholder</span>=<span class="string">"输入品牌名称"</span> <span class="attr">type</span>=<span class="string">"text"</span> /></span><span class="tag"><<span class="name">input</span> <span class="attr">id</span>=<span class="string">"brand_seach"</span> <span class="attr">type</span>=<span class="string">"button"</span> <span class="attr">value</span>=<span class="string">"搜索"</span> <span class="attr">style</span>=<span class="string">"margin-left: 12px;"</span>/></span><span class="tag"></<span class="name">div</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">div</span>></span>注释:最多可选择4个品牌<span class="tag"></<span class="name">div</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">table</span> <span class="attr">border</span>=<span class="string">"1"</span> <span class="attr">bordercolor</span>=<span class="string">"#ddd"</span> <span class="attr">style</span>=<span class="string">"border-collapse: collapse;border-spacing: 0;"</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">thead</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">tr</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">th</span>></span>品牌编号<span class="tag"></<span class="name">th</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">th</span>></span>品牌名称<span class="tag"></<span class="name">th</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">th</span>></span>LOGO<span class="tag"></<span class="name">th</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">th</span>></span>操作<span class="tag"></<span class="name">th</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">tr</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">thead</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">tbody</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">volist</span> <span class="attr">name</span>=<span class="string">"brand"</span> <span class="attr">id</span>=<span class="string">"item"</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">tr</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">td</span>></span>{$item.brand_sn}<span class="tag"></<span class="name">td</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">td</span>></span>{$item.brand_name}<span class="tag"></<span class="name">td</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">td</span>></span><span class="tag"><<span class="name">img</span> <span class="attr">style</span>=<span class="string">"width: 100px;height: 30px"</span> <span class="attr">src</span>=<span class="string">"{$item.filepath}"</span> <span class="attr">alt</span>=<span class="string">""</span> /></span><span class="tag"></<span class="name">td</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">td</span>></span><span class="tag"><<span class="name">input</span> <span class="attr">onclick</span>=<span class="string">"selects(this, 'brand_sn', 4, '最多只能选择4个品牌')"</span> <span class="attr">value</span>=<span class="string">"{$item.brand_sn}"</span> <span class="attr">type</span>=<span class="string">"checkbox"</span> /></span><span class="tag"></<span class="name">td</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">tr</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">volist</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">tbody</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">table</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">div</span> <span class="attr">id</span>=<span class="string">"brand_page"</span>></span><span class="tag"></<span class="name">div</span>></span></span><br><span class="line"><span class="tag"></<span class="name">div</span>></span></span><br></pre></td></tr></table></figure><h4 id="1-2、javascript代码"><a href="#1-2、javascript代码" class="headerlink" title="1.2、javascript代码"></a>1.2、javascript代码</h4><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">//调用ajaxpage分页方法</span></span><br><span class="line">app =<span class="string">"__APP__"</span>;</span><br><span class="line">$(<span class="string">'#brand_page'</span>).ajaxPage({</span><br><span class="line"> pages:<span class="string">"<?php echo $brand_pages; ?>"</span>,</span><br><span class="line"> type: <span class="string">'brand'</span>,</span><br><span class="line">})</span><br><span class="line">$(<span class="string">'#product_page'</span>).ajaxPage({</span><br><span class="line"> pages:<span class="string">"<?php echo $product_pages; ?>"</span>,</span><br><span class="line"> type: <span class="string">'product'</span>,</span><br><span class="line">})</span><br><span class="line"></span><br><span class="line"><span class="comment">//如果有搜索的话,要有每页显示的条数</span></span><br><span class="line">number = <span class="string">"<?php echo $number; ?>"</span>;</span><br><span class="line">f_id = <span class="string">"<?php echo $_GET['f_id']==''?'0':$_GET['f_id']; ?>"</span>;</span><br></pre></td></tr></table></figure><h4 id="1-3、ajaxPage方法"><a href="#1-3、ajaxPage方法" class="headerlink" title="1.3、ajaxPage方法"></a>1.3、ajaxPage方法</h4><p> (需要根据具体情况需要更改)<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br><span class="line">133</span><br><span class="line">134</span><br><span class="line">135</span><br><span class="line">136</span><br><span class="line">137</span><br><span class="line">138</span><br><span class="line">139</span><br><span class="line">140</span><br><span class="line">141</span><br><span class="line">142</span><br><span class="line">143</span><br><span class="line">144</span><br><span class="line">145</span><br><span class="line">146</span><br><span class="line">147</span><br><span class="line">148</span><br><span class="line">149</span><br><span class="line">150</span><br><span class="line">151</span><br><span class="line">152</span><br><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br><span class="line">210</span><br><span class="line">211</span><br><span class="line">212</span><br><span class="line">213</span><br><span class="line">214</span><br><span class="line">215</span><br><span class="line">216</span><br><span class="line">217</span><br><span class="line">218</span><br><span class="line">219</span><br><span class="line">220</span><br><span class="line">221</span><br><span class="line">222</span><br><span class="line">223</span><br><span class="line">224</span><br><span class="line">225</span><br><span class="line">226</span><br><span class="line">227</span><br><span class="line">228</span><br><span class="line">229</span><br><span class="line">230</span><br><span class="line">231</span><br><span class="line">232</span><br><span class="line">233</span><br><span class="line">234</span><br><span class="line">235</span><br><span class="line">236</span><br><span class="line">237</span><br><span class="line">238</span><br><span class="line">239</span><br><span class="line">240</span><br><span class="line">241</span><br><span class="line">242</span><br><span class="line">243</span><br><span class="line">244</span><br><span class="line">245</span><br><span class="line">246</span><br><span class="line">247</span><br><span class="line">248</span><br><span class="line">249</span><br><span class="line">250</span><br><span class="line">251</span><br><span class="line">252</span><br><span class="line">253</span><br><span class="line">254</span><br><span class="line">255</span><br><span class="line">256</span><br><span class="line">257</span><br><span class="line">258</span><br><span class="line">259</span><br><span class="line">260</span><br><span class="line">261</span><br><span class="line">262</span><br><span class="line">263</span><br><span class="line">264</span><br><span class="line">265</span><br><span class="line">266</span><br><span class="line">267</span><br><span class="line">268</span><br><span class="line">269</span><br><span class="line">270</span><br><span class="line">271</span><br><span class="line">272</span><br><span class="line">273</span><br><span class="line">274</span><br><span class="line">275</span><br><span class="line">276</span><br><span class="line">277</span><br><span class="line">278</span><br><span class="line">279</span><br><span class="line">280</span><br><span class="line">281</span><br><span class="line">282</span><br><span class="line">283</span><br><span class="line">284</span><br><span class="line">285</span><br><span class="line">286</span><br><span class="line">287</span><br><span class="line">288</span><br></pre></td><td class="code"><pre><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * @param id 元素的id</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">style</span>(<span class="params">obj</span>) </span>{</span><br><span class="line"> <span class="comment">//所以a的样式</span></span><br><span class="line"> obj.children(<span class="string">'a'</span>).css({</span><br><span class="line"> <span class="string">'color'</span>: <span class="string">'#666'</span>,</span><br><span class="line"> <span class="string">'padding'</span>: <span class="string">'0 5px'</span>,</span><br><span class="line"> <span class="string">'text-decoration'</span>: <span class="string">'none'</span>,</span><br><span class="line"> <span class="string">'border'</span>: <span class="string">'1px solid #ccc'</span>,</span><br><span class="line"> <span class="string">'margin-left'</span>: <span class="string">'5px'</span>,</span><br><span class="line"> <span class="string">'display'</span>:<span class="string">'block'</span>,</span><br><span class="line"> <span class="string">'float'</span>: <span class="string">'left'</span>,</span><br><span class="line"> <span class="string">'min-width'</span>: <span class="string">'28px'</span>,</span><br><span class="line"> <span class="string">'text-align'</span>: <span class="string">'center'</span>,</span><br><span class="line"> }).attr({<span class="string">'href'</span>:<span class="string">'javascript:;'</span>,<span class="string">'data'</span>:<span class="string">'no_current'</span>});</span><br><span class="line"></span><br><span class="line"> <span class="comment">//第一个页码的样式</span></span><br><span class="line"> obj.children(<span class="string">'a[class=num]'</span>).first().css({<span class="string">'background'</span>: <span class="string">'#ff6200'</span>,<span class="string">'color'</span>: <span class="string">'#fff'</span>}).attr(<span class="string">'data'</span>,<span class="string">'current'</span>);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// obj.children('a[data=no_current]').mouseover(function () {</span></span><br><span class="line"> <span class="comment">// $(this).css({'background': '#ff6200','color': '#fff'})</span></span><br><span class="line"> <span class="comment">// }).mouseout(function () {</span></span><br><span class="line"> <span class="comment">// $(this).css({'background': '#fff','color': '#666'})</span></span><br><span class="line"> <span class="comment">// })</span></span><br><span class="line"></span><br><span class="line"></span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * @param pages 每页显示的条数</span></span><br><span class="line"><span class="comment"> * @param num 页码显示的数量</span></span><br><span class="line"><span class="comment"> * @param type 多次调用的类型区分</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line">$.fn.extend({</span><br><span class="line"> ajaxPage:<span class="function"><span class="keyword">function</span>(<span class="params">settings</span>) </span>{</span><br><span class="line"> <span class="comment">//设置参数默认值</span></span><br><span class="line"> <span class="comment">// var pages =13;</span></span><br><span class="line"> <span class="comment">// var num = 10;</span></span><br><span class="line"> <span class="keyword">var</span> defaultSetting={</span><br><span class="line"> pages:<span class="number">13</span>,</span><br><span class="line"> num:<span class="number">10</span>,</span><br><span class="line"> type:<span class="string">''</span>,</span><br><span class="line"> };</span><br><span class="line"> $.extend(defaultSetting,settings);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">var</span> pages = defaultSetting.pages;</span><br><span class="line"> <span class="keyword">var</span> num = defaultSetting.num;</span><br><span class="line"> <span class="keyword">var</span> type = defaultSetting.type;</span><br><span class="line"></span><br><span class="line"> <span class="comment">//分页页码</span></span><br><span class="line"> <span class="keyword">var</span> page = <span class="string">"<a class='prev'>上一页</a>"</span>;</span><br><span class="line"> <span class="keyword">if</span>(pages < num){</span><br><span class="line"> num = pages;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">for</span>(<span class="keyword">var</span> i=<span class="number">1</span>; i<=num; i++){</span><br><span class="line"> page += <span class="string">"<a class='num'>"</span>+i+<span class="string">"</a>"</span>;</span><br><span class="line"> }</span><br><span class="line"> page += <span class="string">"<a class='next'>下一页</a>"</span>;</span><br><span class="line"> page += <span class="string">"<span>共"</span>+pages+<span class="string">"页</span>"</span>;</span><br><span class="line"> <span class="keyword">var</span> obj = $(<span class="keyword">this</span>);</span><br><span class="line"> obj.html(page);</span><br><span class="line"></span><br><span class="line"> <span class="comment">//调用样式</span></span><br><span class="line"> style(obj);</span><br><span class="line"></span><br><span class="line"> <span class="comment">//每个页码的点击事件</span></span><br><span class="line"> obj.children(<span class="string">'a[class=num]'</span>).click(<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</span><br><span class="line"> <span class="comment">//获取当前的页码</span></span><br><span class="line"> <span class="keyword">var</span> current = <span class="built_in">parseInt</span>($(<span class="keyword">this</span>).html());</span><br><span class="line"> <span class="comment">//获取显示的第一个页码</span></span><br><span class="line"> <span class="keyword">var</span> first = <span class="built_in">parseInt</span>(obj.children(<span class="string">'a[class=num]'</span>).first().html());</span><br><span class="line"> <span class="comment">//获取显示的最后一个页码</span></span><br><span class="line"> <span class="keyword">var</span> last = <span class="built_in">parseInt</span>(obj.children(<span class="string">'a[class=num]'</span>).last().html());</span><br><span class="line"> <span class="comment">//获取中间的页码</span></span><br><span class="line"> <span class="keyword">var</span> middle = <span class="built_in">parseInt</span>((first+last)/<span class="number">2</span>);</span><br><span class="line"> <span class="comment">//当前索引</span></span><br><span class="line"> <span class="keyword">var</span> index = $(<span class="keyword">this</span>).index();</span><br><span class="line"> <span class="comment">//改变页码的样式</span></span><br><span class="line"> $(<span class="keyword">this</span>).css({<span class="string">'background'</span>: <span class="string">'#ff6200'</span>,<span class="string">'color'</span>: <span class="string">'#fff'</span>}).siblings(<span class="string">'a[class=num]'</span>).css({<span class="string">'background'</span>: <span class="string">'#fff'</span>,<span class="string">'color'</span>: <span class="string">'#666'</span>});</span><br><span class="line"> $(<span class="keyword">this</span>).attr(<span class="string">'data'</span>,<span class="string">'current'</span>).siblings().attr(<span class="string">'data'</span>,<span class="string">'no_current'</span>);</span><br><span class="line"> <span class="comment">//增加、减小页码,如果当前页码小于中间页码,所有值减一,反之。两个极值(最大、最小)</span></span><br><span class="line"> <span class="keyword">if</span>(last < pages){</span><br><span class="line"> <span class="keyword">if</span>(current > middle){</span><br><span class="line"> a_each(obj, <span class="string">'add'</span>, current)</span><br><span class="line"> }<span class="keyword">else</span>{</span><br><span class="line"> <span class="keyword">if</span>(first > <span class="number">1</span>){</span><br><span class="line"> a_each(obj, <span class="string">'reduce'</span>, current)</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }<span class="keyword">else</span> <span class="keyword">if</span>(last == pages && first > <span class="number">1</span> && current < middle){</span><br><span class="line"> a_each(obj, <span class="string">'reduce'</span>, current)</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">//请求数据</span></span><br><span class="line"> ajax_request(obj,current,type);</span><br><span class="line"></span><br><span class="line"> })</span><br><span class="line"></span><br><span class="line"> <span class="comment">//上一页、下一页</span></span><br><span class="line"> obj.find(<span class="string">'.prev,.next'</span>).mouseover(<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</span><br><span class="line"> $(<span class="keyword">this</span>).css({<span class="string">'background'</span>: <span class="string">'#ff6200'</span>,<span class="string">'color'</span>: <span class="string">'#fff'</span>});</span><br><span class="line"> }).click(<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</span><br><span class="line"> <span class="comment">//判断是上一页还是下一页</span></span><br><span class="line"> <span class="keyword">var</span> html_val = $(<span class="keyword">this</span>).html();</span><br><span class="line"> <span class="comment">//当前页码</span></span><br><span class="line"> <span class="keyword">var</span> current = <span class="built_in">parseInt</span>(obj.find(<span class="string">'a[data=current]'</span>).html());</span><br><span class="line"> <span class="comment">//获取显示的第一个页码</span></span><br><span class="line"> <span class="keyword">var</span> first = <span class="built_in">parseInt</span>(obj.children(<span class="string">'a[class=num]'</span>).first().html());</span><br><span class="line"> <span class="comment">//获取显示的最后一个页码</span></span><br><span class="line"> <span class="keyword">var</span> last = <span class="built_in">parseInt</span>(obj.children(<span class="string">'a[class=num]'</span>).last().html());</span><br><span class="line"> <span class="comment">//请求的页码</span></span><br><span class="line"> <span class="keyword">var</span> request_page = <span class="string">'1'</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span>(html_val == <span class="string">'上一页'</span> && current><span class="number">1</span>){</span><br><span class="line"> <span class="keyword">if</span>(first><span class="number">1</span>){</span><br><span class="line"> a_each(obj, <span class="string">'reduce'</span>, current<span class="number">-1</span>)</span><br><span class="line"> }<span class="keyword">else</span>{</span><br><span class="line"> a_each(obj, <span class="string">'reduce_end'</span>, current<span class="number">-1</span>)</span><br><span class="line"> }</span><br><span class="line"> request_page = current<span class="number">-1</span>;</span><br><span class="line"> }<span class="keyword">else</span> <span class="keyword">if</span>(html_val == <span class="string">'下一页'</span> && current<last){</span><br><span class="line"> <span class="keyword">if</span>(last<pages){</span><br><span class="line"> a_each(obj, <span class="string">'add'</span>, current+<span class="number">1</span>)</span><br><span class="line"> }<span class="keyword">else</span>{</span><br><span class="line"> a_each(obj, <span class="string">'add_end'</span>, current+<span class="number">1</span>)</span><br><span class="line"> }</span><br><span class="line"> request_page = current+<span class="number">1</span>;</span><br><span class="line"> }<span class="keyword">else</span>{</span><br><span class="line"> request_page = current;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">//请求数据</span></span><br><span class="line"> ajax_request(obj,request_page,type);</span><br><span class="line"> }).mouseout(<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</span><br><span class="line"> $(<span class="keyword">this</span>).css({<span class="string">'background'</span>: <span class="string">'#fff'</span>,<span class="string">'color'</span>: <span class="string">'#666'</span>});</span><br><span class="line"> })</span><br><span class="line"> }</span><br><span class="line">});</span><br><span class="line"><span class="comment">//a标签的遍历</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">a_each</span>(<span class="params">obj, mark, current</span>) </span>{</span><br><span class="line"> obj.children(<span class="string">'a[class=num]'</span>).each(<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> a_val = <span class="built_in">parseInt</span>($(<span class="keyword">this</span>).html());</span><br><span class="line"> <span class="keyword">if</span>(mark == <span class="string">'add'</span>){</span><br><span class="line"> $(<span class="keyword">this</span>).html(a_val+<span class="number">1</span>);</span><br><span class="line"> <span class="keyword">var</span> ack = a_val+<span class="number">1</span>;</span><br><span class="line"> }<span class="keyword">else</span> <span class="keyword">if</span>(mark == <span class="string">'reduce'</span>){</span><br><span class="line"> $(<span class="keyword">this</span>).html(a_val<span class="number">-1</span>);</span><br><span class="line"> <span class="keyword">var</span> ack = a_val<span class="number">-1</span>;</span><br><span class="line"> }<span class="keyword">else</span>{</span><br><span class="line"> <span class="keyword">var</span> ack = a_val;</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//改变页码的样式</span></span><br><span class="line"> <span class="keyword">if</span>(ack == current){</span><br><span class="line"> $(<span class="keyword">this</span>).attr(<span class="string">'data'</span>,<span class="string">'current'</span>).siblings().attr(<span class="string">'data'</span>,<span class="string">'no_current'</span>);</span><br><span class="line"> $(<span class="keyword">this</span>).css({<span class="string">'background'</span>: <span class="string">'#ff6200'</span>,<span class="string">'color'</span>: <span class="string">'#fff'</span>}).siblings(<span class="string">'a[class=num]'</span>).css({<span class="string">'background'</span>: <span class="string">'#fff'</span>,<span class="string">'color'</span>: <span class="string">'#666'</span>});</span><br><span class="line"> }</span><br><span class="line"> })</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">/*************************************以上是实现分页,下面是ajax请求数据**********************************/</span></span><br><span class="line"></span><br><span class="line"><span class="comment">//品牌的搜索</span></span><br><span class="line">$(<span class="string">'#brand_seach'</span>).click(<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> obj = $(<span class="string">'#brand_page'</span>);</span><br><span class="line"> ajax_request(obj,<span class="number">1</span>,<span class="string">'brand'</span>,<span class="literal">true</span>);</span><br><span class="line">})</span><br><span class="line"><span class="comment">//商品的搜索</span></span><br><span class="line">$(<span class="string">'#product_seach'</span>).click(<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> obj = $(<span class="string">'#product_page'</span>);</span><br><span class="line"> ajax_request(obj,<span class="number">1</span>,<span class="string">'product'</span>,<span class="literal">true</span>);</span><br><span class="line">})</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * @param obj 分页的DIV对象</span></span><br><span class="line"><span class="comment"> * @param page 当前的页码</span></span><br><span class="line"><span class="comment"> * @param type 多次调用的类型区分</span></span><br><span class="line"><span class="comment"> * @param seach 是否再次调用分页方法:false,不调用;true调用(默认:false)</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">ajax_request</span>(<span class="params">obj,page,type,seach</span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> seach = seach||<span class="literal">false</span>;</span><br><span class="line"> <span class="keyword">if</span>(type==<span class="string">'brand'</span>){</span><br><span class="line"> <span class="keyword">var</span> name = $(<span class="string">'input[name=name]'</span>).val();</span><br><span class="line"> <span class="keyword">var</span> data = {<span class="string">'type'</span>:<span class="string">'brand'</span>,<span class="string">'page'</span>:page,<span class="string">'name'</span>:name,<span class="string">'mf_id'</span>:mf_id,<span class="string">'seach'</span>:seach};</span><br><span class="line"> }<span class="keyword">else</span> <span class="keyword">if</span>(type==<span class="string">'product'</span>){</span><br><span class="line"> <span class="keyword">var</span> sn = $(<span class="string">'input[name=sn]'</span>).val();</span><br><span class="line"> <span class="keyword">var</span> product_name = $(<span class="string">'input[name=product_name]'</span>).val();</span><br><span class="line"> <span class="keyword">var</span> category = $(<span class="string">'input[name=category]'</span>).val();</span><br><span class="line"> <span class="keyword">var</span> brand_name = $(<span class="string">'input[name=brand_name]'</span>).val();</span><br><span class="line"> <span class="keyword">var</span> data = {<span class="string">'type'</span>:<span class="string">'product'</span>,<span class="string">'page'</span>:page,<span class="string">'sn'</span>:sn,<span class="string">'product_name'</span>:product_name,<span class="string">'category'</span>:category,<span class="string">'brand_name'</span>:brand_name,<span class="string">'mf_id'</span>:mf_id,<span class="string">'seach'</span>:seach};</span><br><span class="line"> }</span><br><span class="line"> $.ajax({</span><br><span class="line"> url:app+<span class="string">'/Home/Floor/first/'</span>,</span><br><span class="line"> data:data,</span><br><span class="line"> type:<span class="string">'post'</span>,</span><br><span class="line"> datatype:<span class="string">'json'</span>,</span><br><span class="line"> success:<span class="function"><span class="keyword">function</span> (<span class="params">response</span>) </span>{</span><br><span class="line"> <span class="comment">// console.log(response);</span></span><br><span class="line"> <span class="keyword">var</span> brand_html = <span class="string">''</span>;</span><br><span class="line"> <span class="comment">//返回的数据</span></span><br><span class="line"> <span class="keyword">var</span> response_result = response.response_result;</span><br><span class="line"> <span class="comment">//返回的数量</span></span><br><span class="line"> <span class="keyword">var</span> response_count = response.response_count;</span><br><span class="line"> <span class="comment">//填充数据</span></span><br><span class="line"> <span class="keyword">if</span>(type==<span class="string">'brand'</span>){</span><br><span class="line"> $.each(response_result,<span class="function"><span class="keyword">function</span> (<span class="params">index,object</span>) </span>{</span><br><span class="line"> brand_html += <span class="string">"<tr><td>"</span>+object.brand_sn+<span class="string">"</td><td>"</span>+object.brand_name+<span class="string">"</td><td><img style='height: 30px;width: 100px' src='"</span>+object.filepath+<span class="string">"' alt='"</span>+object.brand_name+<span class="string">"' /></td><td><input onclick=\"selects(this, 'brand_sn',4,'最多只能选择4个品牌')\" value='"</span>+object.brand_sn+<span class="string">"' type='checkbox' /></td></tr>"</span>;</span><br><span class="line"> })</span><br><span class="line"> }<span class="keyword">else</span> <span class="keyword">if</span>(type == <span class="string">'product'</span>){</span><br><span class="line"> $.each(response_result,<span class="function"><span class="keyword">function</span> (<span class="params">index,object</span>) </span>{</span><br><span class="line"> brand_html += <span class="string">"<tr><td>"</span>+object.id+<span class="string">"</td><td>"</span>+object.sn+<span class="string">"</td><td>"</span>+object.name+<span class="string">"</td><td><img style='width: 25px;height: 25px' src='"</span>+object.filepath+<span class="string">"' alt='"</span>+object.name+<span class="string">"'></td><td>"</span>+object.format+<span class="string">"</td><td>"</span>+object.cate_name+<span class="string">"</td><td>"</span>+object.brand_name+<span class="string">"</td><td><input onclick=\"selects(this, 'product_id', 8, '最多只能选择8个商品')\" value='"</span>+object.id+<span class="string">"' type='checkbox' /></td></tr>"</span>;</span><br><span class="line"> })</span><br><span class="line"> }</span><br><span class="line"> obj.siblings(<span class="string">'table'</span>).find(<span class="string">'tbody'</span>).html(brand_html);</span><br><span class="line"> <span class="comment">//调用选择的状态</span></span><br><span class="line"> select_status(obj)</span><br><span class="line"> <span class="comment">//搜索调用分页</span></span><br><span class="line"> <span class="keyword">if</span>(seach){</span><br><span class="line"> <span class="keyword">if</span>(response_count>number){</span><br><span class="line"> response_length = <span class="built_in">Math</span>.ceil(response_count/<span class="number">10</span>);</span><br><span class="line"> }<span class="keyword">else</span>{</span><br><span class="line"> response_length = <span class="number">1</span>;</span><br><span class="line"> }</span><br><span class="line"> obj.ajaxPage({</span><br><span class="line"> pages:response_length,</span><br><span class="line"> type:type,</span><br><span class="line"> })</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> })</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">/*************************************以上是ajax请求数据,下面是品牌、商品的挑选状态*****************************/</span></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * @param obj 分页的DIV对象</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">select_status</span>(<span class="params">obj</span>) </span>{</span><br><span class="line"> <span class="comment">// 获取选择的品牌</span></span><br><span class="line"> <span class="keyword">var</span> element_name = obj.parents(<span class="string">'.floor'</span>).attr(<span class="string">'data'</span>);</span><br><span class="line"> <span class="keyword">var</span> select_brand = $(<span class="string">'input[name='</span>+element_name+<span class="string">']'</span>).val();</span><br><span class="line"> <span class="keyword">if</span>(select_brand != <span class="string">''</span>){</span><br><span class="line"> select_brand = $.unique(select_brand.split(<span class="string">','</span>))</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> obj.siblings(<span class="string">'table'</span>).find(<span class="string">'input[type=checkbox]'</span>).each(<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> checkbox_val = $(<span class="keyword">this</span>).val();</span><br><span class="line"> <span class="keyword">if</span>($.inArray(checkbox_val, select_brand) != <span class="number">-1</span>){</span><br><span class="line"> <span class="comment">// console.log(checkbox_val)</span></span><br><span class="line"></span><br><span class="line"> $(<span class="keyword">this</span>).attr(<span class="string">'checked'</span>,<span class="string">'checked'</span>);</span><br><span class="line"> }</span><br><span class="line"> });</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"><span class="comment">/*************************************以上是ajax请求数据,下面是品牌、商品的挑选*****************************/</span></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * @param obj 分页的DIV对象</span></span><br><span class="line"><span class="comment"> * @param element_name 元素的名称(brand_sn|product_id)</span></span><br><span class="line"><span class="comment"> * @param max_num 元素element_name值的最大长度</span></span><br><span class="line"><span class="comment"> * @param message 如果element_name大于max_num时的提示信息</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">selects</span>(<span class="params">obj, element_name, max_num, message</span>)</span>{</span><br><span class="line"> <span class="comment">// 获取选择的品牌或者商品</span></span><br><span class="line"> <span class="keyword">var</span> select_elemet = $(<span class="string">'input[name='</span>+element_name+<span class="string">']'</span>).val();</span><br><span class="line"> <span class="keyword">if</span>(select_elemet == <span class="string">''</span>){</span><br><span class="line"> arrs = <span class="keyword">new</span> <span class="built_in">Array</span>();</span><br><span class="line"> }<span class="keyword">else</span>{</span><br><span class="line"> arrs = $.unique(select_elemet.split(<span class="string">','</span>))</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">var</span> select_value = $(obj).val();</span><br><span class="line"> <span class="keyword">if</span>($(obj).is(<span class="string">":checked"</span>) == <span class="literal">true</span>){</span><br><span class="line"> <span class="keyword">if</span>(arrs.length < max_num){</span><br><span class="line"> arrs.push(select_value);</span><br><span class="line"> }<span class="keyword">else</span>{</span><br><span class="line"> alert(message);</span><br><span class="line"> $(obj).removeAttr(<span class="string">'checked'</span>);</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">false</span>;</span><br><span class="line"> }</span><br><span class="line"> }<span class="keyword">else</span>{</span><br><span class="line"> <span class="keyword">if</span>($.inArray(select_value,arrs) != <span class="number">-1</span>){</span><br><span class="line"> arrs.splice($.inArray(select_value,arrs),<span class="number">1</span>);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">var</span> select_str = arrs.join(<span class="string">','</span>);</span><br><span class="line"> $(<span class="string">'input[name='</span>+element_name+<span class="string">']'</span>).val(select_str);</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><h4 id="1-4、PHP代码"><a href="#1-4、PHP代码" class="headerlink" title="1.4、PHP代码"></a>1.4、PHP代码</h4><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br></pre></td><td class="code"><pre><span class="line">$page = (int)$_POST[<span class="string">'page'</span>];</span><br><span class="line">$current = ($page<span class="number">-1</span>) * $number;</span><br><span class="line">$type = I(<span class="string">'post.type'</span>);</span><br><span class="line">$f_id = I(<span class="string">'post.f_id'</span>);</span><br><span class="line"></span><br><span class="line"><span class="keyword">if</span>($type==<span class="string">'brand'</span>){</span><br><span class="line"> $name = preg_replace(<span class="string">'# #'</span>,<span class="string">''</span>,$_POST[<span class="string">'name'</span>]);</span><br><span class="line"> $where[<span class="string">'brand_name'</span>] = <span class="keyword">array</span>(<span class="string">'like'</span>,$name.<span class="string">'%'</span>);</span><br><span class="line"> $result = $indexFloor->brand_all($where,$f_id);</span><br><span class="line">}<span class="keyword">elseif</span>($type==<span class="string">'product'</span>){</span><br><span class="line"> $sn = preg_replace(<span class="string">'# #'</span>,<span class="string">''</span>,$_POST[<span class="string">'sn'</span>]);</span><br><span class="line"> $product_name = preg_replace(<span class="string">'# #'</span>,<span class="string">''</span>,$_POST[<span class="string">'product_name'</span>]);</span><br><span class="line"> $category = preg_replace(<span class="string">'# #'</span>,<span class="string">''</span>,$_POST[<span class="string">'category'</span>]);</span><br><span class="line"> $brand_name = preg_replace(<span class="string">'# #'</span>,<span class="string">''</span>,$_POST[<span class="string">'brand_name'</span>]);</span><br><span class="line"> <span class="keyword">if</span>(!<span class="keyword">empty</span>($sn)){</span><br><span class="line"> $where[<span class="string">'p.sn'</span>] =$sn;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span>(!<span class="keyword">empty</span>($product_name)){</span><br><span class="line"> $where[<span class="string">'p.name'</span>] = <span class="keyword">array</span>(<span class="string">'like'</span>,$product_name.<span class="string">'%'</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span>(!<span class="keyword">empty</span>($category)){</span><br><span class="line"> $where[<span class="string">'cate.cat_id'</span>] = $category;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span>(!<span class="keyword">empty</span>($brand_name)){</span><br><span class="line"> $where[<span class="string">'brand.brand_name'</span>] = <span class="keyword">array</span>(<span class="string">'like'</span>,$brand_name.<span class="string">'%'</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> $result = $indexFloor->product_all($where,$f_id);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="comment">//返回数据</span></span><br><span class="line">$response_count = count($result);</span><br><span class="line">$response_result = array_splice($result, $current, $number);</span><br><span class="line">$response_data = <span class="keyword">array</span>(<span class="string">'response_count'</span>=>$response_count,<span class="string">'response_result'</span>=>$response_result);</span><br><span class="line"><span class="keyword">$this</span>->ajaxReturn($response_data);</span><br></pre></td></tr></table></figure><h2 id="2、基于ThinkPHP的多文件上传"><a href="#2、基于ThinkPHP的多文件上传" class="headerlink" title="2、基于ThinkPHP的多文件上传"></a>2、基于ThinkPHP的多文件上传</h2><h4 id="2-1、MyMoreUpload类的调用方法"><a href="#2-1、MyMoreUpload类的调用方法" class="headerlink" title="2.1、MyMoreUpload类的调用方法"></a>2.1、MyMoreUpload类的调用方法</h4><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">#upload方法的参数,只能是upload(更新)或者add(新增)</span></span><br><span class="line"><span class="keyword">require</span> <span class="string">'./ThinkPHP/Library/Org/MyMoreUpload.class.php'</span>;</span><br><span class="line">$files_mf[<span class="string">'mf_img'</span>] = $_FILES[<span class="string">'mf_img'</span>];</span><br><span class="line">$upload_mp = <span class="keyword">new</span> \MyMoreUpload($files_mf);</span><br><span class="line">$mf_res = $upload_mp->upload(<span class="string">'update'</span>);</span><br><span class="line"><span class="keyword">if</span>(!<span class="keyword">empty</span>($mf_res[<span class="number">0</span>])){</span><br><span class="line"> $data[<span class="string">'mf_img'</span>] = $mf_res[<span class="number">0</span>];</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h4 id="2-2、MyMoreUpload类"><a href="#2-2、MyMoreUpload类" class="headerlink" title="2.2、MyMoreUpload类"></a>2.2、MyMoreUpload类</h4><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br><span class="line">86</span><br><span class="line">87</span><br><span class="line">88</span><br><span class="line">89</span><br><span class="line">90</span><br><span class="line">91</span><br><span class="line">92</span><br><span class="line">93</span><br><span class="line">94</span><br><span class="line">95</span><br><span class="line">96</span><br><span class="line">97</span><br><span class="line">98</span><br><span class="line">99</span><br><span class="line">100</span><br><span class="line">101</span><br><span class="line">102</span><br><span class="line">103</span><br><span class="line">104</span><br><span class="line">105</span><br><span class="line">106</span><br><span class="line">107</span><br><span class="line">108</span><br><span class="line">109</span><br><span class="line">110</span><br><span class="line">111</span><br><span class="line">112</span><br><span class="line">113</span><br><span class="line">114</span><br><span class="line">115</span><br><span class="line">116</span><br><span class="line">117</span><br><span class="line">118</span><br><span class="line">119</span><br><span class="line">120</span><br><span class="line">121</span><br><span class="line">122</span><br><span class="line">123</span><br><span class="line">124</span><br><span class="line">125</span><br><span class="line">126</span><br><span class="line">127</span><br><span class="line">128</span><br><span class="line">129</span><br><span class="line">130</span><br><span class="line">131</span><br><span class="line">132</span><br></pre></td><td class="code"><pre><span class="line"><span class="meta"><?php</span></span><br><span class="line"> header(<span class="string">"Content-type: text/html; charset=utf-8"</span>);</span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * Auth:LiuShuaiCai</span></span><br><span class="line"><span class="comment"> * Class MyMoreUpload 适合多文件上传,单文件请用MyUpload</span></span><br><span class="line"><span class="comment"> * require './ThinkPHP/Library/Org/MyMoreUpload.class.php';</span></span><br><span class="line"><span class="comment"> * $files['mp_ing'] = $_FILES['mp_img'];</span></span><br><span class="line"><span class="comment"> * $upload=new \MyMoreUpload($files);</span></span><br><span class="line"><span class="comment"> * $mp_res=$upload->upload('add');</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * Param $files 传入的参数</span></span><br><span class="line"><span class="comment"> * Param $config 上传配置</span></span><br><span class="line"><span class="comment"> * Param $error 错误信息</span></span><br><span class="line"><span class="comment"> * Param $mark 标志:add->添加,update->更新</span></span><br><span class="line"><span class="comment"> * Param $sortfiles 整理后的数组</span></span><br><span class="line"><span class="comment"> * Param $_files 判断后的数组</span></span><br><span class="line"><span class="comment"> * Return Array $filepath 最后返回的图片路径</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">MyMoreUpload</span></span>{</span><br><span class="line"><span class="keyword">protected</span> $files = <span class="keyword">array</span>();</span><br><span class="line"><span class="keyword">protected</span> $config = <span class="keyword">array</span>();</span><br><span class="line"><span class="keyword">protected</span> $error = <span class="keyword">array</span>();</span><br><span class="line"><span class="keyword">protected</span> $mark = <span class="keyword">array</span>(<span class="string">'add'</span>,<span class="string">'update'</span>);</span><br><span class="line"><span class="keyword">protected</span> $sortfiles = <span class="keyword">array</span>();</span><br><span class="line"><span class="keyword">protected</span> $_files = <span class="keyword">array</span>();</span><br><span class="line"><span class="keyword">protected</span> $filepath = <span class="keyword">array</span>();</span><br><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__construct</span><span class="params">($files,$config=array<span class="params">()</span>)</span></span>{</span><br><span class="line"> <span class="keyword">if</span>(!<span class="keyword">empty</span>($files)){</span><br><span class="line"> <span class="keyword">$this</span>->files = $files;</span><br><span class="line"> }<span class="keyword">else</span>{</span><br><span class="line"> <span class="keyword">$this</span>->files = $_FILES;</span><br><span class="line"> }</span><br><span class="line"> </span><br><span class="line"> <span class="keyword">if</span>(!<span class="keyword">empty</span>($config)){</span><br><span class="line"> <span class="keyword">$this</span>->config = $config;</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//对多个上传的图片进行整理</span></span><br><span class="line"> <span class="keyword">foreach</span> (<span class="keyword">$this</span>->files <span class="keyword">as</span> $name=>$file) {</span><br><span class="line"> $count = count($file[<span class="string">'name'</span>]);</span><br><span class="line"> <span class="keyword">if</span>($count==<span class="number">1</span>){</span><br><span class="line"> $check = is_array($file[<span class="string">'name'</span>]);</span><br><span class="line"> <span class="keyword">if</span>($check){</span><br><span class="line"> <span class="keyword">for</span>($key=<span class="number">0</span>; $key<$count; $key++){</span><br><span class="line"> <span class="keyword">$this</span>->sortfiles[$name.$key] = <span class="keyword">array</span>(</span><br><span class="line"> <span class="string">'name'</span> => $file[<span class="string">'name'</span>][$key],</span><br><span class="line"> <span class="string">'type'</span> => $file[<span class="string">'type'</span>][$key],</span><br><span class="line"> <span class="string">'tmp_name'</span> => $file[<span class="string">'tmp_name'</span>][$key],</span><br><span class="line"> <span class="string">'error'</span> => $file[<span class="string">'error'</span>][$key],</span><br><span class="line"> <span class="string">'size'</span> => $file[<span class="string">'size'</span>][$key],</span><br><span class="line"> );</span><br><span class="line"> }</span><br><span class="line"> }<span class="keyword">else</span>{</span><br><span class="line"> <span class="keyword">$this</span>->sortfiles[$name] = $file;</span><br><span class="line"> }</span><br><span class="line"> }<span class="keyword">else</span>{</span><br><span class="line"> <span class="keyword">for</span>($key=<span class="number">0</span>; $key<$count; $key++){</span><br><span class="line"> <span class="keyword">$this</span>->sortfiles[$name.$key] = <span class="keyword">array</span>(</span><br><span class="line"> <span class="string">'name'</span> => $file[<span class="string">'name'</span>][$key],</span><br><span class="line"> <span class="string">'type'</span> => $file[<span class="string">'type'</span>][$key],</span><br><span class="line"> <span class="string">'tmp_name'</span> => $file[<span class="string">'tmp_name'</span>][$key],</span><br><span class="line"> <span class="string">'error'</span> => $file[<span class="string">'error'</span>][$key],</span><br><span class="line"> <span class="string">'size'</span> => $file[<span class="string">'size'</span>][$key],</span><br><span class="line"> );</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__call</span><span class="params">($function_name, $args)</span></span>{</span><br><span class="line"><span class="keyword">echo</span> <span class="string">"你所调用的函数:$function_name(参数:<br />"</span>;</span><br><span class="line"> var_dump($args);</span><br><span class="line"> <span class="keyword">echo</span> <span class="string">")不存在!"</span>;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">upload</span><span class="params">($mark)</span></span>{</span><br><span class="line">$mark=strtolower($mark);</span><br><span class="line"><span class="keyword">if</span>(!in_array($mark, <span class="keyword">$this</span>->mark)){</span><br><span class="line"><span class="keyword">echo</span> <span class="string">'函数参数为 add OR update,页面3秒后返回上一页'</span>;</span><br><span class="line"><span class="keyword">echo</span> <span class="string">'<script>setTimeout(function(){window.location="'</span>.$_SERVER[<span class="string">"HTTP_REFERER"</span>].<span class="string">'";},3000);</script>'</span>;</span><br><span class="line"><span class="keyword">die</span>;</span><br><span class="line">}</span><br><span class="line">$num = <span class="number">0</span>;</span><br><span class="line"><span class="comment">//dump($this->sortfiles);die;</span></span><br><span class="line"> <span class="keyword">foreach</span> (<span class="keyword">$this</span>->sortfiles <span class="keyword">as</span> $single_key=>$single_file){</span><br><span class="line"> $error=$single_file[<span class="string">'error'</span>];</span><br><span class="line"> <span class="keyword">if</span>($error!=<span class="number">0</span>){</span><br><span class="line"> <span class="keyword">if</span>($mark==<span class="string">'update'</span>){</span><br><span class="line"> <span class="keyword">$this</span>->filepath[$num] = <span class="string">''</span>;</span><br><span class="line"> }<span class="keyword">else</span>{</span><br><span class="line"> <span class="keyword">echo</span> <span class="string">"第{$num}张图片为空,上传失败,页面3秒后返回上一页"</span>;</span><br><span class="line"> <span class="keyword">echo</span> <span class="string">'<script>setTimeout(function(){window.location="'</span> . $_SERVER[<span class="string">"HTTP_REFERER"</span>] . <span class="string">'";},3000);</script>'</span>;</span><br><span class="line"> <span class="keyword">die</span>;</span><br><span class="line"><span class="comment">// $this->error[] = $error_message;</span></span><br><span class="line"><span class="comment">// $this->filepath[$num] = '';</span></span><br><span class="line"> }</span><br><span class="line"> }<span class="keyword">elseif</span>($error==<span class="number">0</span>){</span><br><span class="line"> <span class="keyword">$this</span>->_files[$num][$single_key] = $single_file;</span><br><span class="line"> }</span><br><span class="line"> $num ++;</span><br><span class="line"> }</span><br><span class="line"><span class="comment">// dump($this->error);</span></span><br><span class="line"><span class="comment">// dump($this->_files);</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span>(<span class="keyword">empty</span>(<span class="keyword">$this</span>->config)){</span><br><span class="line"> <span class="keyword">$this</span>->config=<span class="keyword">array</span>(</span><br><span class="line"> <span class="string">'maxSize'</span>=><span class="number">1024</span>*<span class="number">1024</span>*<span class="number">2</span>,</span><br><span class="line"> <span class="string">'exts'</span>=><span class="keyword">array</span>(<span class="string">'jpg'</span>, <span class="string">'gif'</span>, <span class="string">'png'</span>, <span class="string">'jpeg'</span>),</span><br><span class="line"> <span class="string">'rootPath'</span>=><span class="string">'./Public/Upload'</span>,</span><br><span class="line"> <span class="string">'savePath'</span>=><span class="string">'/siteadmin/Subject/'</span>,</span><br><span class="line"> <span class="string">'subName'</span>=><span class="keyword">array</span>(<span class="string">'date'</span>,<span class="string">'Ymd'</span>)</span><br><span class="line"> );</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">//实例化上传类</span></span><br><span class="line"> $upload=<span class="keyword">new</span> \Think\Upload(<span class="keyword">$this</span>->config);</span><br><span class="line"><span class="keyword">if</span>(!<span class="keyword">empty</span>(<span class="keyword">$this</span>->_files)) {</span><br><span class="line"> <span class="keyword">foreach</span> (<span class="keyword">$this</span>->_files <span class="keyword">as</span> $numkey=>$item) {</span><br><span class="line"> <span class="comment">//调用upload方法,上传文件</span></span><br><span class="line"> $info = $upload->upload($item);</span><br><span class="line"> $name = key($info);</span><br><span class="line"> <span class="keyword">if</span>($info){</span><br><span class="line"> <span class="keyword">$this</span>->filepath[$numkey] = <span class="string">'/Public/Upload'</span> . $info[$name][<span class="string">'savepath'</span>] . $info[$name][<span class="string">'savename'</span>];</span><br><span class="line"> }<span class="keyword">else</span>{</span><br><span class="line"> <span class="keyword">echo</span> <span class="string">'图片'</span>.$numkey.<span class="string">'上传失败:'</span>.$upload->getError().<span class="string">',页面3秒后返回上一页'</span>;</span><br><span class="line"> <span class="keyword">echo</span> <span class="string">'<script>setTimeout(function(){window.location="'</span> . $_SERVER[<span class="string">"HTTP_REFERER"</span>] . <span class="string">'";},3000);</script>'</span>;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"><span class="comment">// dump($this->filepath);</span></span><br><span class="line"><span class="comment">//返回文件路径</span></span><br><span class="line"><span class="keyword">return</span> <span class="keyword">$this</span>->filepath;</span><br><span class="line">}</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="3、对多维数组进行排序"><a href="#3、对多维数组进行排序" class="headerlink" title="3、对多维数组进行排序"></a>3、对多维数组进行排序</h2><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br></pre></td><td class="code"><pre><span class="line">$arrs = <span class="keyword">array</span>(</span><br><span class="line"><span class="string">'0'</span> => <span class="keyword">array</span>(</span><br><span class="line"><span class="string">'name'</span> => <span class="string">'Tom'</span>,</span><br><span class="line"><span class="string">'age'</span> => <span class="number">23</span>,</span><br><span class="line">),</span><br><span class="line"></span><br><span class="line"><span class="string">'1'</span> => <span class="keyword">array</span>(</span><br><span class="line"><span class="string">'name'</span> => <span class="string">'Tom'</span>,</span><br><span class="line"><span class="string">'age'</span> => <span class="number">20</span>,</span><br><span class="line">),</span><br><span class="line"></span><br><span class="line"><span class="string">'2'</span> => <span class="keyword">array</span>(</span><br><span class="line"><span class="string">'name'</span> => <span class="string">'Tom'</span>,</span><br><span class="line"><span class="string">'age'</span> => <span class="number">25</span>,</span><br><span class="line">),</span><br><span class="line">);</span><br><span class="line"></span><br><span class="line"><span class="keyword">foreach</span> ($arrs <span class="keyword">as</span> $key => $value) {</span><br><span class="line">$sort[$key] = $value[<span class="string">'age'</span>];</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">array_multisort($sort, SORT_DESC, $arrs);</span><br><span class="line"></span><br><span class="line"><span class="keyword">echo</span> <span class="string">"<pre>"</span>;</span><br><span class="line">print_r($arrs);</span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment">结果:</span></span><br><span class="line"><span class="comment">Array</span></span><br><span class="line"><span class="comment">(</span></span><br><span class="line"><span class="comment"> [0] => Array</span></span><br><span class="line"><span class="comment"> (</span></span><br><span class="line"><span class="comment"> [name] => Tom</span></span><br><span class="line"><span class="comment"> [age] => 25</span></span><br><span class="line"><span class="comment"> )</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment"> [1] => Array</span></span><br><span class="line"><span class="comment"> (</span></span><br><span class="line"><span class="comment"> [name] => Tom</span></span><br><span class="line"><span class="comment"> [age] => 23</span></span><br><span class="line"><span class="comment"> )</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment"> [2] => Array</span></span><br><span class="line"><span class="comment"> (</span></span><br><span class="line"><span class="comment"> [name] => Tom</span></span><br><span class="line"><span class="comment"> [age] => 20</span></span><br><span class="line"><span class="comment"> )</span></span><br><span class="line"><span class="comment"></span></span><br><span class="line"><span class="comment">)</span></span><br><span class="line"><span class="comment">**/</span></span><br></pre></td></tr></table></figure><p>附件:<br><a href="https://portal.qiniu.com/" target="_blank" rel="noopener">jquery.ajaxpage.js</a><br><a href="http://onx0p7mg5.bkt.clouddn.com/MyUpload.class.php?attname=" target="_blank" rel="noopener">MyMoreUpload.class.php</a><br><a href="http://onx0p7mg5.bkt.clouddn.com/MyUpload.class.php?attname=" target="_blank" rel="noopener">MyUpload.class.php</a></p>]]></content>
<summary type="html">
<p>终于闲下来了,趁此时间把三月份总结一下</p>
<h2 id="1、Ajax分页"><a href="#1、Ajax分页" class="headerlink" title="1、Ajax分页"></a>1、Ajax分页</h2><p>企业购的后台模板管理、楼层管理中用到的ajax分页(商品的选择、搜索),自己写了一下,还不是很完整,先记录一下(注:下面的数据都是修改过的,不会对我们的网站产生任何影响)。<br>
</summary>
<category term="前端" scheme="http://blog.feifan.news/categories/%E5%89%8D%E7%AB%AF/"/>
<category term="ajax分页" scheme="http://blog.feifan.news/tags/ajax%E5%88%86%E9%A1%B5/"/>
<category term="多文件上传" scheme="http://blog.feifan.news/tags/%E5%A4%9A%E6%96%87%E4%BB%B6%E4%B8%8A%E4%BC%A0/"/>
</entry>
<entry>
<title>学习 CGI 和 Fast CGI</title>
<link href="http://blog.feifan.news/2017/04/10/cgi/"/>
<id>http://blog.feifan.news/2017/04/10/cgi/</id>
<published>2017-04-10T03:47:32.000Z</published>
<updated>2022-02-28T23:30:06.544Z</updated>
<content type="html"><![CDATA[<h2 id="1、了解CGI"><a href="#1、了解CGI" class="headerlink" title="1、了解CGI"></a>1、了解CGI</h2><p>CGI(Common Gateway Interface):通用网关接口<br>CGI应用是通过标准的POSIX流(stdin,stdout,stderr和环境变量)加上环境变量,来与HTTP服务器进行通信。<br>功能:绝大数的cgi程序被用来解释、处理来自表单的输入信息,在服务器产生相应的信息的处理,或将相应的信息反馈给浏览器。<br><a id="more"></a></p><h4 id="1-1、工作原理:"><a href="#1-1、工作原理:" class="headerlink" title="1.1、工作原理:"></a>1.1、工作原理:</h4><p>(1)浏览器通过HTML表单或者超链接请求指向一个CGI应用程序的UTL<br>(2)web服务器接收用户请求并交给CGI程序处理,包括查询数据库、计算数值或调用系统中其他程序<br>(3)CGI程序把处理结果传送给web服务器<br>(4)web服务器把结果返回给用户</p><h4 id="1-2、环境变量列表"><a href="#1-2、环境变量列表" class="headerlink" title="1.2、环境变量列表"></a>1.2、环境变量列表</h4><ul><li>SERVER_NAME:运行CGI序为机器名或IP地址。</li><li>SERVER_INTERFACE:WWW服务器的类型,如:CERN型或NCSA型。</li></ul><ul><li>SERVER_PROTOCOL:通信协议,应当是HTTP/1.0。</li><li>SERVER_PORT:TCP端口,一般说来web端口是80。</li><li>HTTP_ACCEPT:HTTP定义的浏览器能够接受的数据类型。</li></ul><ul><li>HTTP_REFERER:发送表单的文件URL。(并非所有的浏览器都传送这一变量)</li><li>HTTP_USER-AGENT:发送表单的浏览的有关信息。</li></ul><ul><li>GETWAY_INTERFACE:CGI程序的版本,在UNIX下为 CGI/1.1。</li><li>PATH_TRANSLATED:PATH_INFO中包含的实际路径名。</li><li>PATH_INFO:浏览器用GET方式发送数据时的附加路径。</li><li>SCRIPT_NAME:CGI程序的路径名。</li><li>QUERY_STRING:表单输入的数据,URL中问号后的内容。</li><li>REMOTE_HOST:发送程序的主机名,不能确定该值。</li><li>REMOTE_ADDR:发送程序的机器的IP地址。</li></ul><ul><li>REMOTE_USER:发送程序的人名。</li><li>CONTENT_TYPE:POST发送,一般为application/xwww-form-urlencoded。</li></ul><ul><li>CONTENT_LENGTH:POST方法输入的数据的字节数。<br>结构图如下:<br><img src="http://onx0p7mg5.bkt.clouddn.com/cgi.jpg" alt="cgi"><br>每当客户请求CGI的时候,WEB服务器就请求操作系统生成一个新的CGI解释器进程(如php-cgi.exe),CGI 的一个进程则处理完一个请求后退出,下一个请求来时再创建新进程。当然,这样在访问量很少没有并发的情况也行。可是当访问量增大,并发存在,这种方式就不 适合了。于是就有了fastcgi</li></ul><h2 id="2、了解Fast-CGI"><a href="#2、了解Fast-CGI" class="headerlink" title="2、了解Fast CGI"></a>2、了解Fast CGI</h2><p>FastCGI像是一个常驻(long-live)型的CGI,它可以一直执行着,只要激活后,不会每次都要花费时间去fork一次(这是CGI最为人诟病的fork-and-execute 模式)</p><h4 id="2-1、Fast-CGI原理"><a href="#2-1、Fast-CGI原理" class="headerlink" title="2.1、Fast CGI原理"></a>2.1、Fast CGI原理</h4><p>1、Web Server启动时载入FastCGI进程管理器(IIS ISAPI或Apache Module)<br>2、FastCGI进程管理器自身初始化,启动多个CGI解释器进程(可见多个php-cgi)并等待来自Web Server的连接。<br>3、当客户端请求到达Web Server时,FastCGI进程管理器选择并连接到一个CGI解释器。Web server将CGI环境变量和标准输入发送到FastCGI子进程php-cgi。<br>4、FastCGI子进程完成处理后将标准输出和错误信息从同一连接返回Web Server。当FastCGI子进程关闭连接时,请求便告处理完成。FastCGI子进程接着等待并处理来自FastCGI进程管理器(运行在Web Server中)的下一个连接。 在CGI模式中,php-cgi在此便退出了。</p><h4 id="2-2、缺点"><a href="#2-2、缺点" class="headerlink" title="2.2、缺点"></a>2.2、缺点</h4><p>Fast CGI因为是多进程,所以比CGI多线程消耗更多的服务器内存</p>]]></content>
<summary type="html">
<h2 id="1、了解CGI"><a href="#1、了解CGI" class="headerlink" title="1、了解CGI"></a>1、了解CGI</h2><p>CGI(Common Gateway Interface):通用网关接口<br>CGI应用是通过标准的POSIX流(stdin,stdout,stderr和环境变量)加上环境变量,来与HTTP服务器进行通信。<br>功能:绝大数的cgi程序被用来解释、处理来自表单的输入信息,在服务器产生相应的信息的处理,或将相应的信息反馈给浏览器。<br>
</summary>
<category term="PHP" scheme="http://blog.feifan.news/categories/PHP/"/>
<category term="CGI" scheme="http://blog.feifan.news/tags/CGI/"/>
</entry>
<entry>
<title>实际项目中的常用的JS函数总结</title>
<link href="http://blog.feifan.news/2017/04/09/js-func/"/>
<id>http://blog.feifan.news/2017/04/09/js-func/</id>
<published>2017-04-09T15:50:35.000Z</published>
<updated>2019-05-06T15:38:02.751Z</updated>
<content type="html"><![CDATA[<h2 id="1、JS去除所有的空格"><a href="#1、JS去除所有的空格" class="headerlink" title="1、JS去除所有的空格"></a>1、JS去除所有的空格</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">replace(<span class="regexp">/\s+/g</span>,<span class="string">''</span>);</span><br></pre></td></tr></table></figure><a id="more"></a><p>\s:匹配任何不可见字符,空格、制表符、换页符等等,相当于[ \f\n\r\t\v]。<br>g:全局匹配</p><h2 id="2、JS检查一个字符串中知否包含另一个字符串"><a href="#2、JS检查一个字符串中知否包含另一个字符串" class="headerlink" title="2、JS检查一个字符串中知否包含另一个字符串"></a>2、JS检查一个字符串中知否包含另一个字符串</h2><h4 id="2-1、test查找"><a href="#2-1、test查找" class="headerlink" title="2.1、test查找"></a>2.1、test查找</h4><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> patt = <span class="keyword">new</span> <span class="built_in">RegExp</span>(<span class="string">'hello'</span>); <span class="comment">//or var patt = /hello/; 要查找的字符串</span></span><br><span class="line"><span class="keyword">var</span> str = <span class="string">'hello world'</span>; <span class="comment">//在str中查找</span></span><br><span class="line"><span class="keyword">var</span> bool = patt.test(str); <span class="comment">//返回值</span></span><br></pre></td></tr></table></figure><h4 id="2-2、exec查找"><a href="#2-2、exec查找" class="headerlink" title="2.2、exec查找"></a>2.2、exec查找</h4><p>exec() 返回第一个匹配的值,和test一样<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> str = <span class="string">'hello world'</span>;</span><br><span class="line"><span class="keyword">var</span> patt = <span class="regexp">/hello/g</span>;</span><br><span class="line"><span class="keyword">var</span> array = patt.exec(str); <span class="comment">//返回数组</span></span><br></pre></td></tr></table></figure></p><h4 id="2-3、match查找"><a href="#2-3、match查找" class="headerlink" title="2.3、match查找"></a>2.3、match查找</h4><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> str = <span class="string">'hello world'</span>;</span><br><span class="line"><span class="keyword">var</span> patt = <span class="regexp">/hello/g</span>;</span><br><span class="line"><span class="keyword">var</span> array = str.match(patt); <span class="comment">//返回数组</span></span><br></pre></td></tr></table></figure><h4 id="2-4、search查找"><a href="#2-4、search查找" class="headerlink" title="2.4、search查找"></a>2.4、search查找</h4><p>Search()返回与正则表达式查找内容匹配的第一个子字符串的位置(偏移位)<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> str = <span class="string">'hello world'</span>;</span><br><span class="line"><span class="keyword">var</span> res = str.search(<span class="string">'world'</span>); <span class="comment">//res=6</span></span><br><span class="line"><span class="keyword">var</span> res = str.search(<span class="regexp">/world/g</span>); <span class="comment">//res=1</span></span><br></pre></td></tr></table></figure></p><p>用正则匹配和用字符串搜索的结果可能会不一样</p><h4 id="2-5、indexOf查找"><a href="#2-5、indexOf查找" class="headerlink" title="2.5、indexOf查找"></a>2.5、indexOf查找</h4><p>indexOf()返回某个指定的字符串值在字符串中首次出现的位置。如果没有则返回-1<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> str = <span class="string">'Hello world, welcome to the universe.'</span>;</span><br><span class="line"><span class="keyword">var</span> n = str.indexOf(<span class="string">'welcome'</span>); <span class="comment">//n=13</span></span><br></pre></td></tr></table></figure></p><h2 id="3、JS割成字符串"><a href="#3、JS割成字符串" class="headerlink" title="3、JS割成字符串"></a>3、JS割成字符串</h2><p>函数:split() 将字符串分割成数组<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> str = <span class="string">'hello world php'</span>;</span><br><span class="line"><span class="keyword">var</span> arr = str.split(<span class="string">' '</span>); <span class="comment">//用指定字符分割</span></span><br><span class="line"><span class="keyword">var</span> arr2 = str.split(<span class="string">'/\s+/g'</span>) <span class="comment">//用正则分割</span></span><br></pre></td></tr></table></figure></p><h2 id="4、JS页面跳转刷新"><a href="#4、JS页面跳转刷新" class="headerlink" title="4、JS页面跳转刷新"></a>4、JS页面跳转刷新</h2><h4 id="4-1、页面跳转"><a href="#4-1、页面跳转" class="headerlink" title="4.1、页面跳转"></a>4.1、页面跳转</h4><pre><code>前进:history.go(1) 后退:history.go(-1) or history.back() //只返回,不刷新返回并刷新页面:location.replace(document.referrer); document.referrer //前一个页面的URL</code></pre><h4 id="4-2、页面刷新"><a href="#4-2、页面刷新" class="headerlink" title="4.2、页面刷新"></a>4.2、页面刷新</h4><p>1、js刷新</p><pre><code>刷新:history.go(0) or window.location.reload();</code></pre><p>2、页面自动刷新:把如下代码加入<head><meta name="generator" content="Hexo 3.8.0">区域中</head></p><pre><code><meta http-equiv="refresh" content="20"><meta http-equiv="refresh" content="20;url=http://www.baidu.com"></code></pre><p>3、JS刷新框架的脚本语句 </p><pre><code>//刷新包含该框架的页面用 <script language=JavaScript> parent.location.reload();</script>//子窗口刷新父窗口<script language=JavaScript> self.opener.location.reload();</script>( 或 <a href="javascript:opener.location.reload()">刷新</a> )//刷新另一个框架的页面用 <script language=JavaScript> parent.另一FrameID.location.reload();</script></code></pre><h2 id="5、JS打开页面自动跳到锚点"><a href="#5、JS打开页面自动跳到锚点" class="headerlink" title="5、JS打开页面自动跳到锚点"></a>5、JS打开页面自动跳到锚点</h2> <figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="built_in">window</span>.onload=<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{</span><br><span class="line"> location.hash=<span class="string">'你锚点的名称'</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="6、JS判断多选框是否被选中"><a href="#6、JS判断多选框是否被选中" class="headerlink" title="6、JS判断多选框是否被选中"></a>6、JS判断多选框是否被选中</h2><pre><code>if ($(“#checkbox-id”)get(0).checked) { // do something}if($(‘#checkbox-id’).is(‘:checked’)) { // do something}if ($(‘#checkbox-id’).attr(‘checked’)) { // do something}</code></pre>]]></content>
<summary type="html">
<h2 id="1、JS去除所有的空格"><a href="#1、JS去除所有的空格" class="headerlink" title="1、JS去除所有的空格"></a>1、JS去除所有的空格</h2><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">replace(<span class="regexp">/\s+/g</span>,<span class="string">''</span>);</span><br></pre></td></tr></table></figure>
</summary>
<category term="前端" scheme="http://blog.feifan.news/categories/%E5%89%8D%E7%AB%AF/"/>
<category term="JS" scheme="http://blog.feifan.news/tags/JS/"/>
</entry>
<entry>
<title>Mysql的sql分析(explain|profile)</title>
<link href="http://blog.feifan.news/2017/04/05/mysql-explain-profile/"/>
<id>http://blog.feifan.news/2017/04/05/mysql-explain-profile/</id>
<published>2017-04-05T13:44:51.000Z</published>
<updated>2019-05-06T15:38:02.761Z</updated>
<content type="html"><![CDATA[<h3 id="1、Explain详解"><a href="#1、Explain详解" class="headerlink" title="1、Explain详解"></a>1、Explain详解</h3><p>explain 显示了Mysql如何使用索引处理select语句以及连接表。通过explain分析可以更好的选择索引,优化select语句。<a id="more"></a><br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br></pre></td><td class="code"><pre><span class="line">mysql> explain SELECT pre_products.id,pre_products.name,pre_product_pictures.filepath,pre_product_spec.rate_profit,pre_product_spec.purchase_price,pre_product_config.moq FROM `pre_products` INNER JOIN</span><br><span class="line"> pre_product_config ON pre_products.id = pre_product_config.product_id INNER JOIN pre_product_spec ON pre_products.id = pre_product_spec.product_id INNER JOIN pre_product_pictures ON pre_products.id =</span><br><span class="line"> pre_product_pictures.product_id INNER JOIN pre_product_categorys ON pre_products.id = pre_product_categorys.product_id WHERE pre_product_pictures.type = 1 AND pre_products.status = 2 AND pre_products</span><br><span class="line">.id IN ('374','378','385','386','387','388','389','390') AND ( pre_product_config.moq=pre_product_spec.lower_limit ) GROUP BY pre_products.id ORDER BY id;</span><br><span class="line">+----+-------------+-----------------------+-------+-------------------------+--------------+---------+--------------------------+------+--------------------------+</span><br><span class="line">| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |</span><br><span class="line">+----+-------------+-----------------------+-------+-------------------------+--------------+---------+--------------------------+------+--------------------------+</span><br><span class="line">| 1 | SIMPLE | pre_products | range | PRIMARY | PRIMARY | 3 | NULL | 8 | Using where |</span><br><span class="line">| 1 | SIMPLE | pre_product_config | ref | product_id,moq | product_id | 5 | qiyegood.pre_products.id | 1 | Using where |</span><br><span class="line">| 1 | SIMPLE | pre_product_categorys | ref | product_id_2,product_id | product_id_2 | 4 | qiyegood.pre_products.id | 1 | Using where; Using index |</span><br><span class="line">| 1 | SIMPLE | pre_product_pictures | ref | product_id | product_id | 4 | qiyegood.pre_products.id | 4 | Using where |</span><br><span class="line">| 1 | SIMPLE | pre_product_spec | ref | product_id | product_id | 5 | qiyegood.pre_products.id | 4 | Using where |</span><br><span class="line">+----+-------------+-----------------------+-------+-------------------------+--------------+---------+--------------------------+------+--------------------------+</span><br><span class="line">5 rows in set (0.00 sec)</span><br></pre></td></tr></table></figure></p><h4 id="1-1、每一列的意思"><a href="#1-1、每一列的意思" class="headerlink" title="1.1、每一列的意思"></a>1.1、每一列的意思</h4><p>id:MySQL Query Optimizer 选定的执行计划中查询的序列号。表示查询中执行 select 子句或操作表的顺序,id值越大优先级越高,越先被执行。id 相同,执行顺序由上至下。<br>select_type:查询的类型</p><div class="table-container"><table><thead><tr><th style="text-align:left">类型</th><th style="text-align:left">说明</th></tr></thead><tbody><tr><td style="text-align:left">SIMPLE</td><td style="text-align:left">简单的 select 查询,不使用 union 及子查询</td></tr><tr><td style="text-align:left">PRIMARY</td><td style="text-align:left">最外层的 select 查询</td></tr><tr><td style="text-align:left">UNION UNION</td><td style="text-align:left">中的第二个或随后的 select 查询,不 依赖于外部查询的结果集</td></tr><tr><td style="text-align:left">DEPENDENT UNION</td><td style="text-align:left">UNION 中的第二个或随后的 select 查询,依 赖于外部查询的结果集</td></tr><tr><td style="text-align:left">SUBQUERY</td><td style="text-align:left">子查询中的第一个 select 查询,不依赖于外 部查询的结果集</td></tr><tr><td style="text-align:left">DEPENDENT SUBQUERY</td><td style="text-align:left">子查询中的第一个 select 查询,依赖于外部 查询的结果集</td></tr><tr><td style="text-align:left">DERIVED</td><td style="text-align:left">用于 from 子句里有子查询的情况。 MySQL 会 递归执行这些子查询, 结果放在临时表里。</td></tr><tr><td style="text-align:left">UNCACHEABLE SUBQUERY</td><td style="text-align:left">结果集不能被缓存的子查询,必须重新为外 层查询的每一行进行评估。</td></tr><tr><td style="text-align:left">UNCACHEABLE UNION</td><td style="text-align:left">UNION 中的第二个或随后的 select 查询,属 于不可缓存的子查询</td></tr></tbody></table></div><p>table:输出行所引用的表<br>type:显示连接使用的类型,按照从最优到最差的类型排序 </p><div class="table-container"><table><thead><tr><th style="text-align:left">类型</th><th style="text-align:left">说明</th></tr></thead><tbody><tr><td style="text-align:left">System</td><td style="text-align:left">表仅有一行(=系统表)。这是 const 连接类型的一个特例。</td></tr><tr><td style="text-align:left">const</td><td style="text-align:left">const 用于用常数值比较 PRIMARY KEY 时。当 查询的表仅有一行时,使用 System。</td></tr><tr><td style="text-align:left">eq_ref</td><td style="text-align:left">const 用于用常数值比较 PRIMARY KEY 时。当 查询的表仅有一行时,使用System。</td></tr><tr><td style="text-align:left">ref</td><td style="text-align:left">连接不能基于关键字选择单个行,可能查找到多个符合条件的行。叫做ref是因为索引要跟某个参考值相比较。这个参考值或者是一 个常数,或者是来自一个表里的多表查询的 结果值</td></tr><tr><td style="text-align:left">ref_or_null</td><td style="text-align:left">如同 ref, 但是 MySQL 必须在初次查找的结果 里找出 null 条目,然后进行二次查找。</td></tr><tr><td style="text-align:left">index_merge</td><td style="text-align:left">说明索引合并优化被使用了。</td></tr><tr><td style="text-align:left">unique_subquery</td><td style="text-align:left">在某些 IN 查询中使用此种类型,而不是常规的 ref:value IN (SELECT primary_key FROM single_table WHERE some_expr)</td></tr><tr><td style="text-align:left">index_subquery</td><td style="text-align:left">在 某 些 IN 查 询 中 使 用 此 种 类 型 , 与 unique_subquery类似,但是查询的是非唯一 性索引: value IN (SELECT key_column FROM single_table WHERE some_expr)</td></tr><tr><td style="text-align:left">range</td><td style="text-align:left">只检索给定范围的行,使用一个索引来选择 行。key 列显示使用了哪个索引。当使用=、<>、>、>=、<、<=、IS NULL、<=>、BETWEEN 或者 IN操作符,用常量比较关键字列时,可 以使用 range。</td></tr><tr><td style="text-align:left">index</td><td style="text-align:left">全表扫描,只是扫描表的时候按照索引次序 进行而不是行。主要优点就是避免了排序, 但是开销仍然非常大。</td></tr><tr><td style="text-align:left">all</td><td style="text-align:left">最坏的情况,从头到尾全表扫描。</td></tr></tbody></table></div><p>possible_keys:指出Mysql能在该表中使用哪些索引有助于查询,如果为空,说明没有可用的索引<br>key:MySQL 实际从 possible_key 选择使用的索引。 如果为 NULL,则没有使用索引。很少的情况 下,MYSQL会选择优化不足的索引。这种情 况下,可以在 SELECT 语句中使用 USE INDEX (indexname)来强制使用一个索引或者用IGNORE INDEX(indexname)来强制 MYSQL 忽略索引。<br>key_len:使用的索引的长度。在不损失精确性的情况 下,长度越短越好。<br>ref:显示索引的哪一列被使用了。<br>rows:MYSQL 认为必须检查的用来返回请求数据的行数。<br>Extra:extra 中出现以下 2 项意味着 MYSQL 根本不能使用索引,效率会受到重大影响。应尽可能对此进行优化。</p><div class="table-container"><table><thead><tr><th style="text-align:left">extra项</th><th style="text-align:left">说明</th></tr></thead><tbody><tr><td style="text-align:left">Using filesort</td><td style="text-align:left">表示MySQL会对结果使用一个外部索引排序,而不是从表里按索引次序读到相关内容。可能在内存或者磁盘上进行排序。MySQL 中无法利用索引完成的排序操作称为“文件排序”</td></tr><tr><td style="text-align:left">Using temporary</td><td style="text-align:left">表示MySQL在对查询结果排序时使用临时表。常见于排序 order by 和分组查询 group by。</td></tr></tbody></table></div><pre><code>注意点:1、join语句的使用,永远用小结果集驱动大结果集。2、仔细分析上面字段的类型。</code></pre><h3 id="2、压力测试"><a href="#2、压力测试" class="headerlink" title="2、压力测试"></a>2、压力测试</h3><p>压力测试<a href>select benchmark(count,sql)</a>;计算sql语句执行count次所花费的时间<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br></pre></td><td class="code"><pre><span class="line">mysql> select benchmark(1000000000,"select count(*) from pre_templet_floor");</span><br><span class="line">+----------------------------------------------------------------+</span><br><span class="line">| benchmark(1000000000,"select count(*) from pre_templet_floor") |</span><br><span class="line">+----------------------------------------------------------------+</span><br><span class="line">| 0 |</span><br><span class="line">+----------------------------------------------------------------+</span><br><span class="line">1 row in set (4.63 sec)</span><br><span class="line"></span><br><span class="line">mysql> select count(*) from pre_templet_floor;</span><br><span class="line">+----------+</span><br><span class="line">| count(*) |</span><br><span class="line">+----------+</span><br><span class="line">| 27 |</span><br><span class="line">+----------+</span><br><span class="line">1 row in set (0.00 sec)</span><br></pre></td></tr></table></figure></p><h3 id="3、Profile详解"><a href="#3、Profile详解" class="headerlink" title="3、Profile详解"></a>3、Profile详解</h3><p>profile用于查看一个sql的具体消耗。</p><h4 id="3-1、查看profile是否开启,默认为关闭"><a href="#3-1、查看profile是否开启,默认为关闭" class="headerlink" title="3.1、查看profile是否开启,默认为关闭"></a>3.1、查看profile是否开启,默认为关闭</h4><p>方法一:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">mysql> select @@profiling;</span><br><span class="line">+-------------+</span><br><span class="line">| @@profiling |</span><br><span class="line">+-------------+</span><br><span class="line">| 0 | --0为关闭,1为开启</span><br><span class="line">+-------------+</span><br><span class="line">1 row in set (0.00 sec)</span><br></pre></td></tr></table></figure></p><p>方法二:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">mysql> show variables like '%profil%';</span><br><span class="line">+------------------------+-------+</span><br><span class="line">| Variable_name | Value |</span><br><span class="line">+------------------------+-------+</span><br><span class="line">| have_profiling | YES | --只读变量,用于控制是否由系统变量开启或禁用profiling </span><br><span class="line">| profiling | OFF | --开启SQL语句剖析功能 </span><br><span class="line">| profiling_history_size | 15 | --设置保留profiling的数目,缺省为15,范围为0至100,为0时将禁用profiling </span><br><span class="line">+------------------------+-------+</span><br><span class="line">3 rows in set (0.00 sec)</span><br></pre></td></tr></table></figure></p><h4 id="3-2、开启profile"><a href="#3-2、开启profile" class="headerlink" title="3.2、开启profile"></a>3.2、开启profile</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">mysql> set profiling=1;</span><br><span class="line">Query OK, 0 rows affected (0.00 sec)</span><br></pre></td></tr></table></figure><p>查看profile的状态(已经开启)<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">mysql> select @@profiling;</span><br><span class="line">+-------------+</span><br><span class="line">| @@profiling |</span><br><span class="line">+-------------+</span><br><span class="line">| 1 |</span><br><span class="line">+-------------+</span><br><span class="line">1 row in set (0.00 sec)</span><br></pre></td></tr></table></figure></p><h4 id="3-3、profile具体操作"><a href="#3-3、profile具体操作" class="headerlink" title="3.3、profile具体操作"></a>3.3、profile具体操作</h4><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br></pre></td><td class="code"><pre><span class="line">mysql> show profiles;</span><br><span class="line">+----------+--------------+---------------------------------------------------+</span><br><span class="line">| Query_ID | Duration | Query |</span><br><span class="line">+----------+--------------+---------------------------------------------------+</span><br><span class="line">| 57 | 0.00070650 | select count(*) from pre_templet_loor |</span><br><span class="line">+----------+--------------+---------------------------------------------------+</span><br><span class="line">1 rows in set (0.00 sec)</span><br></pre></td></tr></table></figure><p>type的类型有一下9种:</p><pre><code>ALL:显示所有性能信息。BLOCK IO:显示块IO(块的输入输出)的次数。CONTEXT SWITCHES:显示自动和被动的上下文切换数量。CPU:显示用户和系统的CPU使用情况。IPC:显示发送和接收的消息数量。MEMORY:MySQL5.6中还未实现,只是计划实现。PAGE FAULTS:显示主要的和次要的页面故障。SOURCE:显示源代码的函数名称,以及在源码文件名称与行数(即源码中的位置)。SWAPS:显示swap的次数。 </code></pre><p>具体分析上面的SQL语句:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br></pre></td><td class="code"><pre><span class="line">mysql> show profile for query 57;</span><br><span class="line">+----------------------+----------+</span><br><span class="line">| Status | Duration |</span><br><span class="line">+----------------------+----------+</span><br><span class="line">| starting | 0.000060 |</span><br><span class="line">| checking permissions | 0.000007 |</span><br><span class="line">| Opening tables | 0.000275 |</span><br><span class="line">| System lock | 0.000008 |</span><br><span class="line">| init | 0.000009 |</span><br><span class="line">| optimizing | 0.000003 |</span><br><span class="line">| statistics | 0.000008 |</span><br><span class="line">| preparing | 0.000005 |</span><br><span class="line">| executing | 0.000003 |</span><br><span class="line">| Sending data | 0.000056 |</span><br><span class="line">| end | 0.000003 |</span><br><span class="line">| query end | 0.000003 |</span><br><span class="line">| closing tables | 0.000004 |</span><br><span class="line">| freeing items | 0.000226 |</span><br><span class="line">| logging slow query | 0.000001 |</span><br><span class="line">| logging slow query | 0.000036 |</span><br><span class="line">| cleaning up | 0.000001 |</span><br><span class="line">+----------------------+----------+</span><br><span class="line">17 rows in set (0.00 sec)</span><br></pre></td></tr></table></figure></p><p>上图中纵向栏意义:</p><div class="table-container"><table><thead><tr><th style="text-align:left">类型</th><th style="text-align:left">说明</th></tr></thead><tbody><tr><td style="text-align:left">starting</td><td style="text-align:left">开始</td></tr><tr><td style="text-align:left">checking permissions</td><td style="text-align:left">检查权限</td></tr><tr><td style="text-align:left">Opening tables</td><td style="text-align:left">打开表</td></tr><tr><td style="text-align:left">init</td><td style="text-align:left">初始化</td></tr><tr><td style="text-align:left">System lock</td><td style="text-align:left">系统锁</td></tr><tr><td style="text-align:left">optimizing</td><td style="text-align:left">优化</td></tr><tr><td style="text-align:left">statistics</td><td style="text-align:left">统计</td></tr><tr><td style="text-align:left">preparing</td><td style="text-align:left">准备</td></tr><tr><td style="text-align:left">executing</td><td style="text-align:left">执行</td></tr><tr><td style="text-align:left">Sending data</td><td style="text-align:left">发送数据</td></tr><tr><td style="text-align:left">Sorting result</td><td style="text-align:left">排序</td></tr><tr><td style="text-align:left">end</td><td style="text-align:left">结束</td></tr><tr><td style="text-align:left">query end</td><td style="text-align:left">查询 结束</td></tr><tr><td style="text-align:left">closing tables</td><td style="text-align:left">关闭表 /去除TMP 表</td></tr><tr><td style="text-align:left">freeing items</td><td style="text-align:left">释放物品</td></tr><tr><td style="text-align:left">cleaning up</td><td style="text-align:left">清理</td></tr></tbody></table></div><pre><code>通过对以上数据的分析可以知道SQL的具体消耗情况。</code></pre>]]></content>
<summary type="html">
<h3 id="1、Explain详解"><a href="#1、Explain详解" class="headerlink" title="1、Explain详解"></a>1、Explain详解</h3><p>explain 显示了Mysql如何使用索引处理select语句以及连接表。通过explain分析可以更好的选择索引,优化select语句。
</summary>
<category term="Mysql" scheme="http://blog.feifan.news/categories/Mysql/"/>
<category term="mysql" scheme="http://blog.feifan.news/tags/mysql/"/>
</entry>
<entry>
<title>hexo+github 搭建个人博客</title>
<link href="http://blog.feifan.news/2017/04/04/hexo-github/"/>
<id>http://blog.feifan.news/2017/04/04/hexo-github/</id>
<published>2017-04-04T14:25:16.000Z</published>
<updated>2019-05-06T15:38:02.748Z</updated>
<content type="html"><![CDATA[<blockquote><p>回头想想自己一直在摆弄着买空间、域名、vps,买了一年的空间马上就有到了,想着换一个vps,后来看了看github个人博客,感觉还不错,博客就是记录自己的在工作中的遇到的问题以及对工作的总结,这个应该够用了。所以就在网上搜了一下,发现有好多hexo主题,个人比较喜欢简单的,最后选择了<a href="https://github.com/hexojs/hexo-theme-light" target="_blank" rel="noopener">hexo-theme-light</a>.进行了简单的修改,博客刚成型,还在修改中,先记录一下。<a id="more"></a> </p></blockquote><p>博客需要准备:</p><ul><li>github帐号</li><li>域名(非必须)</li><li>nodejs环境<br>以上这些东西不知道怎么弄就百度 ,主要记录一下自己比较陌生的几个地方。</li></ul><h3 id="1、配置SSH-Key"><a href="#1、配置SSH-Key" class="headerlink" title="1、配置SSH Key"></a>1、配置SSH Key</h3><p>使用ssh key解决本地和github的链接问题,获取github权限,提交代码到github<br>检查是否存在ssh密钥<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cd ~/.ssh</span><br></pre></td></tr></table></figure></p><p>如果提示:No such file or directory 说明你是第一次使用git。<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ssh-keygen -t rsa</span><br></pre></td></tr></table></figure></p><p>然后连续3次回车,最终会生成一个文件在用户目录下,打开用户目录,找到.ssh\id_rsa.pub文件,记事本打开并复制里面的内容,打开你的github主页,进入个人设置 -> SSH and GPG keys -> New SSH key:将刚复制的内容粘贴到key那里,title随便填,保存。<br>测试是否成功<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ ssh -T [email protected] # 注意邮箱地址不用改</span><br></pre></td></tr></table></figure></p><p>如果提示:Are you sure you want to continue connecting (yes/no)?,输入yes,然后会看到:</p><pre><code>Hi liushuaicai! You've successfully authenticated, but GitHub does not provide shell access.</code></pre><p>看到这个信息说明SSH已配置成功!<br>此时你还需要为git设置用户名和邮箱:<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line">$ git config --global user.name "liushuaicai"// 你的github用户名,非昵称</span><br><span class="line">$ git config --global user.email "[email protected]"// 填写你的github注册邮箱</span><br></pre></td></tr></table></figure></p><h3 id="2、上传代码到github"><a href="#2、上传代码到github" class="headerlink" title="2、上传代码到github"></a>2、上传代码到github</h3><p>安装hexo-deployer-git插件(也可用淘宝 NPM 镜像cnpm安装)<br><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install hexo-deployer-git --save</span><br></pre></td></tr></table></figure></p><p>配置_config.yml(在文件中加入以下内容):</p><pre><code>deploy: type: git repository: [email protected]:LiuShuaiaCai/liushuaicaiblog.github.io.git branch: master</code></pre><p>然后用 hexo g 命令生成public文件夹,不要忘记在提交代码之前github上的代码clone一份,然后把clone下来的CNAME文件cp一份到刚生成的public文件夹(CNAME文件中是在前面的域名绑定时生成的文件,里面是你的域名),不然会提交失败。最后用 hexo d 提交到github,会把以前的代码覆盖。</p><h3 id="3、本地的搜索引擎"><a href="#3、本地的搜索引擎" class="headerlink" title="3、本地的搜索引擎"></a>3、<a href="http://hahack.com/codes/local-search-engine-for-hexo/#%E5%AE%89%E8%A3%85%E5%92%8C%E9%85%8D%E7%BD%AE-hexo-generator-search" target="_blank" rel="noopener">本地的搜索引擎</a></h3><p>以下是我复制的内容,为了自己以后使用方便,大家可以去作者的<a href="http://hahack.com/codes/local-search-engine-for-hexo/#%E5%AE%89%E8%A3%85%E5%92%8C%E9%85%8D%E7%BD%AE-hexo-generator-search" target="_blank" rel="noopener">网站</a>看更详细的介绍<br>安装和配置 hexo-generator-search</p><figure class="highlight plain"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">$ npm install --save hexo-generator-search</span><br></pre></td></tr></table></figure><p>然后,在站点根 _config.yml 里头添加设置项:</p><pre><code>search: path: search.xml field: post</code></pre><p>其中:</p><pre><code>path - 指定生成的索引数据的文件名。默认为 search.xml 。field - 指定索引数据的生成范围。可选值包括: post - 只生成博客文章(post)的索引(默认); page - 只生成其他页面(page)的索引; all - 生成所有文章和页面的索引。</code></pre><p>完成后,可以试试访问预览站点的 search.xml 页面。例如,如果你的预览站点域名是 <a href="http://0.0.0.0:4000" target="_blank" rel="noopener">http://0.0.0.0:4000</a> ,那么可以访问 <a href="http://0.0.0.0:4000/search.xml" target="_blank" rel="noopener">http://0.0.0.0:4000/search.xml</a> 看看是否会打开一个 xml 页面。<br>编写搜索界面</p><p>搜索界面由一个输入框(input)和一个用于动态插入搜索结果的 div 组成。例如:<br><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">div</span> <span class="attr">id</span>=<span class="string">"site_search"</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">input</span> <span class="attr">type</span>=<span class="string">"text"</span> <span class="attr">id</span>=<span class="string">"local-search-input"</span> <span class="attr">name</span>=<span class="string">"q"</span> <span class="attr">results</span>=<span class="string">"0"</span> <span class="attr">placeholder</span>=<span class="string">"search my blog..."</span> <span class="attr">class</span>=<span class="string">"form-control"</span>/></span></span><br><span class="line"> <span class="tag"><<span class="name">div</span> <span class="attr">id</span>=<span class="string">"local-search-result"</span>></span><span class="tag"></<span class="name">div</span>></span></span><br><span class="line"><span class="tag"></<span class="name">div</span>></span></span><br></pre></td></tr></table></figure></p><p>你也可以根据自己的喜好写成其他的形式,例如把用于插入结果的 div 移动到页面的其他地方。<br>实现本地搜索函数</p><p>接下来编写一个 search.js 脚本,用来实现基于 search.xml 的本地检索函数 searchFunc :<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br><span class="line">62</span><br><span class="line">63</span><br><span class="line">64</span><br><span class="line">65</span><br><span class="line">66</span><br><span class="line">67</span><br><span class="line">68</span><br><span class="line">69</span><br><span class="line">70</span><br><span class="line">71</span><br><span class="line">72</span><br><span class="line">73</span><br><span class="line">74</span><br><span class="line">75</span><br><span class="line">76</span><br><span class="line">77</span><br><span class="line">78</span><br><span class="line">79</span><br><span class="line">80</span><br><span class="line">81</span><br><span class="line">82</span><br><span class="line">83</span><br><span class="line">84</span><br><span class="line">85</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> searchFunc = <span class="function"><span class="keyword">function</span>(<span class="params">path, search_id, content_id</span>) </span>{</span><br><span class="line"><span class="meta"> 'use strict'</span>;</span><br><span class="line"> $.ajax({</span><br><span class="line"> url: path,</span><br><span class="line"> dataType: <span class="string">"xml"</span>,</span><br><span class="line"> success: <span class="function"><span class="keyword">function</span>(<span class="params"> xmlResponse </span>) </span>{</span><br><span class="line"> <span class="comment">// get the contents from search data</span></span><br><span class="line"> <span class="keyword">var</span> datas = $( <span class="string">"entry"</span>, xmlResponse ).map(<span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">return</span> {</span><br><span class="line"> title: $( <span class="string">"title"</span>, <span class="keyword">this</span> ).text(),</span><br><span class="line"> content: $(<span class="string">"content"</span>,<span class="keyword">this</span>).text(),</span><br><span class="line"> url: $( <span class="string">"url"</span> , <span class="keyword">this</span>).text()</span><br><span class="line"> };</span><br><span class="line"> }).get();</span><br><span class="line"> <span class="keyword">var</span> $input = <span class="built_in">document</span>.getElementById(search_id);</span><br><span class="line"> <span class="keyword">var</span> $resultContent = <span class="built_in">document</span>.getElementById(content_id);</span><br><span class="line"> $input.addEventListener(<span class="string">'input'</span>, <span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{</span><br><span class="line"> <span class="keyword">var</span> str=<span class="string">'<ul class=\"search-result-list\">'</span>; </span><br><span class="line"> <span class="keyword">var</span> keywords = <span class="keyword">this</span>.value.trim().toLowerCase().split(<span class="regexp">/[\s\-]+/</span>);</span><br><span class="line"> $resultContent.innerHTML = <span class="string">""</span>;</span><br><span class="line"> <span class="keyword">if</span> (<span class="keyword">this</span>.value.trim().length <= <span class="number">0</span>) {</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">// perform local searching</span></span><br><span class="line"> datas.forEach(<span class="function"><span class="keyword">function</span>(<span class="params">data</span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> isMatch = <span class="literal">true</span>;</span><br><span class="line"> <span class="keyword">var</span> content_index = [];</span><br><span class="line"> <span class="keyword">var</span> data_title = data.title.trim().toLowerCase();</span><br><span class="line"> <span class="keyword">var</span> data_content = data.content.trim().replace(<span class="regexp">/<[^>]+>/g</span>,<span class="string">""</span>).toLowerCase();</span><br><span class="line"> <span class="keyword">var</span> data_url = data.url;</span><br><span class="line"> <span class="keyword">var</span> index_title = <span class="number">-1</span>;</span><br><span class="line"> <span class="keyword">var</span> index_content = <span class="number">-1</span>;</span><br><span class="line"> <span class="keyword">var</span> first_occur = <span class="number">-1</span>;</span><br><span class="line"> <span class="comment">// only match artiles with not empty titles and contents</span></span><br><span class="line"> <span class="keyword">if</span>(data_title != <span class="string">''</span> && data_content != <span class="string">''</span>) {</span><br><span class="line"> keywords.forEach(<span class="function"><span class="keyword">function</span>(<span class="params">keyword, i</span>) </span>{</span><br><span class="line"> index_title = data_title.indexOf(keyword);</span><br><span class="line"> index_content = data_content.indexOf(keyword);</span><br><span class="line"> <span class="keyword">if</span>( index_title < <span class="number">0</span> && index_content < <span class="number">0</span> ){</span><br><span class="line"> isMatch = <span class="literal">false</span>;</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="keyword">if</span> (index_content < <span class="number">0</span>) {</span><br><span class="line"> index_content = <span class="number">0</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (i == <span class="number">0</span>) {</span><br><span class="line"> first_occur = index_content;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> });</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">// show search results</span></span><br><span class="line"> <span class="keyword">if</span> (isMatch) {</span><br><span class="line"> str += <span class="string">"<li><a href='"</span>+ data_url +<span class="string">"' class='search-result-title'>"</span>+ data_title +<span class="string">"</a>"</span>;</span><br><span class="line"> <span class="keyword">var</span> content = data.content.trim().replace(<span class="regexp">/<[^>]+>/g</span>,<span class="string">""</span>);</span><br><span class="line"> <span class="keyword">if</span> (first_occur >= <span class="number">0</span>) {</span><br><span class="line"> <span class="comment">// cut out 100 characters</span></span><br><span class="line"> <span class="keyword">var</span> start = first_occur - <span class="number">20</span>;</span><br><span class="line"> <span class="keyword">var</span> end = first_occur + <span class="number">80</span>;</span><br><span class="line"> <span class="keyword">if</span>(start < <span class="number">0</span>){</span><br><span class="line"> start = <span class="number">0</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span>(start == <span class="number">0</span>){</span><br><span class="line"> end = <span class="number">100</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span>(end > content.length){</span><br><span class="line"> end = content.length;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">var</span> match_content = content.substr(start, end); </span><br><span class="line"> <span class="comment">// highlight all keywords</span></span><br><span class="line"> keywords.forEach(<span class="function"><span class="keyword">function</span>(<span class="params">keyword</span>)</span>{</span><br><span class="line"> <span class="keyword">var</span> regS = <span class="keyword">new</span> <span class="built_in">RegExp</span>(keyword, <span class="string">"gi"</span>);</span><br><span class="line"> match_content = match_content.replace(regS, <span class="string">"<em class=\"search-keyword\">"</span>+keyword+<span class="string">"</em>"</span>);</span><br><span class="line"> });</span><br><span class="line"> </span><br><span class="line"> str += <span class="string">"<p class=\"search-result\">"</span> + match_content +<span class="string">"...</p>"</span></span><br><span class="line"> }</span><br><span class="line"> str += <span class="string">"</li>"</span>;</span><br><span class="line"> }</span><br><span class="line"> });</span><br><span class="line"> str += <span class="string">"</ul>"</span>;</span><br><span class="line"> $resultContent.innerHTML = str;</span><br><span class="line"> });</span><br><span class="line"> }</span><br><span class="line"> });</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><p>searchFunc 包含三个参数:</p><pre><code>path - 用 hexo-generator-search 生成的搜索索引文件的路径。注意这个 path 和前面 hexo-generator-search 的 path 选项有所不同。这里的 path 才是指这个文件的路径,而前面的 path 指的是生成的文件名 2 2也许第二个 path 叫 filename 更合适。 ;search_id - 搜索框的 id 。对于我们的例子,就是 local-search-input;content_id - 结果框的 id 。对于我们的例子,就是 local-search-result。</code></pre><p>调用搜索函数</p><p>有了上面的检索函数,接下来可以在适当时机调用它。由于 path 的实际地址是根 _config.yml 里 config.root + config.search.path 两个值组成,所以我们最好将这个调用写在页面模板中,以方便获取站点的设置信息。例如,对于 ejs 模板:<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br></pre></td><td class="code"><pre><span class="line"><script type=<span class="string">"text/javascript"</span>> </span><br><span class="line"> <span class="keyword">var</span> search_path = <span class="string">"<%= config.search.path %>"</span>;</span><br><span class="line"> <span class="keyword">if</span> (search_path.length == <span class="number">0</span>) {</span><br><span class="line"> search_path = <span class="string">"search.xml"</span>;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">var</span> path = <span class="string">"<%= config.root %>"</span> + search_path;</span><br><span class="line"> searchFunc(path, <span class="string">'local-search-input'</span>, <span class="string">'local-search-result'</span>);</span><br><span class="line"><<span class="regexp">/script></span></span><br></pre></td></tr></table></figure></p><p>至此就完成了本地检索引擎的实线,最后的工作就是修改样式,让检索页面更美观。在 searchFunc 函数中,我已经为几个关键的页面元素设定了 css 名:</p><pre><code>ul.search-result-list - 搜索结果列表的样式名;a.search-result-title - 搜索结果文章标题的样式名;p.search-result - 搜索结果每篇文章的预览段落的样式名;em.search-keyword - 搜索结果每篇文章的预览段落中匹配关键词的样式名。</code></pre><p>最后给出 hexo-theme-freemind 主题的相关样式:<br><figure class="highlight css"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="selector-tag">ul</span><span class="selector-class">.search-result-list</span> {</span><br><span class="line"> <span class="attribute">padding-left</span>: <span class="number">10px</span>;</span><br><span class="line">}</span><br><span class="line"><span class="selector-tag">a</span><span class="selector-class">.search-result-title</span> {</span><br><span class="line"> <span class="attribute">font-weight</span>: bold;</span><br><span class="line">}</span><br><span class="line"><span class="selector-tag">p</span><span class="selector-class">.search-result</span> {</span><br><span class="line"> color=#555;</span><br><span class="line">}</span><br><span class="line"><span class="selector-tag">em</span><span class="selector-class">.search-keyword</span> {</span><br><span class="line"> <span class="attribute">border-bottom</span>: <span class="number">1px</span> dashed <span class="number">#4088b8</span>;</span><br><span class="line"> <span class="attribute">font-weight</span>: bold;</span><br><span class="line">}</span><br></pre></td></tr></table></figure></p><h2 id="4、更换googleapis相关的链接"><a href="#4、更换googleapis相关的链接" class="headerlink" title="4、更换googleapis相关的链接"></a>4、更换googleapis相关的链接</h2><p>4.1 文件 layout/_partial/after_footer.ejs<br>找到</p><pre><code>ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js</code></pre><p>替换为</p><pre><code>ajax.useso.com/ajax/libs/jquery/2.0.3/jquery.min.js</code></pre><p>4.2 文件 source/css/_base/variable.styl<br>找到</p><pre><code>fonts.googleapis.com/css?family=Lato:400,400italic</code></pre><p>替换为 </p><pre><code>fonts.useso.com/css?family=Lato:400,400italic</code></pre><p>4.3 文件 layout/_partial/head.ejs<br>找到</p><pre><code>fonts.googleapis.com/css?family=Source+Code+Pro</code></pre><p>替换为</p><pre><code>fonts.useso.com/css?family=Source+Code+Pro</code></pre><h2 id="5、分享"><a href="#5、分享" class="headerlink" title="5、分享"></a>5、分享</h2><p>默认自带的是AddThis,进文章一看便发现都是分享到facebook、twitter等之类的网站,换成百度分享。<br>5.1 文件 layout/_partial/post/share.ejs<br>内容全部替换为<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br></pre></td><td class="code"><pre><span class="line"><div <span class="class"><span class="keyword">class</span></span>=<span class="string">"bdsharebuttonbox"</span>></span><br><span class="line"> <a href=<span class="string">"#"</span> <span class="class"><span class="keyword">class</span></span>=<span class="string">"bds_more"</span> data-cmd=<span class="string">"more"</span>><span class="xml"><span class="tag"></<span class="name">a</span>></span></span></span><br><span class="line"> <a href=<span class="string">"#"</span> <span class="class"><span class="keyword">class</span></span>=<span class="string">"bds_qzone"</span> data-cmd=<span class="string">"qzone"</span>><span class="xml"><span class="tag"></<span class="name">a</span>></span></span></span><br><span class="line"> <a href=<span class="string">"#"</span> <span class="class"><span class="keyword">class</span></span>=<span class="string">"bds_tsina"</span> data-cmd=<span class="string">"tsina"</span>><span class="xml"><span class="tag"></<span class="name">a</span>></span></span></span><br><span class="line"> <a href=<span class="string">"#"</span> <span class="class"><span class="keyword">class</span></span>=<span class="string">"bds_tqq"</span> data-cmd=<span class="string">"tqq"</span>><span class="xml"><span class="tag"></<span class="name">a</span>></span></span></span><br><span class="line"> <a href=<span class="string">"#"</span> <span class="class"><span class="keyword">class</span></span>=<span class="string">"bds_renren"</span> data-cmd=<span class="string">"renren"</span>><span class="xml"><span class="tag"></<span class="name">a</span>></span></span></span><br><span class="line"> <a href=<span class="string">"#"</span> <span class="class"><span class="keyword">class</span></span>=<span class="string">"bds_weixin"</span> data-cmd=<span class="string">"weixin"</span>><span class="xml"><span class="tag"></<span class="name">a</span>></span></span></span><br><span class="line"><<span class="regexp">/div></span></span><br><span class="line"><span class="regexp"></span></span><br><span class="line"><span class="regexp"><script></span></span><br><span class="line"><span class="regexp"> window._bd_share_config = {</span></span><br><span class="line"><span class="regexp"> "common": {</span></span><br><span class="line"><span class="regexp"> "bdSnsKey": {},</span></span><br><span class="line"><span class="regexp"> "bdText": "",</span></span><br><span class="line"><span class="regexp"> "bdMini": "2",</span></span><br><span class="line"><span class="regexp"> "bdPic": "",</span></span><br><span class="line"><span class="regexp"> "bdStyle": "0",</span></span><br><span class="line"><span class="regexp"> "bdSize": "16"</span></span><br><span class="line"><span class="regexp"> },</span></span><br><span class="line"><span class="regexp"> "share": {},</span></span><br><span class="line"><span class="regexp"> "image": {</span></span><br><span class="line"><span class="regexp"> "viewList": ["qzone", "tsina", "tqq", "renren", "weixin"],</span></span><br><span class="line"><span class="regexp"> "viewText": "分享到",</span></span><br><span class="line"><span class="regexp"> "viewSize": "16"</span></span><br><span class="line"><span class="regexp"> },</span></span><br><span class="line"><span class="regexp"> "selectShare": {</span></span><br><span class="line"><span class="regexp"> "bdContainerClass": null,</span></span><br><span class="line"><span class="regexp"> "bdSelectMiniList": ["qzone", "tsina", "tqq", "renren", "weixin"]</span></span><br><span class="line"><span class="regexp"> }</span></span><br><span class="line"><span class="regexp"> };</span></span><br><span class="line"><span class="regexp"> with(document) 0[(getElementsByTagName('head')[0] || body).appendChild(createElement('script')).src = 'http:/</span><span class="regexp">/bdimg.share.baidu.com/</span><span class="keyword">static</span>/api/js/share.js?v=<span class="number">89860593.</span>js?cdnversion=<span class="string">' + ~(-new Date() / 36e5)];</span></span><br><span class="line"><span class="string"></script></span></span><br></pre></td></tr></table></figure></p><h2 id="6、评论-默认自带的是disqus-换成多说"><a href="#6、评论-默认自带的是disqus-换成多说" class="headerlink" title="6、评论: (默认自带的是disqus,换成多说)"></a>6、评论: (默认自带的是disqus,换成多说)</h2><p>6.1 文件 hexo/_config.yml<br>添加</p><pre><code>duoshuo_shortname: xxx</code></pre><p>注:其实xxx是你在多说系统注册的一个shortname,这方面自行科普。<br>6.2 全局载入多说的js,在layout/_partial/after_footer.ejs尾部中加入如下代码<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line"><script type=<span class="string">"text/javascript"</span>></span><br><span class="line"><span class="keyword">var</span> duoshuo_shortname = <span class="string">'<%= config.duoshuo_shortname %>'</span>;</span><br><span class="line"><span class="keyword">var</span> duoshuoQuery = {<span class="attr">short_name</span>:duoshuo_shortname};</span><br><span class="line"> (<span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> ds = <span class="built_in">document</span>.createElement(<span class="string">'script'</span>);</span><br><span class="line"> ds.type = <span class="string">'text/javascript'</span>;ds.async = <span class="literal">true</span>;</span><br><span class="line"> ds.src = <span class="string">'http://static.duoshuo.com/embed.js'</span>;</span><br><span class="line"> ds.charset = <span class="string">'UTF-8'</span>;</span><br><span class="line"> (<span class="built_in">document</span>.getElementsByTagName(<span class="string">'head'</span>)[<span class="number">0</span>] || <span class="built_in">document</span>.getElementsByTagName(<span class="string">'body'</span>)[<span class="number">0</span>]).appendChild(ds);</span><br><span class="line"> })();</span><br><span class="line"><<span class="regexp">/script></span></span><br></pre></td></tr></table></figure></p><p>6.3 显示正文评论,文件 layout/_partial/comment.ejs<br>全文替换为<br><figure class="highlight javascript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br></pre></td><td class="code"><pre><span class="line"><% <span class="keyword">if</span> (page.comments){ %></span><br><span class="line"> <section id=<span class="string">"comment"</span>></span><br><span class="line"> <h1 <span class="class"><span class="keyword">class</span></span>=<span class="string">"title"</span>><span class="xml"><span class="tag"><<span class="name">%=</span> <span class="attr">__</span>('<span class="attr">comment</span>') %></span><span class="tag"></<span class="name">h1</span>></span></span></span><br><span class="line"> <div <span class="class"><span class="keyword">class</span></span>=<span class="string">"ds-thread"</span> data-thread-key=<span class="string">"<%- item.path %>"</span>><span class="xml"><span class="tag"></<span class="name">div</span>></span></span></span><br><span class="line"> <<span class="regexp">/section></span></span><br><span class="line"><span class="regexp"><% } %></span></span><br></pre></td></tr></table></figure></p><p>6.4 显示列表评论数,文件 layout/_partial/article.ejs<br>找到<br><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">%</span> <span class="attr">if</span> (<span class="attr">item.comment</span> && <span class="attr">config.disqus_shortname</span>){ %></span></span><br><span class="line"> <span class="tag"><<span class="name">div</span> <span class="attr">class</span>=<span class="string">"alignright"</span>></span></span><br><span class="line"> <span class="tag"><<span class="name">a</span> <span class="attr">href</span>=<span class="string">"<%- item.permalink %>#disqus_thread"</span> <span class="attr">class</span>=<span class="string">"comment-link"</span>></span>Comments<span class="tag"></<span class="name">a</span>></span></span><br><span class="line"> <span class="tag"></<span class="name">div</span>></span></span><br><span class="line"><span class="tag"><<span class="name">%</span> } %></span></span><br></pre></td></tr></table></figure></p><p>替换为<br><figure class="highlight html"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="tag"><<span class="name">%</span> <span class="attr">if</span> (!<span class="attr">item.comment</span>){ %></span></span><br><span class="line"> <span class="tag"><<span class="name">a</span> <span class="attr">href</span>=<span class="string">"<%- config.root %><%- item.path %>"</span> <span class="attr">class</span>=<span class="string">"ds-thread-count comment-link alignright"</span> <span class="attr">data-thread-key</span>=<span class="string">"<%- item.path %>"</span> <span class="attr">data-count-type</span>=<span class="string">"comments"</span>></span><span class="tag"></<span class="name">a</span>></span></span><br><span class="line"><span class="tag"><<span class="name">%</span> } %></span></span><br></pre></td></tr></table></figure></p><h2 id="7、添加RSS"><a href="#7、添加RSS" class="headerlink" title="7、添加RSS"></a>7、添加RSS</h2><p>hexo提供了RSS的生成插件,需要手动安装和设置。步骤如下:</p><ul><li>安装RSS插件到本地:npm install hexo-generator-feed</li><li><p>在站点添加链接:</p><p> 在themes/light/_config.yml中,编辑 rss: /atom.xml</p></li></ul><blockquote><p>其他功能修改查看下面的博客链接</p><h2 id="8、常用hexo命令"><a href="#8、常用hexo命令" class="headerlink" title="8、常用hexo命令"></a>8、常用hexo命令</h2><p>常见命令</p></blockquote><pre><code>hexo new "postName" #新建文章hexo new page "pageName" #新建页面hexo generate #生成静态页面至public目录hexo server #开启预览访问端口(默认端口4000,'ctrl + c'关闭server)hexo deploy #部署到GitHubhexo help # 查看帮助hexo version #查看Hexo的版本</code></pre><p>缩写:</p><pre><code>hexo n == hexo newhexo g == hexo generatehexo s == hexo serverhexo d == hexo deploy</code></pre><p>组合命令:</p><pre><code>hexo s -g #生成并本地预览hexo d -g #生成并上传</code></pre><p>文章的格式如下:</p><pre><code>---title: postName #文章页面上的显示名称,一般是中文date: 2013-12-02 15:30:16 #文章生成时间,一般不改,当然也可以任意修改categories: 默认分类 #分类tags: [tag1,tag2,tag3] #文章标签,可空,多标签请用格式,注意:后面有个空格description: 附加一段文章摘要,字数最好在140字以内,会出现在meta的description里面---以下是正文</code></pre><h4 id="参考文章"><a href="#参考文章" class="headerlink" title="参考文章:"></a>参考文章:</h4><p><em><a href="http://www.mjiayou.com/2014/08/18/hexo-theme-modify-based-light/" target="_blank" rel="noopener">青春不再 | 马加油DE博客</a></em><br><em><a href="http://www.jianshu.com/p/70343b7c2fd3" target="_blank" rel="noopener">蓝江老涌-简书</a></em><br><em><a href="http://www.cnblogs.com/liuxianan/p/build-blog-website-by-hexo-github.html" target="_blank" rel="noopener">小茗同学的博客园</a></em><br><em><a href="http://www.jianshu.com/p/347e7a0919ed" target="_blank" rel="noopener">在Hexo主题中新添加resume布局</a></em><br><em><a href="http://opiece.me/2015/04/16/hexo-guide-3/" target="_blank" rel="noopener">hexo搭建博客的实用功能(下)(基于hexo3.0) </a></em><br><em><a href="http://www.ituring.com.cn/article/199294?utm_source=tuicool&utm_medium=referral" target="_blank" rel="noopener">Hexo:(三)高级进阶</a></em><br><em><a href="http://wiki.jikexueyuan.com/project/hexo-document/" target="_blank" rel="noopener">极客学院</a></em></p><blockquote><p>到此为止我的第一篇github博客算是完成了,Time:2017/04/05 凌晨03点25分</p></blockquote>]]></content>
<summary type="html">
<blockquote>
<p>回头想想自己一直在摆弄着买空间、域名、vps,买了一年的空间马上就有到了,想着换一个vps,后来看了看github个人博客,感觉还不错,博客就是记录自己的在工作中的遇到的问题以及对工作的总结,这个应该够用了。所以就在网上搜了一下,发现有好多hexo主题,个人比较喜欢简单的,最后选择了<a href="https://github.com/hexojs/hexo-theme-light" target="_blank" rel="noopener">hexo-theme-light</a>.进行了简单的修改,博客刚成型,还在修改中,先记录一下。
</summary>
<category term="hexo" scheme="http://blog.feifan.news/categories/hexo/"/>
<category term="Hexo" scheme="http://blog.feifan.news/tags/Hexo/"/>
<category term="github" scheme="http://blog.feifan.news/tags/github/"/>
</entry>
</feed>