-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathatom.xml
455 lines (289 loc) · 269 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
<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
<title>Dai Chong's blog</title>
<subtitle>戴崇博客,戴崇技术博客,php技术博客,hexo博客,web技术博客</subtitle>
<link href="/atom.xml" rel="self"/>
<link href="http://www.daichongweb.com/"/>
<updated>2021-09-09T02:40:55.430Z</updated>
<id>http://www.daichongweb.com/</id>
<author>
<name>Daichongweb</name>
</author>
<generator uri="http://hexo.io/">Hexo</generator>
<entry>
<title>php strtotime的妙用</title>
<link href="http://www.daichongweb.com/php-strtotime%E7%9A%84%E5%A6%99%E7%94%A8/"/>
<id>http://www.daichongweb.com/php-strtotime的妙用/</id>
<published>2021-09-08T08:50:43.000Z</published>
<updated>2021-09-09T02:40:55.430Z</updated>
<content type="html"><![CDATA[<h4 id="strtotime的函数介绍"><a href="#strtotime的函数介绍" class="headerlink" title="strtotime的函数介绍"></a>strtotime的函数介绍</h4><p> <code>strtotime()</code>函数通过名字就可以看出来是把<code>字符串转为时间戳</code>的一个函数。</p><p> 在实际项目开发中肯定用到的特别多,但是使用方法都比较单一,只会用它把<code>2021/09/08 15:00:00</code>这样的时间格式转化为时间戳。<br><a id="more"></a></p><p> ps:不同的分隔符,比如 m/d/y 或 d-m-y 会影响到解析结果:若以反斜线 (/) 为分隔,将会做为美洲日期 m/d/y 来解析;而当分隔符为短横线 (-) 或点 (.) 时,则将做为欧洲日期 d-m-y 格式来解析。当年份只有两位数字,且分隔符为短横线 (-时,日期字符串将被解析为 y-m-d 格式。</p><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><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><br><span class="line">strtotime('today midnight'); </span><br><span class="line"></span><br><span class="line">// 今天中午</span><br><span class="line">strtotime('today noon'); </span><br><span class="line"></span><br><span class="line">// 今天早上10点</span><br><span class="line">strtotime('today 10am'); </span><br><span class="line"></span><br><span class="line">// 明天早上10点</span><br><span class="line">strtotime('next day 10am'); </span><br><span class="line"></span><br><span class="line">// 明天的开始时间</span><br><span class="line">strtotime('tomorrow');</span><br><span class="line"></span><br><span class="line">// 昨天的开始时间</span><br><span class="line">strtotime('yesterday');</span><br><span class="line"></span><br><span class="line">// 1630512000=9月2日,这个就是9月2日00:00的时间戳</span><br><span class="line">strtotime('today midnight', 1630576301); </span><br><span class="line"></span><br><span class="line">// 周五00:00的时间戳,也可以填周一到周日的英文单词</span><br><span class="line">strtotime('friday');</span><br><span class="line"></span><br><span class="line">// 七周后周日的开始时间 twelfth:十二周,seventh:七周,eleventh:十一周</span><br><span class="line">strtotime('seventh sunday');</span><br><span class="line"></span><br><span class="line">// 七周后周三的开始时间</span><br><span class="line">strtotime('seventh wednesday');</span><br><span class="line"></span><br><span class="line">// 1天前</span><br><span class="line">strtotime('-1');</span><br><span class="line"></span><br><span class="line">// 1天后</span><br><span class="line">strtotime('+1');</span><br></pre></td></tr></table></figure><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><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">// 四月一号0点的时间戳</span><br><span class="line">strtotime('first day of April');</span><br><span class="line"></span><br><span class="line">// 四月最后一天的0点的时间戳</span><br><span class="line">strtotime('last day of April');</span><br><span class="line"></span><br><span class="line">// 上个月第一天的时间戳(小:时:秒是当前的时间)</span><br><span class="line">strtotime('first day of previous month') || strtotime('first day of -1 month');</span><br><span class="line">PS:`+n`就是多少个月后,`-n`就是多少个月前</span><br><span class="line"></span><br><span class="line">// 这个月最后一天的时间戳</span><br><span class="line">strtotime('last day of this month');</span><br></pre></td></tr></table></figure><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><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">// 返回一周后的现在再加三天的时间戳,也就是10天后。</span><br><span class="line">strtotime('+1 week 3 days');</span><br><span class="line"></span><br><span class="line">strtotime('+1 week');</span><br><span class="line">strtotime('-1 week');</span><br><span class="line"></span><br><span class="line">// 周六的时间戳,可以填周济英文单词,如sunday、monday</span><br><span class="line">strtotime('saturday');</span><br><span class="line">PS:如果填写的是monday(周一),并且这个时间已经是过去式了,则返回的时间是下周对应周几的时间</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
<h4 id="strtotime的函数介绍"><a href="#strtotime的函数介绍" class="headerlink" title="strtotime的函数介绍"></a>strtotime的函数介绍</h4><p>&emsp;<code>strtotime()</code>函数通过名字就可以看出来是把<code>字符串转为时间戳</code>的一个函数。</p>
<p>&emsp;在实际项目开发中肯定用到的特别多,但是使用方法都比较单一,只会用它把<code>2021/09/08 15:00:00</code>这样的时间格式转化为时间戳。<br></p>
</summary>
<category term="最近更新" scheme="http://www.daichongweb.com/tags/%E6%9C%80%E8%BF%91%E6%9B%B4%E6%96%B0/"/>
</entry>
<entry>
<title>mac配置php xdebug</title>
<link href="http://www.daichongweb.com/mac%E9%85%8D%E7%BD%AEphp-xdebug/"/>
<id>http://www.daichongweb.com/mac配置php-xdebug/</id>
<published>2021-09-04T12:00:43.000Z</published>
<updated>2021-09-08T08:52:01.392Z</updated>
<content type="html"><![CDATA[<h4 id="介绍"><a href="#介绍" class="headerlink" title="介绍"></a>介绍</h4><p> 大多数php程序员调试都只使用echo、print_r、var_dump()等函数来代替断点调试,虽然对于大多数开发经验丰富的程序员来说已经足够了,但是如果我们要调试性能、定位错误的情况下,简单的断点调试已经完全没办法满足需求。<br><a id="more"></a></p><p> 在我们平时的php开发中,一个大的项目经过长时间的积累以后你会发现性能越来越慢,而性能到底消耗在了什么地方,常常是一个令人头疼的问题,function a()调用了多少次,function b()又消耗了多少时间,我们到底怎么查找是哪个蛀虫拉慢了我们的程序运行速度呢?在这里给大家介绍一款工具xdebug,相信很多人已经听说过了,希望借助这个工具我们可以起到简单分析php程序性能瓶颈的问题。</p><h4 id="xdebug是什么?"><a href="#xdebug是什么?" class="headerlink" title="xdebug是什么?"></a>xdebug是什么?</h4><p> XDebug是一个开放源代码的PHP程序调试器(即一个Debug工具),可以用来跟踪,调试和分析PHP程序的运行状况。</p><h4 id="如何配置"><a href="#如何配置" class="headerlink" title="如何配置"></a>如何配置</h4><p> 首先我们通过<code>phpinfo()</code>来查看是否安装了<code>xdebug</code>。<br> PS:这里我已经安装过了,windows需要去官网或者phpstudy下载和php版本对应的xdebug扩展。<br><img src="/mac配置php-xdebug/1.png"></p><h5 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h5><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">pecl install xdebug</span><br><span class="line">或者</span><br><span class="line">brew install xdebug</span><br></pre></td></tr></table></figure><h5 id="php增加配置"><a href="#php增加配置" class="headerlink" title="php增加配置"></a>php增加配置</h5><p> 找到php的配置文件目录<code>config.d</code>,新增一个<code>ext-xdebug.ini</code><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">[xdebug]</span><br><span class="line">zend_extension="/usr/local/Cellar/[email protected]/7.4.23/pecl/20190902/xdebug.so"//xdebug安装路径,安装完成后会返回</span><br><span class="line">xdebug.mode=debug </span><br><span class="line">xdebug.idekey=PHPSTORM</span><br><span class="line">xdebug.client_host=127.0.0.1</span><br><span class="line">xdebug.client_port=9002</span><br><span class="line">xdebug.remote_handler="dbgp"</span><br></pre></td></tr></table></figure></p><p> 重启php服务</p><h5 id="配置phpStorm"><a href="#配置phpStorm" class="headerlink" title="配置phpStorm"></a>配置phpStorm</h5><img src="/mac配置php-xdebug/2.png"><img src="/mac配置php-xdebug/3.png"><img src="/mac配置php-xdebug/4.png"><img src="/mac配置php-xdebug/5.png"><h5 id="开启debug"><a href="#开启debug" class="headerlink" title="开启debug"></a>开启debug</h5><img src="/mac配置php-xdebug/6.png"><p> 把这个参数到你请求的url中<br><img src="/mac配置php-xdebug/9.png"><br><img src="/mac配置php-xdebug/8.png"></p><h4 id="大功告成"><a href="#大功告成" class="headerlink" title="大功告成"></a>大功告成</h4><p> 接下来就请享受这一切吧!!!</p>]]></content>
<summary type="html">
<h4 id="介绍"><a href="#介绍" class="headerlink" title="介绍"></a>介绍</h4><p>&emsp;大多数php程序员调试都只使用echo、print_r、var_dump()等函数来代替断点调试,虽然对于大多数开发经验丰富的程序员来说已经足够了,但是如果我们要调试性能、定位错误的情况下,简单的断点调试已经完全没办法满足需求。<br></p>
</summary>
<category term="php" scheme="http://www.daichongweb.com/tags/php/"/>
</entry>
<entry>
<title>解决微信小程序授权第一次总是会失败的问题</title>
<link href="http://www.daichongweb.com/%E8%A7%A3%E5%86%B3%E5%BE%AE%E4%BF%A1%E5%B0%8F%E7%A8%8B%E5%BA%8F%E6%8E%88%E6%9D%83%E7%AC%AC%E4%B8%80%E6%AC%A1%E6%80%BB%E6%98%AF%E4%BC%9A%E5%A4%B1%E8%B4%A5%E7%9A%84%E9%97%AE%E9%A2%98/"/>
<id>http://www.daichongweb.com/解决微信小程序授权第一次总是会失败的问题/</id>
<published>2021-04-20T02:52:42.000Z</published>
<updated>2021-09-04T12:12:05.147Z</updated>
<content type="html"><![CDATA[<h4 id="介绍"><a href="#介绍" class="headerlink" title="介绍"></a>介绍</h4><p> 相信有很多同学都遇到过小程序需要授权两次的问题,这个问题的原因是错误的授权流程导致的。</p><p> (1)错误的流程:<code>引导用户点击授权按钮(getUserProfile)</code>=><code>调起授权(wx.getUserProfile)</code>=><code>获取code(wx.login)</code>=><code>请求后端、传输数据(code、iv等)</code>=><code>后端解密并登陆</code>。</p><p> (2)正确的流程:<code>获取code(wx.show)</code>=><code>引导用户点击授权按钮(getUserProfile)</code>=><code>调起授权(wx.getUserProfile)</code>=><code>请求后端、传输数据(code、iv等)</code>=><code>后端解密并登陆</code>。</p><a id="more"></a><h4 id="代码演示"><a href="#代码演示" class="headerlink" title="代码演示"></a>代码演示</h4><h5 id="1-错误的流程"><a href="#1-错误的流程" class="headerlink" title="(1)错误的流程"></a>(1)错误的流程</h5><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></pre></td><td class="code"><pre><span class="line">getUserProfile: <span class="function"><span class="keyword">function</span> (<span class="params">e</span>) </span>{</span><br><span class="line"> <span class="keyword">let</span> _this = <span class="keyword">this</span>;</span><br><span class="line"> <span class="comment">// 微信小程序授权框</span></span><br><span class="line"> wx.getUserProfile({</span><br><span class="line"> desc: <span class="string">'用于完善会员资料'</span>,</span><br><span class="line"> success: <span class="function">(<span class="params">userResult</span>) =></span> {</span><br><span class="line"> wx.login({</span><br><span class="line"> success (loginResult) {</span><br><span class="line"> <span class="keyword">if</span> (loginResult.code) {</span><br><span class="line"> <span class="comment">//发起网络请求,数据解密</span></span><br><span class="line"> wx.request({</span><br><span class="line"> url: <span class="string">'https://test.com/onLogin'</span>,</span><br><span class="line"> data: {</span><br><span class="line"> code: loginResult.code,</span><br><span class="line"> iv: userResult.iv,</span><br><span class="line"> encryptedData: userResult.encryptedData,</span><br><span class="line"> rawData: userResult.rawData</span><br><span class="line"> },</span><br><span class="line"> success(res){</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 class="keyword">else</span> {</span><br><span class="line"> <span class="built_in">console</span>.log(<span class="string">'登录失败!'</span> + res.errMsg)</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></pre></td></tr></table></figure><h5 id="2-正确的流程"><a href="#2-正确的流程" class="headerlink" title="(2)正确的流程"></a>(2)正确的流程</h5><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></pre></td><td class="code"><pre><span class="line"><span class="comment">// 获取code</span></span><br><span class="line">onShow:<span class="function"><span class="keyword">function</span>(<span class="params"></span>)</span>{</span><br><span class="line"> wx.login({</span><br><span class="line"> success: <span class="function"><span class="params">res</span> =></span> {</span><br><span class="line"> _this.setData({</span><br><span class="line"> code: res.code</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">getUserProfile: <span class="function"><span class="keyword">function</span> (<span class="params">e</span>) </span>{</span><br><span class="line"> <span class="keyword">let</span> _this = <span class="keyword">this</span>;</span><br><span class="line"> <span class="comment">// 检测授权是否过期</span></span><br><span class="line"> wx.checkSession({</span><br><span class="line"> success(checkRes) {</span><br><span class="line"> <span class="comment">// 调起授权窗口</span></span><br><span class="line"> wx.getUserProfile({</span><br><span class="line"> lang: <span class="string">'zh_CN'</span>,</span><br><span class="line"> desc: <span class="string">'用于完善会员资料'</span>,</span><br><span class="line"> success: <span class="function">(<span class="params">userResult</span>) =></span> {</span><br><span class="line"> <span class="comment">//发起网络请求,数据解密</span></span><br><span class="line"> wx.request({</span><br><span class="line"> url: <span class="string">'https://test.com/onLogin'</span>,</span><br><span class="line"> data: {</span><br><span class="line"> code: _this.data.code,</span><br><span class="line"> iv: userResult.iv,</span><br><span class="line"> encryptedData: userResult.encryptedData,</span><br><span class="line"> rawData: userResult.rawData</span><br><span class="line"> },</span><br><span class="line"> success(res){</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><br><span class="line"> fail() {</span><br><span class="line"> <span class="comment">//过期重新获取</span></span><br><span class="line"> _this.getCode();</span><br><span class="line"> }</span><br><span class="line"> })</span><br><span class="line"> },</span><br></pre></td></tr></table></figure><h4 id="注意"><a href="#注意" class="headerlink" title="注意"></a>注意</h4><p> 正确的写法在<code>微信开发者工具</code>和<code>扫码预览</code>都无法调起微信授权框,一定要在<code>真机调试</code>和发布<code>体验版</code>中测试。</p>]]></content>
<summary type="html">
<h4 id="介绍"><a href="#介绍" class="headerlink" title="介绍"></a>介绍</h4><p>&emsp;相信有很多同学都遇到过小程序需要授权两次的问题,这个问题的原因是错误的授权流程导致的。</p>
<p>&emsp;(1)错误的流程:<code>引导用户点击授权按钮(getUserProfile)</code>=&gt;<code>调起授权(wx.getUserProfile)</code>=&gt;<code>获取code(wx.login)</code>=&gt;<code>请求后端、传输数据(code、iv等)</code>=&gt;<code>后端解密并登陆</code>。</p>
<p>&emsp;(2)正确的流程:<code>获取code(wx.show)</code>=&gt;<code>引导用户点击授权按钮(getUserProfile)</code>=&gt;<code>调起授权(wx.getUserProfile)</code>=&gt;<code>请求后端、传输数据(code、iv等)</code>=&gt;<code>后端解密并登陆</code>。</p>
</summary>
<category term="微信小程序" scheme="http://www.daichongweb.com/tags/%E5%BE%AE%E4%BF%A1%E5%B0%8F%E7%A8%8B%E5%BA%8F/"/>
</entry>
<entry>
<title>php微信支付ApiV3版-新版微信支付开发</title>
<link href="http://www.daichongweb.com/php%E5%BE%AE%E4%BF%A1%E6%94%AF%E4%BB%98ApiV3%E7%89%88-%E6%96%B0%E7%89%88%E5%BE%AE%E4%BF%A1%E6%94%AF%E4%BB%98%E5%BC%80%E5%8F%91/"/>
<id>http://www.daichongweb.com/php微信支付ApiV3版-新版微信支付开发/</id>
<published>2021-04-06T08:13:10.000Z</published>
<updated>2021-09-03T05:56:57.956Z</updated>
<content type="html"><![CDATA[<h4 id="微信支付文档"><a href="#微信支付文档" class="headerlink" title="微信支付文档"></a>微信支付文档</h4><p><a herf="https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_1.shtml">统一下单文档JsApi</a></p><h4 id="前期准备流程"><a href="#前期准备流程" class="headerlink" title="前期准备流程"></a>前期准备流程</h4><ol><li>微信公众号申请</li><li>支付商户号申请</li><li>微信公众号绑定支付商户号<a id="more"></a> <img src="/php微信支付ApiV3版-新版微信支付开发/1.png">4.设置白名单、生成AppSecret(开发-基本配置) <img src="/php微信支付ApiV3版-新版微信支付开发/2.png">5.申请Api证书、设置APIv3密钥 <img src="/php微信支付ApiV3版-新版微信支付开发/3.png">6.设置支付配置、jsapi支付授权目录、Native支付回调链接(产品中心-开发配置) <img src="/php微信支付ApiV3版-新版微信支付开发/4.png"><h4 id="支付流程"><a href="#支付流程" class="headerlink" title="支付流程"></a>支付流程</h4> 1.前端调用后端下单接口 <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></pre></td><td class="code"><pre><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 class="type">{*}</span> </span>active </span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param <span class="type">{*}</span> </span>mobile </span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param <span class="type">{*}</span> </span>token </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">createOrder</span>(<span class="params">active, mobile, token</span>) </span>{</span><br><span class="line"> $.showLoading();</span><br><span class="line"> $.ajax({</span><br><span class="line"> type: <span class="string">'post'</span>,</span><br><span class="line"> url: url,</span><br><span class="line"> data: { <span class="string">'active'</span>: active, <span class="string">'pay_type'</span>: <span class="string">'wechat'</span>, <span class="string">'mobile'</span>: mobile },</span><br><span class="line"> dataType: <span class="string">'json'</span>,</span><br><span class="line"> beforeSend: <span class="function"><span class="keyword">function</span> (<span class="params">XMLHttpRequest</span>) </span>{</span><br><span class="line"> XMLHttpRequest.setRequestHeader(<span class="string">"token"</span>, token);</span><br><span class="line"> },</span><br><span class="line"> success: <span class="function"><span class="keyword">function</span> (<span class="params">res</span>) </span>{</span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> <span class="keyword">if</span> (res.status == <span class="string">'error'</span> || res.code != <span class="number">200</span>) {</span><br><span class="line"> $.toptip(res.message, <span class="string">'warning'</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"> WeixinJSBridge.invoke(<span class="string">'getBrandWCPayRequest'</span>, {</span><br><span class="line"> <span class="string">"appId"</span>: res.data.appId,</span><br><span class="line"> <span class="string">"timeStamp"</span>: res.data.timeStamp,</span><br><span class="line"> <span class="string">"nonceStr"</span>: res.data.nonceStr,</span><br><span class="line"> <span class="string">"package"</span>: res.data.package,</span><br><span class="line"> <span class="string">"signType"</span>: res.data.signType,</span><br><span class="line"> <span class="string">"paySign"</span>: res.data.paySign</span><br><span class="line"> },</span><br><span class="line"> <span class="function"><span class="keyword">function</span> (<span class="params">res</span>) </span>{</span><br><span class="line"> <span class="keyword">if</span> (res.err_msg == <span class="string">"get_brand_wcpay_request:ok"</span>) {</span><br><span class="line"> $.toptip(<span class="string">'支付成功'</span>, <span class="string">'success'</span>)</span><br><span class="line"> }</span><br><span class="line"> });</span><br><span class="line"> } <span class="keyword">catch</span> (err) {</span><br><span class="line"> toLogin();</span><br><span class="line"> }</span><br><span class="line"> },</span><br><span class="line"> error: <span class="function"><span class="keyword">function</span> (<span class="params">res</span>) </span>{</span><br><span class="line"> $.toptip(<span class="string">'网络错误'</span>, <span class="string">'warning'</span>)</span><br><span class="line"> }, <span class="attr">complete</span>: <span class="function"><span class="keyword">function</span> (<span class="params">res</span>) </span>{</span><br><span class="line"> $.hideLoading();</span><br><span class="line"> }</span><br><span class="line"> })</span><br><span class="line">}</span><br><span class="line"><a href=<span class="string">"javascript:;"</span> <span class="class"><span class="keyword">class</span></span>=<span class="string">"weui-btn weui-btn_primary"</span> onclick=<span class="string">"createOrder(1,mobile,token)"</span>>立即支付<<span class="regexp">/a></span></span><br></pre></td></tr></table></figure></li></ol><p>2.处理信息、生成订单、返回支付信息<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></pre></td><td class="code"><pre><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> $userId</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> $mobile</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> int $active</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> string $payType</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> array|mixed</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@throws</span> ApiException</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@throws</span> \Throwable</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">createOrder</span><span class="params">($userId, $mobile, $active = <span class="number">1</span>, $payType = <span class="string">'wechat'</span>)</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> DB::beginTransaction();</span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> <span class="keyword">if</span> (<span class="keyword">$this</span>->countWaitOrderByUserId($userId)) {</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> ApiException(<span class="string">'您有未支付的订单,请先处理完毕'</span>, <span class="number">500</span>);</span><br><span class="line"> }</span><br><span class="line"> $activity = <span class="keyword">$this</span>->findActive($active);</span><br><span class="line"> <span class="keyword">if</span> (!$activity) {</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> ApiException(<span class="string">'充值金额有误'</span>, <span class="number">500</span>);</span><br><span class="line"> }</span><br><span class="line"> $orderId = StringHelper::getOrderId(<span class="string">'R'</span>);</span><br><span class="line"> $orderData = [</span><br><span class="line"> <span class="string">'order_id'</span> => $orderId,</span><br><span class="line"> <span class="string">'user_id'</span> => $userId,</span><br><span class="line"> <span class="string">'original_price'</span> => $activity->original_price,</span><br><span class="line"> <span class="string">'price'</span> => $activity->price,</span><br><span class="line"> <span class="string">'pay_type'</span> => $payType,</span><br><span class="line"> <span class="string">'mobile'</span> => $mobile,</span><br><span class="line"> <span class="string">'active'</span> => $active</span><br><span class="line"> ];</span><br><span class="line"> <span class="keyword">if</span> (!<span class="keyword">$this</span>->insertOrder($orderData)) {</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> ApiException(<span class="string">'订单创建失败'</span>, <span class="number">500</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">// 请求微信统一下单</span></span><br><span class="line"> <span class="keyword">if</span> ($result = <span class="keyword">$this</span>->payOrder($orderId, $userId)) {</span><br><span class="line"> DB::commit();</span><br><span class="line"> <span class="keyword">return</span> $result;</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> ApiException(<span class="string">'统一下单失败'</span>, <span class="number">500</span>);</span><br><span class="line"> } <span class="keyword">catch</span> (\<span class="keyword">Exception</span> $exception) {</span><br><span class="line"> DB::rollBack();</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> ApiException($exception->getMessage(), <span class="number">500</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"> * 微信统一下单</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> $orderId</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> $userId</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 class="doctag">@throws</span> ApiException</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@throws</span> GuzzleException</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">payOrder</span><span class="params">($orderId, $userId)</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> $orderInfo = <span class="keyword">$this</span>->findOrderByOrderId($orderId);</span><br><span class="line"> <span class="keyword">if</span> (!$orderInfo || $orderInfo->user_id != $userId) {</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> ApiException(<span class="string">'订单不存在'</span>, <span class="number">500</span>);</span><br><span class="line"> }</span><br><span class="line"> $userInfo = (<span class="keyword">new</span> UserService())->findUserById($userId, [<span class="string">'openid'</span>]);</span><br><span class="line"> <span class="keyword">if</span> (!$userInfo) {</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> ApiException(<span class="string">'用户不存在'</span>, <span class="number">500</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (!$userInfo->openid) {</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> ApiException(<span class="string">'请先绑定微信'</span>, <span class="number">500</span>);</span><br><span class="line"> }</span><br><span class="line"> $payParam = config(<span class="string">'wechat.config'</span>);</span><br><span class="line"> <span class="comment">//统一下单参数</span></span><br><span class="line"> $payConfig = [</span><br><span class="line"> <span class="string">'appid'</span> => $payParam[<span class="string">'appId'</span>],</span><br><span class="line"> <span class="string">'mchid'</span> => $payParam[<span class="string">'mchId'</span>],</span><br><span class="line"> <span class="string">'description'</span> => $orderInfo[<span class="string">'price'</span>] . <span class="string">'话费充值-话费慢充72小时内到账'</span>,</span><br><span class="line"> <span class="string">'out_trade_no'</span> => $orderId,</span><br><span class="line"> <span class="string">'notify_url'</span> => $payParam[<span class="string">'notifyUrl'</span>],</span><br><span class="line"> <span class="string">'amount'</span> => [</span><br><span class="line"> <span class="string">'total'</span> => $orderInfo[<span class="string">'price'</span>],</span><br><span class="line"> <span class="string">'currency'</span> => <span class="string">'CNY'</span></span><br><span class="line"> ],</span><br><span class="line"> <span class="string">'payer'</span> => [</span><br><span class="line"> <span class="string">'openid'</span> => $userInfo[<span class="string">'openid'</span>]</span><br><span class="line"> ]</span><br><span class="line"> ];</span><br><span class="line"> <span class="comment">// 重点,微信apiv3必须在headers里设置四个参数</span></span><br><span class="line"> $client = <span class="keyword">new</span> Client();</span><br><span class="line"> $httpClient = $client->post($payParam[<span class="string">'payUrl'</span>], [</span><br><span class="line"> <span class="string">'headers'</span> => [</span><br><span class="line"> <span class="string">'Content-Type'</span> => <span class="string">'application/json'</span>,</span><br><span class="line"> <span class="string">'User-Agent'</span> => <span class="string">'Mozilla/4.0'</span>,</span><br><span class="line"> <span class="string">'Accept'</span> => <span class="string">'application/json'</span>,</span><br><span class="line"> <span class="string">'Authorization'</span> => StringHelper::getAuth($payParam[<span class="string">'payUrl'</span>], json_encode($payConfig), <span class="string">'POST'</span>)</span><br><span class="line"> ],</span><br><span class="line"> <span class="string">'json'</span> => $payConfig</span><br><span class="line"> ]);</span><br><span class="line"> $result = $httpClient->getBody()</span><br><span class="line"> ->getContents();</span><br><span class="line"> $payResult = json_decode($result, <span class="keyword">true</span>);</span><br><span class="line"> <span class="keyword">if</span> ($httpClient->getStatusCode() != <span class="number">200</span>) {</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> ApiException(<span class="string">'支付错误'</span>, <span class="number">500</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (<span class="keyword">isset</span>($payResult[<span class="string">'errcode'</span>])) {</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> ApiException($payResult[<span class="string">'errmsg'</span>], <span class="number">500</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (<span class="keyword">isset</span>($payResult[<span class="string">'code'</span>])) {</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> ApiException($payResult[<span class="string">'code'</span>], <span class="number">500</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">// 获取支付参数</span></span><br><span class="line"> $appId = $payParam[<span class="string">'appId'</span>];</span><br><span class="line"> $time = time();</span><br><span class="line"> $str = StringHelper::createNonce();</span><br><span class="line"> $prepayId = <span class="string">'prepay_id='</span> . $payResult[<span class="string">'prepay_id'</span>];</span><br><span class="line"> $message = $appId . <span class="string">"\n"</span> .</span><br><span class="line"> $time . <span class="string">"\n"</span> .</span><br><span class="line"> $str . <span class="string">"\n"</span> .</span><br><span class="line"> $prepayId . <span class="string">"\n"</span>;</span><br><span class="line"> <span class="keyword">return</span> [</span><br><span class="line"> <span class="string">'appId'</span> => $payParam[<span class="string">'appId'</span>],</span><br><span class="line"> <span class="string">'timeStamp'</span> => $time,</span><br><span class="line"> <span class="string">'nonceStr'</span> => $str,</span><br><span class="line"> <span class="string">'package'</span> => <span class="string">'prepay_id='</span> . $payResult[<span class="string">'prepay_id'</span>],</span><br><span class="line"> <span class="string">'signType'</span> => <span class="string">'RSA'</span>,</span><br><span class="line"> <span class="string">'paySign'</span> => StringHelper::getSign($message)</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="keyword">public</span> <span class="keyword">static</span> <span class="function"><span class="keyword">function</span> <span class="title">createNonce</span><span class="params">($length = <span class="number">32</span>)</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> $chars = <span class="string">"abcdefghijklmnopqrstuvwxyz0123456789"</span>;</span><br><span class="line"> $str = <span class="string">""</span>;</span><br><span class="line"> <span class="keyword">for</span> ($i = <span class="number">0</span>; $i < $length; $i++) {</span><br><span class="line"> $str .= substr($chars, mt_rand(<span class="number">0</span>, strlen($chars) - <span class="number">1</span>), <span class="number">1</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> $str;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 生成auth</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">getAuth</span><span class="params">($url, $body, $type = <span class="string">'POST'</span>)</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> $config = Config::get(<span class="string">'wechat.config'</span>);</span><br><span class="line"> $nonce = <span class="keyword">self</span>::createNonce();</span><br><span class="line"> $timestamp = time();</span><br><span class="line"> $url_parts = parse_url($url);</span><br><span class="line"> $canonical_url = ($url_parts[<span class="string">'path'</span>] . (!<span class="keyword">empty</span>($url_parts[<span class="string">'query'</span>]) ? <span class="string">"?${url_parts['query']}"</span> : <span class="string">""</span>));</span><br><span class="line"> $message = $type . <span class="string">"\n"</span> .</span><br><span class="line"> $canonical_url . <span class="string">"\n"</span> .</span><br><span class="line"> $timestamp . <span class="string">"\n"</span> .</span><br><span class="line"> $nonce . <span class="string">"\n"</span> .</span><br><span class="line"> $body . <span class="string">"\n"</span>;</span><br><span class="line"> $sign = <span class="keyword">self</span>::getSign($message);</span><br><span class="line"> $schema = <span class="string">'WECHATPAY2-SHA256-RSA2048'</span>;</span><br><span class="line"> $token = sprintf(<span class="string">'mchid="%s",nonce_str="%s",timestamp="%d",serial_no="%s",signature="%s"'</span>,</span><br><span class="line"> $config[<span class="string">'mchId'</span>], $nonce, $timestamp, $config[<span class="string">'serialNo'</span>], $sign);</span><br><span class="line"> <span class="keyword">return</span> $schema . <span class="string">' '</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="keyword">public</span> <span class="keyword">static</span> <span class="function"><span class="keyword">function</span> <span class="title">getSign</span><span class="params">($message)</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> $filePath = <span class="string">'../resources/cert/apiclient_key.pem'</span>;</span><br><span class="line"> openssl_sign($message, $raw_sign, openssl_get_privatekey(file_get_contents($filePath)), <span class="string">'sha256WithRSAEncryption'</span>);</span><br><span class="line"> <span class="keyword">return</span> base64_encode($raw_sign);</span><br><span class="line"> }</span><br></pre></td></tr></table></figure></p><h4 id="完成支付"><a href="#完成支付" class="headerlink" title="完成支付"></a>完成支付</h4><p>这篇文章没有使用微信的sdk,所以代码量还有有点大的,不过整体逻辑简单。</p>]]></content>
<summary type="html">
<h4 id="微信支付文档"><a href="#微信支付文档" class="headerlink" title="微信支付文档"></a>微信支付文档</h4><p><a herf="https://pay.weixin.qq.com/wiki/doc/apiv3/apis/chapter3_1_1.shtml">统一下单文档JsApi</a></p>
<h4 id="前期准备流程"><a href="#前期准备流程" class="headerlink" title="前期准备流程"></a>前期准备流程</h4><ol>
<li>微信公众号申请</li>
<li>支付商户号申请</li>
<li>微信公众号绑定支付商户号</li></ol>
</summary>
<category term="微信支付" scheme="http://www.daichongweb.com/tags/%E5%BE%AE%E4%BF%A1%E6%94%AF%E4%BB%98/"/>
</entry>
<entry>
<title>JetBrains2020全家桶激活</title>
<link href="http://www.daichongweb.com/JetBrains2020%E5%85%A8%E5%AE%B6%E6%A1%B6%E6%BF%80%E6%B4%BB/"/>
<id>http://www.daichongweb.com/JetBrains2020全家桶激活/</id>
<published>2020-08-19T02:28:42.000Z</published>
<updated>2021-09-03T05:56:57.858Z</updated>
<content type="html"><![CDATA[<h4 id="官方下载最新版"><a href="#官方下载最新版" class="headerlink" title="官方下载最新版"></a>官方下载最新版</h4><a href="https://www.jetbrains.com" target="_blank" rel="noopener">JetBrains官网下载</a><h5 id="亲测可激活"><a href="#亲测可激活" class="headerlink" title="亲测可激活"></a>亲测可激活</h5><blockquote><p>1.IntelliJ IDEA 2020.2及以下版本<br>2.PhpStorm 2020.2及以下版本<br>3.WebStorm 2020.2及以下版本<br><a id="more"></a></p></blockquote><h4 id="下载补丁"><a href="#下载补丁" class="headerlink" title="下载补丁"></a>下载补丁</h4><a href="https://www.daichongweb.cn/image/jetbrains-agent-2020.jar" target="_blank" rel="noopener">下载补丁</a><h4 id="如何激活"><a href="#如何激活" class="headerlink" title="如何激活"></a>如何激活</h4><p> (1).运行IDE(新安装的选择<code>Evaluate</code>)</p><p> (2).随便打开或者创建一个项目,成功后保持不动</p><p> (3).把补丁解压后的<code>jetbrains-agent.jar</code>拖入到IDE中,弹框后点击<code>Restart</code>。</p><p> (4).重启后会弹出【JetbrainsAgent 配置助手】,选择<code>Activation Code</code>,复制下面的安装参数,然后点击为<code>XXX</code>安装就可以了!!!</p><h4 id="安装参数"><a href="#安装参数" class="headerlink" title="安装参数"></a>安装参数</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">LFq51qqupnaiTNn39w6zATiOTxZI2JYuRJEBlzmUDv4zeeNlXhMgJZVb0q5QkLr+CIUrSuNB7ucifrGXawLB4qswPOXYG7+ItDNUR/<span class="number">9</span>UkLTUWlnHLX07hnR1USOrWIjTmbytcIKEdaI6x0RskyotuItj84xxoSBP/iRBW2EHpOc</span><br></pre></td></tr></table></figure><h4 id="常见问题"><a href="#常见问题" class="headerlink" title="常见问题"></a>常见问题</h4><p> (1).安装成功后还是跳转到激活页面,请尝试断网后再操作。<br> (2).断网后还是无法破解,请尝试删除hosts设置的映射后再操作。</p><h4 id="致谢🙏"><a href="#致谢🙏" class="headerlink" title="致谢🙏"></a>致谢🙏</h4><p> 好用的话就请评论一下再走吧!</p>]]></content>
<summary type="html">
<h4 id="官方下载最新版"><a href="#官方下载最新版" class="headerlink" title="官方下载最新版"></a>官方下载最新版</h4><a href="https://www.jetbrains.com" target="_blank" rel="noopener">JetBrains官网下载</a>
<h5 id="亲测可激活"><a href="#亲测可激活" class="headerlink" title="亲测可激活"></a>亲测可激活</h5><blockquote>
<p>1.IntelliJ IDEA 2020.2及以下版本<br>2.PhpStorm 2020.2及以下版本<br>3.WebStorm 2020.2及以下版本<br></p></blockquote>
</summary>
<category term="开发工具" scheme="http://www.daichongweb.com/tags/%E5%BC%80%E5%8F%91%E5%B7%A5%E5%85%B7/"/>
</entry>
<entry>
<title>fastjson类型转换</title>
<link href="http://www.daichongweb.com/fastjson%E7%B1%BB%E5%9E%8B%E8%BD%AC%E6%8D%A2/"/>
<id>http://www.daichongweb.com/fastjson类型转换/</id>
<published>2020-05-25T03:15:32.000Z</published>
<updated>2021-09-03T05:56:57.912Z</updated>
<content type="html"><![CDATA[<h4 id="jsonString转map"><a href="#jsonString转map" class="headerlink" title="jsonString转map"></a>jsonString转map</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">JSON.parseObject(string)</span><br></pre></td></tr></table></figure><h4 id="实体类转jsonstring"><a href="#实体类转jsonstring" class="headerlink" title="实体类转jsonstring"></a>实体类转jsonstring</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">JSON.toJSONString(javaClass)</span><br></pre></td></tr></table></figure><a id="more"></a><h4 id="存入redis队列之前是jsonString,拿出来变成object处理办法"><a href="#存入redis队列之前是jsonString,拿出来变成object处理办法" class="headerlink" title="存入redis队列之前是jsonString,拿出来变成object处理办法"></a>存入redis队列之前是jsonString,拿出来变成object处理办法</h4><figure class="highlight java"><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">// 先转字符</span></span><br><span class="line">String value = lotteryData.index(roomId, userId).toString();</span><br><span class="line"><span class="comment">// 转map</span></span><br><span class="line">JSON.parseObject(value);</span><br></pre></td></tr></table></figure><h4 id="如何组成一个多维数组"><a href="#如何组成一个多维数组" class="headerlink" title="如何组成一个多维数组"></a>如何组成一个多维数组</h4><figure class="highlight java"><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></pre></td><td class="code"><pre><span class="line"><span class="comment">// 例子</span></span><br><span class="line">{</span><br><span class="line"> <span class="string">"data"</span>: [</span><br><span class="line"> {</span><br><span class="line"> <span class="string">"nickname"</span>: <span class="string">"戴崇"</span>,</span><br><span class="line"> <span class="string">"userId"</span>: <span class="number">6144</span>,</span><br><span class="line"> <span class="string">"roomId"</span>: <span class="number">10086</span></span><br><span class="line"> },</span><br><span class="line"> {</span><br><span class="line"> <span class="string">"nickname"</span>: <span class="string">"戴崇"</span>,</span><br><span class="line"> <span class="string">"userId"</span>: <span class="number">2174</span>,</span><br><span class="line"> <span class="string">"roomId"</span>: <span class="number">10086</span></span><br><span class="line"> },</span><br><span class="line"> {</span><br><span class="line"> <span class="string">"nickname"</span>: <span class="string">"戴崇"</span>,</span><br><span class="line"> <span class="string">"userId"</span>: <span class="number">9997</span>,</span><br><span class="line"> <span class="string">"roomId"</span>: <span class="number">10086</span></span><br><span class="line"> }</span><br><span class="line"> ],</span><br><span class="line"> <span class="string">"code"</span>: <span class="string">"0"</span>,</span><br><span class="line"> <span class="string">"msg"</span>: <span class="string">"操作成功!"</span></span><br><span class="line">}</span><br><span class="line"><span class="comment">// 做法</span></span><br><span class="line">List<Map<String, Object>> list = <span class="keyword">new</span> ArrayList<>();</span><br><span class="line"><span class="keyword">for</span> (<span class="keyword">long</span> userId : rands) {</span><br><span class="line"> <span class="keyword">if</span> (userId == <span class="number">0</span>) {</span><br><span class="line"> <span class="keyword">continue</span>;</span><br><span class="line"> }</span><br><span class="line"> String value = lotteryData.index(roomId, userId).toString();</span><br><span class="line"> list.add(JSON.parseObject(value));</span><br><span class="line">}</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
<h4 id="jsonString转map"><a href="#jsonString转map" class="headerlink" title="jsonString转map"></a>jsonString转map</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">JSON.parseObject(string)</span><br></pre></td></tr></table></figure>
<h4 id="实体类转jsonstring"><a href="#实体类转jsonstring" class="headerlink" title="实体类转jsonstring"></a>实体类转jsonstring</h4><figure class="highlight java"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">JSON.toJSONString(javaClass)</span><br></pre></td></tr></table></figure>
</summary>
<category term="java" scheme="http://www.daichongweb.com/tags/java/"/>
</entry>
<entry>
<title>mac下使用homebrew安装指定版本node</title>
<link href="http://www.daichongweb.com/mac%E4%B8%8B%E4%BD%BF%E7%94%A8homebrew%E5%AE%89%E8%A3%85%E6%8C%87%E5%AE%9A%E7%89%88%E6%9C%ACnode/"/>
<id>http://www.daichongweb.com/mac下使用homebrew安装指定版本node/</id>
<published>2020-05-10T11:21:41.000Z</published>
<updated>2021-09-03T05:56:57.931Z</updated>
<content type="html"><![CDATA[<h4 id="介绍"><a href="#介绍" class="headerlink" title="介绍"></a>介绍</h4><p> mac下的homebrew直接使用<code>brew install node</code>安装的node版本是<code>14.+</code>,这给很多程序带来了问题,如果直接安装低版本的node会造成‘npm’等无法使用。</p><h4 id="卸载"><a href="#卸载" class="headerlink" title="卸载"></a>卸载</h4><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">brew remove node</span><br></pre></td></tr></table></figure><a id="more"></a><h4 id="解绑"><a href="#解绑" class="headerlink" title="解绑"></a>解绑</h4><p> 卸载之后要先把之前node解除连接。<br><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">brew unlink node</span><br></pre></td></tr></table></figure></p><h4 id="查找可用的node版本"><a href="#查找可用的node版本" class="headerlink" title="查找可用的node版本"></a>查找可用的node版本</h4><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">brew search node</span><br></pre></td></tr></table></figure><img src="/mac下使用homebrew安装指定版本node/img/2.png" width="500"><h4 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h4><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">brew install node@10</span><br></pre></td></tr></table></figure><img src="/mac下使用homebrew安装指定版本node/img/3.png" width="500"><h4 id="添加环境变量"><a href="#添加环境变量" class="headerlink" title="添加环境变量"></a>添加环境变量</h4><figure class="highlight shell"><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">vi ~/.bash_profile</span><br><span class="line">export PATH="/usr/local/opt/node@10/bin:$PATH"</span><br></pre></td></tr></table></figure><img src="/mac下使用homebrew安装指定版本node/img/4.png" width="500"><p> 经过此步骤还是无法在终端使用‘node -v’就增加<br><figure class="highlight shell"><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">vi ~/.bash_profile</span><br><span class="line">alias node='/usr/local/opt/node@10/bin/node'</span><br></pre></td></tr></table></figure></p><p> 无法使用<code>npm</code>等情况执行<br><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">brew link --overwrite --force node@10</span><br></pre></td></tr></table></figure></p>]]></content>
<summary type="html">
<h4 id="介绍"><a href="#介绍" class="headerlink" title="介绍"></a>介绍</h4><p>&emsp;mac下的homebrew直接使用<code>brew install node</code>安装的node版本是<code>14.+</code>,这给很多程序带来了问题,如果直接安装低版本的node会造成‘npm’等无法使用。</p>
<h4 id="卸载"><a href="#卸载" class="headerlink" title="卸载"></a>卸载</h4><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">brew remove node</span><br></pre></td></tr></table></figure>
</summary>
<category term="node" scheme="http://www.daichongweb.com/tags/node/"/>
</entry>
<entry>
<title>php生成海报图出现图片损坏的问题</title>
<link href="http://www.daichongweb.com/php%E7%94%9F%E6%88%90%E6%B5%B7%E6%8A%A5%E5%9B%BE%E5%87%BA%E7%8E%B0%E5%9B%BE%E7%89%87%E6%8D%9F%E5%9D%8F%E7%9A%84%E9%97%AE%E9%A2%98/"/>
<id>http://www.daichongweb.com/php生成海报图出现图片损坏的问题/</id>
<published>2020-05-10T08:52:30.000Z</published>
<updated>2021-09-03T05:56:57.961Z</updated>
<content type="html"><![CDATA[<h4 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h4><p> 近年小程序、微信发展迅速。微信、微博病毒式传播使用户从传统的APP上向<code>即扫即用、无需安装</code>的小程序上转化。而微信公众号、小程序的迅速发展离不开转发、二维码分享。</p><p> 但是二维码形式单一,对用户来说毫无吸引力。纯粹依靠‘吆喝、金钱、礼物吸引’方式已经变得愈来愈无价值。</p><p> 对于’视觉动物’和大部分用户来说,精美的图片加上二维码的组合更具有吸引力。<br><a id="more"></a><br><img src="/php生成海报图出现图片损坏的问题/img/3.jpg"></p><h4 id="php生成海报图前提条件"><a href="#php生成海报图前提条件" class="headerlink" title="php生成海报图前提条件"></a>php生成海报图前提条件</h4><ul><li>gd库扩展</li></ul><h4 id="上代码"><a href="#上代码" class="headerlink" title="上代码"></a>上代码</h4><h5 id="生成方法"><a href="#生成方法" class="headerlink" title="生成方法"></a>生成方法</h5><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></pre></td><td class="code"><pre><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">createPoster</span><span class="params">($data)</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> $poster = <span class="keyword">new</span> Poster();</span><br><span class="line"> <span class="comment">//创建画布</span></span><br><span class="line"> $im = $poster->createTrueColor(<span class="number">672</span>, <span class="number">1060</span>);</span><br><span class="line"> <span class="comment">//字体文件</span></span><br><span class="line"> $font_file = <span class="keyword">$this</span>->typeface;</span><br><span class="line"> <span class="comment">// 商品图片</span></span><br><span class="line"> $goodsImg = $poster->createImgBoard($im, $data[<span class="string">'goodsPath'</span>], <span class="number">0</span>, <span class="number">0</span>, <span class="number">672</span>, <span class="number">668</span>);</span><br><span class="line"> <span class="comment">//二维码</span></span><br><span class="line"> $codeImg = $poster->createImgBoard($im, $data[<span class="string">'qrcode'</span>], <span class="number">410</span>, <span class="number">710</span>, <span class="number">225</span>, <span class="number">225</span>);</span><br><span class="line"> <span class="comment">//headimg</span></span><br><span class="line"> $headImg = $poster->createImgBoard($im, $data[<span class="string">'headimg'</span>], <span class="number">46</span>, <span class="number">942</span>, <span class="number">65</span>, <span class="number">65</span>);</span><br><span class="line"> <span class="comment">//btnimg</span></span><br><span class="line"> $btnimg = $poster->createImgBoard($im, $data[<span class="string">'btn'</span>], <span class="number">420</span>, <span class="number">960</span>, <span class="number">220</span>, <span class="number">48</span>);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 价格</span></span><br><span class="line"> $price_font = ImageColorAllocate($im, <span class="number">248</span>, <span class="number">6</span>, <span class="number">74</span>);</span><br><span class="line"> imagettftext($im, <span class="number">25</span>, <span class="number">0</span>, <span class="number">41</span>, <span class="number">759</span>, $price_font, $font_file, <span class="string">'¥'</span>);</span><br><span class="line"> imagettftext($im, <span class="number">38</span>, <span class="number">0</span>, <span class="number">60</span>, <span class="number">760</span>, $price_font, $font_file, $data[<span class="string">"price"</span>]);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 商品名称</span></span><br><span class="line"> $goodsName = trim(mb_substr($data[<span class="string">'title'</span>], <span class="number">0</span>, <span class="number">20</span>));</span><br><span class="line"> $good_font = ImageColorAllocate($im, <span class="number">1</span>, <span class="number">1</span>, <span class="number">1</span>);</span><br><span class="line"> imagettftext($im, <span class="number">24</span>, <span class="number">0</span>, <span class="number">40</span>, <span class="number">820</span>, $good_font, $font_file, $poster->AutoWrap(<span class="number">12</span>, <span class="number">0</span>, $font_file, $goodsName, <span class="number">160</span>));</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 昵称</span></span><br><span class="line"> $nickname = trim(mb_substr($data[<span class="string">'nickname'</span>], <span class="number">0</span>, <span class="number">8</span>));</span><br><span class="line"> $nick_font = ImageColorAllocate($im, <span class="number">109</span>, <span class="number">114</span>, <span class="number">120</span>);</span><br><span class="line"> imagettftext($im, <span class="number">16</span>, <span class="number">0</span>, <span class="number">130</span>, <span class="number">965</span>, $nick_font, $font_file, $poster->AutoWrap(<span class="number">12</span>, <span class="number">0</span>, $font_file, $nickname, <span class="number">80</span>));</span><br><span class="line"> imagettftext($im, <span class="number">16</span>, <span class="number">0</span>, <span class="number">130</span>, <span class="number">1000</span>, $nick_font, $font_file, $data[<span class="string">'time'</span>]);</span><br><span class="line"> ob_clean();</span><br><span class="line"> ob_end_clean();</span><br><span class="line"> <span class="comment">// 输出图片</span></span><br><span class="line"> $poster->lookImg($im);</span><br><span class="line"></span><br><span class="line"> <span class="comment">//释放空间</span></span><br><span class="line"> imagedestroy($im);</span><br><span class="line"> imagedestroy($btnimg);</span><br><span class="line"> imagedestroy($goodsImg);</span><br><span class="line"> imagedestroy($codeImg);</span><br><span class="line"> imagedestroy($headImg);</span><br><span class="line"> <span class="comment">// 删除本地二维码</span></span><br><span class="line"> Qrcode::deleteCode($data[<span class="string">'qrcode'</span>]);</span><br><span class="line"> }</span><br></pre></td></tr></table></figure><h5 id="实现类"><a href="#实现类" class="headerlink" title="实现类"></a>实现类</h5><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></pre></td><td class="code"><pre><span class="line"><span class="comment">// 具体类</span></span><br><span class="line"><span class="meta"><?php</span></span><br><span class="line"><span class="keyword">namespace</span> <span class="title">app</span>\<span class="title">library</span>;</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 class="doctag">@author</span> daichongweb</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@url</span> daichongweb.cn,daichongweb.com</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">Poster</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"> * 从图片文件创建Image资源</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> $file 图片文件,支持url</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> bool|resource 成功返回图片image资源,失败返回false</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">createImageFromFile</span><span class="params">($file)</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="keyword">if</span> (preg_match(<span class="string">'/http(s)?:\/\//'</span>, $file)) {</span><br><span class="line"> $fileSuffix = <span class="keyword">self</span>::getNetworkImgType($file);</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> $file_info = getimagesize($file);</span><br><span class="line"> $fileSuffix = $file_info[<span class="number">2</span>];</span><br><span class="line"> <span class="comment">// $fileSuffix = pathinfo($file, PATHINFO_EXTENSION);</span></span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (!$fileSuffix) <span class="keyword">return</span> <span class="keyword">false</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">switch</span> ($fileSuffix) {</span><br><span class="line"> <span class="comment">/*case 'jpeg':</span></span><br><span class="line"><span class="comment"> $theImage = <span class="doctag">@imagecreatefromjpeg</span>($file);</span></span><br><span class="line"><span class="comment"> break;*/</span></span><br><span class="line"> <span class="keyword">case</span> <span class="string">'2'</span>:</span><br><span class="line"> $theImage = imagecreatefromjpeg($file);</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> <span class="keyword">case</span> <span class="string">'3'</span>:</span><br><span class="line"> $theImage = @imagecreatefrompng($file);</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> <span class="keyword">case</span> <span class="string">'1'</span>:</span><br><span class="line"> $theImage = @imagecreatefromgif($file);</span><br><span class="line"> <span class="keyword">break</span>;</span><br><span class="line"> <span class="keyword">default</span>:</span><br><span class="line"> $theImage = @imagecreatefromstring(file_get_contents($file));</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"> <span class="keyword">return</span> $theImage;</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">public</span> <span class="function"><span class="keyword">function</span> <span class="title">AutoWrap</span><span class="params">($fontsize, $angle, $fontface, $string, $width)</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> $content = <span class="string">""</span>;</span><br><span class="line"> <span class="keyword">for</span> ($i = <span class="number">0</span>; $i < mb_strlen($string); $i++) {</span><br><span class="line"> $letter[] = mb_substr($string, $i, <span class="number">1</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">foreach</span> ($letter <span class="keyword">as</span> $l) {</span><br><span class="line"> $teststr = $content . <span class="string">""</span> . $l;</span><br><span class="line"> $testbox = imagettfbbox($fontsize, $angle, $fontface, $teststr);</span><br><span class="line"> <span class="keyword">if</span> (($testbox[<span class="number">2</span>] > $width) && ($content !== <span class="string">""</span>)) {</span><br><span class="line"> $content .= <span class="string">"\n"</span>;</span><br><span class="line"> }</span><br><span class="line"> $content .= $l;</span><br><span class="line"> }</span><br><span class="line"> $content = mb_convert_encoding($content, <span class="string">"html-entities"</span>, <span class="string">"utf-8"</span>);</span><br><span class="line"> <span class="keyword">return</span> $content;</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">getNetworkImgType</span><span class="params">($url)</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> $ch = curl_init();</span><br><span class="line"> curl_setopt($ch, CURLOPT_URL, $url);</span><br><span class="line"> curl_setopt($ch, CURLOPT_NOBODY, <span class="number">1</span>);</span><br><span class="line"> curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, <span class="number">3</span>);</span><br><span class="line"> curl_setopt($ch, CURLOPT_TIMEOUT, <span class="number">3</span>);</span><br><span class="line"> curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, <span class="keyword">false</span>);</span><br><span class="line"> curl_exec($ch);</span><br><span class="line"> $http_code = curl_getinfo($ch);</span><br><span class="line"> curl_close($ch);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> ($http_code[<span class="string">'http_code'</span>] == <span class="number">200</span>) {</span><br><span class="line"> $theImgType = explode(<span class="string">'/'</span>, $http_code[<span class="string">'content_type'</span>]);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> ($theImgType[<span class="number">0</span>] == <span class="string">'image'</span>) {</span><br><span class="line"> <span class="keyword">return</span> $theImgType[<span class="number">1</span>];</span><br><span class="line"> } <span class="keyword">else</span> {</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 class="keyword">else</span> {</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><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> int $width</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> int $height</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> int $r</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> int $g</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> int $b</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> false|resource</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">createTrueColor</span><span class="params">(int $width, int $height, $r = <span class="number">255</span>, $g = <span class="number">255</span>, $b = <span class="number">255</span>)</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> $im = imagecreatetruecolor($width, $height);</span><br><span class="line"> $color = imagecolorallocate($im, $r, $g, $b);</span><br><span class="line"> imagefill($im, <span class="number">0</span>, <span class="number">0</span>, $color);</span><br><span class="line"> <span class="keyword">return</span> $im;</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 class="doctag">@param</span> $im</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> $imgUrl</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> $dst_w</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> $dst_h</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> bool|resource</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">createImgBoard</span><span class="params">($im, $imgUrl, $dst_x, $dst_y, $dst_w, $dst_h)</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="keyword">list</span>($width, $height) = getimagesize($imgUrl);</span><br><span class="line"> $imgBoard = Poster::createImageFromFile($imgUrl);</span><br><span class="line"> imagecopyresized($im, $imgBoard, $dst_x, $dst_y, <span class="number">0</span>, <span class="number">0</span>, $dst_w, $dst_h, $width, $height);</span><br><span class="line"> <span class="keyword">return</span> $imgBoard;</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">@param</span> $im</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">lookImg</span><span class="params">($im)</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> header(<span class="string">"Content-type:text/html;charset=utf-8"</span>);</span><br><span class="line"> Header(<span class="string">"Content-Type: image/jpeg"</span>); <span class="comment">// jpeg 生成会更快,png生成速度慢但是高清</span></span><br><span class="line"> imagejpeg($im);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h5 id="使用方法"><a href="#使用方法" class="headerlink" title="使用方法"></a>使用方法</h5><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="comment">// 获取微信二维码</span></span><br><span class="line">$codePath = Qrcode::createQrcode([</span><br><span class="line"> <span class="string">'scene'</span> => $scene,</span><br><span class="line"> <span class="string">'page'</span> => $path,</span><br><span class="line"> <span class="string">'width'</span> => <span class="string">'112'</span>,</span><br><span class="line"> <span class="string">'auto_color'</span> => <span class="keyword">false</span>,</span><br><span class="line"> <span class="string">'line_color'</span> => [</span><br><span class="line"> <span class="string">'r'</span> => <span class="number">0</span>,</span><br><span class="line"> <span class="string">'g'</span> => <span class="number">0</span>,</span><br><span class="line"> <span class="string">'b'</span> => <span class="number">0</span></span><br><span class="line"> ]</span><br><span class="line">]);</span><br><span class="line">$data = [</span><br><span class="line"> <span class="string">'bg'</span> => <span class="keyword">$this</span>->bg,</span><br><span class="line"> <span class="string">'goodsPath'</span> => $goodsPath,</span><br><span class="line"> <span class="string">'title'</span> => $goodsName,</span><br><span class="line"> <span class="string">'price'</span> => $goodsPrice,</span><br><span class="line"> <span class="string">'btn'</span> => <span class="keyword">$this</span>->btn,</span><br><span class="line"> <span class="string">'time'</span> => date(<span class="string">'Y-m-d H:i'</span>),</span><br><span class="line"> <span class="string">'qrcode'</span> => $codePath,</span><br><span class="line"> <span class="string">'headimg'</span> => $userInfo->headimgurl ? $userInfo->headimgurl : <span class="keyword">$this</span>->defaultHeadImg,</span><br><span class="line"> <span class="string">'nickname'</span> => $userInfo->nickname ? $userInfo->nickname : <span class="string">'特抱抱'</span></span><br><span class="line">];</span><br><span class="line"><span class="keyword">$this</span>->createPoster($data);</span><br></pre></td></tr></table></figure><h4 id="效果图"><a href="#效果图" class="headerlink" title="效果图"></a>效果图</h4><div style="display: flex;justify-content: space-around;"><br> <div style="display: inline-block;"><img src="/php生成海报图出现图片损坏的问题/img/1.jpg" width="300"></div><div style="display: inline-block;"><img src="/php生成海报图出现图片损坏的问题/img/2.jpg" width="300"></div><br></div><p> 从上面两个图很明显可以看出,第二张图下面被切掉了,而且电脑是打不开的。解决这个问题的关键在于<code>ob_clean();ob_end_clean();</code>两个函数。</p><h4 id="解决方法"><a href="#解决方法" class="headerlink" title="解决方法"></a>解决方法</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></pre></td><td class="code"><pre><span class="line"><span class="comment">// 清空缓冲区</span></span><br><span class="line">ob_clean();</span><br><span class="line">ob_end_clean();</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
<h4 id="简介"><a href="#简介" class="headerlink" title="简介"></a>简介</h4><p>&emsp;近年小程序、微信发展迅速。微信、微博病毒式传播使用户从传统的APP上向<code>即扫即用、无需安装</code>的小程序上转化。而微信公众号、小程序的迅速发展离不开转发、二维码分享。</p>
<p>&emsp;但是二维码形式单一,对用户来说毫无吸引力。纯粹依靠‘吆喝、金钱、礼物吸引’方式已经变得愈来愈无价值。</p>
<p>&emsp;对于’视觉动物’和大部分用户来说,精美的图片加上二维码的组合更具有吸引力。<br></p>
</summary>
<category term="php" scheme="http://www.daichongweb.com/tags/php/"/>
</entry>
<entry>
<title>微信小程序支付</title>
<link href="http://www.daichongweb.com/%E5%BE%AE%E4%BF%A1%E5%B0%8F%E7%A8%8B%E5%BA%8F%E6%94%AF%E4%BB%98/"/>
<id>http://www.daichongweb.com/微信小程序支付/</id>
<published>2020-05-10T06:57:38.000Z</published>
<updated>2021-09-03T05:56:57.977Z</updated>
<content type="html"><![CDATA[<h4 id="小程序支付"><a href="#小程序支付" class="headerlink" title="小程序支付"></a>小程序支付</h4><p> 现如今的小程序愈发重要,微信小程序开发也成为开发者必须掌握的重要的技能之一。<br> 经过多年的发展,小程序开发更新换代非常快,在最近的开发中发现之前小程序支付的写法已经完全不适用了,害得我研究了很久,特写一篇文章记录一下。</p><h4 id="开发前提"><a href="#开发前提" class="headerlink" title="开发前提"></a>开发前提</h4><p> (1)开通微信支付商户号。<br> (2)开通小程序。<br> (3)微信支付平台设置特约商户APPID,绑定小程序Appid。(这里要注意,小程序和支付商户必须是同一个主体)。<br> (4)小程序绑定微信支付商户号。</p><a id="more"></a><h4 id="具体差别"><a href="#具体差别" class="headerlink" title="具体差别"></a>具体差别</h4><p> 可以从很久之前的文章看出,现在的小程序支付多了一个二次签名的步骤,这点需要大家注意。<br> 其他的步骤倒是没什么差别,具体可 <a href="https://pay.weixin.qq.com/wiki/doc/api/wxa/wxa_api.php?chapter=9_1" target="_blank" rel="noopener">官方文档</a>。</p><h4 id="上代码(废话不多说,yii2写法)"><a href="#上代码(废话不多说,yii2写法)" class="headerlink" title="上代码(废话不多说,yii2写法)"></a>上代码(废话不多说,yii2写法)</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></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">actionIndex</span><span class="params">()</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> $user_id = FsRequest::userId(<span class="string">'true'</span>);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (!$user_id) {</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> <span class="keyword">Exception</span>(<span class="string">'请先登录'</span>, [], <span class="number">201</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> $data = \Yii::$app->request->post();</span><br><span class="line"> <span class="keyword">if</span> (<span class="keyword">empty</span>($data)) {</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> <span class="keyword">Exception</span>(<span class="string">'参数不全'</span>, [], <span class="number">201</span>);</span><br><span class="line"> }</span><br><span class="line"> $openId = WeixinUser::find()->where([<span class="string">'ecuid'</span> => $user_id])->select([<span class="string">'dingdang_mini'</span>])->one();</span><br><span class="line"> <span class="keyword">if</span> (!$openId) {</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> <span class="keyword">Exception</span>(<span class="string">'未绑定小程序'</span>, [], <span class="number">201</span>);</span><br><span class="line"> }</span><br><span class="line"> $payParams = [</span><br><span class="line"> <span class="string">'appid'</span> => $appid,</span><br><span class="line"> <span class="string">'mch_id'</span> => $mch_id,</span><br><span class="line"> <span class="string">'nonce_str'</span> => WxHelper::createNoncestr(<span class="number">32</span>),</span><br><span class="line"> <span class="string">'sign'</span> => <span class="string">''</span>,</span><br><span class="line"> <span class="string">'body'</span> => $data[<span class="string">'body'</span>],</span><br><span class="line"> <span class="string">'out_trade_no'</span> => $data[<span class="string">'orderId'</span>],</span><br><span class="line"> <span class="string">'total_fee'</span> => (int)($data[<span class="string">'price'</span>] * <span class="number">100</span>),</span><br><span class="line"> <span class="string">'openid'</span> => $openId->dingdang_mini,</span><br><span class="line"> <span class="string">'spbill_create_ip'</span> => $_SERVER[<span class="string">'REMOTE_ADDR'</span>],</span><br><span class="line"> <span class="string">'notify_url'</span> => <span class="string">'支付回调'</span>,</span><br><span class="line"> <span class="string">'trade_type'</span> => <span class="string">'JSAPI'</span>,</span><br><span class="line"> ];</span><br><span class="line"></span><br><span class="line"> $payParams[<span class="string">'sign'</span>] = WxHelper::paySign($payParams, $key);</span><br><span class="line"> $xml = WxHelper::arrayToXml($payParams);</span><br><span class="line"> <span class="comment">// die($xml);</span></span><br><span class="line"> $payUrl = <span class="string">'https://api.mch.weixin.qq.com/pay/unifiedorder'</span>;</span><br><span class="line"></span><br><span class="line"> $curl = <span class="keyword">new</span> Curl();</span><br><span class="line"> $curl->setHeader(<span class="string">'Content-Type'</span>, <span class="string">'text/xml; charset=utf-8'</span>); <span class="comment">// xml</span></span><br><span class="line"> $curl->post($payUrl, $xml);</span><br><span class="line"> <span class="comment">// 请求失败</span></span><br><span class="line"> <span class="keyword">if</span> ($curl->error) {</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> <span class="keyword">Exception</span>($curl->errorMessage, [], <span class="number">201</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"> $result = WxHelper::xmlToArray($curl->response);</span><br><span class="line"> <span class="keyword">if</span> ($result[<span class="string">'result_code'</span>] == <span class="string">'FAIL'</span>) {</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> <span class="keyword">Exception</span>($result[<span class="string">'err_code_des'</span>], [], <span class="number">201</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">// 二次签名</span></span><br><span class="line"> $payParamsResult = [</span><br><span class="line"> <span class="string">'appId'</span> => <span class="keyword">$this</span>->appid,</span><br><span class="line"> <span class="string">'nonceStr'</span> => WxHelper::createNoncestr(<span class="number">32</span>),</span><br><span class="line"> <span class="string">'package'</span> => <span class="string">'prepay_id='</span> . $result[<span class="string">'prepay_id'</span>],</span><br><span class="line"> <span class="string">'paySign'</span> => <span class="string">''</span>,</span><br><span class="line"> <span class="string">'signType'</span> => <span class="string">'MD5'</span>,</span><br><span class="line"> <span class="string">'timeStamp'</span> => (string)time()</span><br><span class="line"> ];</span><br><span class="line"> $payParamsResult[<span class="string">'paySign'</span>] = WxHelper::paySign($payParamsResult, <span class="keyword">$this</span>->key);</span><br><span class="line"> FsResponse::jsonSuccess($payParamsResult);</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">return</span> FsResponse::jsonFaild($e->getCode(), $e->getMessage());</span><br><span class="line"> }</span><br><span class="line">}</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><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></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="keyword">namespace</span> <span class="title">app</span>\<span class="title">library</span>\<span class="title">wechat</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">use</span> \<span class="title">Curl</span>\<span class="title">Curl</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">app</span>\<span class="title">models</span>\<span class="title">redis</span>\<span class="title">WxAccessToken</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">yii</span>\<span class="title">db</span>\<span class="title">Exception</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * Class WxHelper</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@package</span> app\library</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">WxHelper</span></span></span><br><span class="line"><span class="class"></span>{</span><br><span class="line"> <span class="comment">// 获取小程序AccessToken</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">getToken</span><span class="params">()</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> $token = WxAccessToken::get();</span><br><span class="line"> <span class="keyword">if</span> (!$token) {</span><br><span class="line"> $url = <span class="string">'https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid='</span> . $appId . <span class="string">'&secret='</span> . $secret;</span><br><span class="line"> $curl = <span class="keyword">new</span> Curl();</span><br><span class="line"> $curl->get($url);</span><br><span class="line"> <span class="keyword">if</span> ($curl->error) {</span><br><span class="line"> WxAccessToken::delete();</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> <span class="keyword">Exception</span>($curl->errorMessage, [],<span class="number">210</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">if</span> (<span class="keyword">isset</span>($curl->response->errcode)) {</span><br><span class="line"> WxAccessToken::delete();</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> <span class="keyword">Exception</span>($curl->response->errmsg,[],<span class="number">210</span>);</span><br><span class="line"> }</span><br><span class="line"> $token = $curl->response->access_token;</span><br><span class="line"> $time = $curl->response->expires_in;</span><br><span class="line"> WxAccessToken::set($token, $time - <span class="number">100</span>);</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><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">xmlToArray</span><span class="params">($xml)</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="comment">//禁止引用外部xml实体</span></span><br><span class="line"> libxml_disable_entity_loader(<span class="keyword">true</span>);</span><br><span class="line"> $values = json_decode(json_encode(simplexml_load_string($xml, <span class="string">'SimpleXMLElement'</span>, LIBXML_NOCDATA)), <span class="keyword">true</span>);</span><br><span class="line"> <span class="keyword">return</span> $values;</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">paySign</span><span class="params">($payParams, $key)</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> ksort($payParams);</span><br><span class="line"> $signString = <span class="keyword">self</span>::toUrlParams($payParams);</span><br><span class="line"> $signString .= <span class="string">'&key='</span> . $key;</span><br><span class="line"> $signString = strtoupper(md5($signString));</span><br><span class="line"> <span class="keyword">return</span> $signString;</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">public</span> <span class="keyword">static</span> <span class="function"><span class="keyword">function</span> <span class="title">createNoncestr</span><span class="params">($length = <span class="number">7</span>)</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> $chars = <span class="string">"abcdefghijklmnopqrstuvwxyzABCDEFGHIGKLMNOPQRSTUVWXYZ0123456789"</span>;</span><br><span class="line"> $str = <span class="string">""</span>;</span><br><span class="line"> <span class="keyword">for</span> ($i = <span class="number">0</span>; $i < $length; $i++) {</span><br><span class="line"> $str .= substr($chars, mt_rand(<span class="number">0</span>, strlen($chars) - <span class="number">1</span>), <span class="number">1</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">return</span> $str;</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">toUrlParams</span><span class="params">($payParams)</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> $buff = <span class="string">""</span>;</span><br><span class="line"> <span class="keyword">foreach</span> ($payParams <span class="keyword">as</span> $k => $v) {</span><br><span class="line"> <span class="keyword">if</span> ($k != <span class="string">"sign"</span> && $v != <span class="string">""</span> && !is_array($v)) {</span><br><span class="line"> $buff .= $k . <span class="string">"="</span> . $v . <span class="string">"&"</span>;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> $buff = trim($buff, <span class="string">"&"</span>);</span><br><span class="line"> <span class="keyword">return</span> $buff;</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">arrayToXml</span><span class="params">($array)</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> $xml = <span class="string">"<xml>"</span>;</span><br><span class="line"> <span class="keyword">foreach</span> ($array <span class="keyword">as</span> $key => $val) {</span><br><span class="line"> <span class="keyword">if</span> (is_numeric($val)) {</span><br><span class="line"> $xml .= <span class="string">"<"</span> . $key . <span class="string">">"</span> . $val . <span class="string">"</"</span> . $key . <span class="string">">"</span>;</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> $xml .= <span class="string">"<"</span> . $key . <span class="string">"><![CDATA["</span> . $val . <span class="string">"]]></"</span> . $key . <span class="string">">"</span>;</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> $xml .= <span class="string">"</xml>"</span>;</span><br><span class="line"> <span class="keyword">return</span> $xml;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h4 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h4><p> 微信支付比较简单,只是文档写的不清晰导致开发难度增加。</p>]]></content>
<summary type="html">
<h4 id="小程序支付"><a href="#小程序支付" class="headerlink" title="小程序支付"></a>小程序支付</h4><p>&emsp;现如今的小程序愈发重要,微信小程序开发也成为开发者必须掌握的重要的技能之一。<br>&emsp;经过多年的发展,小程序开发更新换代非常快,在最近的开发中发现之前小程序支付的写法已经完全不适用了,害得我研究了很久,特写一篇文章记录一下。</p>
<h4 id="开发前提"><a href="#开发前提" class="headerlink" title="开发前提"></a>开发前提</h4><p>&emsp;(1)开通微信支付商户号。<br>&emsp;(2)开通小程序。<br>&emsp;(3)微信支付平台设置特约商户APPID,绑定小程序Appid。(这里要注意,小程序和支付商户必须是同一个主体)。<br>&emsp;(4)小程序绑定微信支付商户号。</p>
</summary>
<category term="小程序支付" scheme="http://www.daichongweb.com/tags/%E5%B0%8F%E7%A8%8B%E5%BA%8F%E6%94%AF%E4%BB%98/"/>
</entry>
<entry>
<title>phpOffice/phpSpreadsheet导出excel</title>
<link href="http://www.daichongweb.com/phpOffice-phpSpreadsheet%E5%AF%BC%E5%87%BAexcel/"/>
<id>http://www.daichongweb.com/phpOffice-phpSpreadsheet导出excel/</id>
<published>2020-04-10T01:46:38.000Z</published>
<updated>2021-09-03T05:56:57.944Z</updated>
<content type="html"><![CDATA[<h4 id="初识phpSpreadsheet"><a href="#初识phpSpreadsheet" class="headerlink" title="初识phpSpreadsheet"></a>初识phpSpreadsheet</h4><p> PHPSpreadsheet是由老外使用纯PHP编写的Excel文件处理扩展,他使用的是最新写法,相比PHPExcel(已不再维护)性能提升巨大,使用方法和函数基本相同,可以完全的替代PHPExcel。使用PhpSpreadsheet可以轻松读取和写入Excel文档,支持Excel的所有操作。</p><h5 id="软件依赖"><a href="#软件依赖" class="headerlink" title="软件依赖"></a>软件依赖</h5><ul><li>PHP5.6或更高版本,推荐PHP7</li><li>php_zip扩展</li><li>php_gd2扩展<a id="more"></a></li></ul><h5 id="PHPSpreadsheet-特性"><a href="#PHPSpreadsheet-特性" class="headerlink" title="PHPSpreadsheet 特性"></a>PHPSpreadsheet 特性</h5><ul><li><p>支持导入和导出.xls,.xlsx,.html,.csv,.pdf等格式文件。</p></li><li><p>提供丰富的API,提供单元格样式设置、Excel表格属性设置、图表设置等等诸多功能。使用PhpSpreadsheet完全可以生成一个外观结构都满足你的Excel表格文件。</p></li><li><p>卓越的性能,尤其在PHP7上表现优异,比PHPExcel强大很多。</p></li></ul><h5 id="安装"><a href="#安装" class="headerlink" title="安装"></a>安装</h5><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">composer <span class="keyword">require</span> phpoffice/phpspreadsheet</span><br></pre></td></tr></table></figure><h4 id="实战"><a href="#实战" class="headerlink" title="实战"></a>实战</h4><p> 下面咱们来做一个通用的导出Excel表格类。</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><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></pre></td><td class="code"><pre><span class="line"><span class="meta"><?php</span></span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> <span class="title">app</span>\<span class="title">common</span>\<span class="title">library</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">use</span> <span class="title">app</span>\<span class="title">common</span>\<span class="title">exception</span>\<span class="title">BusiException</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">PhpOffice</span>\<span class="title">PhpSpreadsheet</span>\<span class="title">IOFactory</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">PhpOffice</span>\<span class="title">PhpSpreadsheet</span>\<span class="title">Spreadsheet</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 导出excel class</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@author</span> daichongweb</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">Export</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="keyword">private</span> $cellIndex = [<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 class="string">'F'</span>, <span class="string">'G'</span>, <span class="string">'H'</span>, <span class="string">'I'</span>, <span class="string">'J'</span>, <span class="string">'K'</span>, <span class="string">'L'</span>, <span class="string">'M'</span>, <span class="string">'N'</span>, <span class="string">'O'</span>, <span class="string">'P'</span>, <span class="string">'Q'</span>, <span class="string">'R'</span>, <span class="string">'S'</span>, <span class="string">'T'</span>, <span class="string">'U'</span>, <span class="string">'V'</span>, <span class="string">'W'</span>, <span class="string">'X'</span>, <span class="string">'Y'</span>, <span class="string">'Z'</span>, <span class="string">'AA'</span>, <span class="string">'AB'</span>, <span class="string">'AC'</span>, <span class="string">'AD'</span>, <span class="string">'AE'</span>, <span class="string">'AF'</span>, <span class="string">'AG'</span>, <span class="string">'AH'</span>, <span class="string">'AI'</span>, <span class="string">'AJ'</span>, <span class="string">'AK'</span>, <span class="string">'AL'</span>, <span class="string">'AM'</span>, <span class="string">'AN'</span>, <span class="string">'AO'</span>, <span class="string">'AP'</span>, <span class="string">'AQ'</span>, <span class="string">'AR'</span>, <span class="string">'AS'</span>, <span class="string">'AT'</span>, <span class="string">'AU'</span>, <span class="string">'AV'</span>, <span class="string">'AW'</span>, <span class="string">'AX'</span>, <span class="string">'AY'</span>, <span class="string">'AZ'</span>];</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 默认配置</span></span><br><span class="line"> <span class="keyword">public</span> $config = [</span><br><span class="line"> <span class="string">'bold'</span> => <span class="keyword">true</span>, <span class="comment">// 加粗</span></span><br><span class="line"> <span class="string">'size'</span> => <span class="number">12</span>, <span class="comment">// 文字大小</span></span><br><span class="line"> <span class="string">'column'</span> => <span class="number">4</span>, <span class="comment">// 设置列数</span></span><br><span class="line"> <span class="string">'title'</span> => <span class="string">'默认导出'</span>, <span class="comment">// 表格标题</span></span><br><span class="line"> <span class="string">'name'</span> => <span class="string">'特抱抱'</span>, <span class="comment">// 文件名</span></span><br><span class="line"> <span class="string">'type'</span> => <span class="string">'Xls'</span>, <span class="comment">// 导出格式</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">public</span> $tableHeader = [</span><br><span class="line"> <span class="string">'php'</span>,</span><br><span class="line"> <span class="string">'vue'</span>,</span><br><span class="line"> <span class="string">'java'</span>,</span><br><span class="line"> <span class="string">'go'</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">public</span> $tableDefaultData = [</span><br><span class="line"> [</span><br><span class="line"> <span class="string">'天下第一'</span>,</span><br><span class="line"> <span class="string">'Vue牛逼'</span>,</span><br><span class="line"> <span class="string">'java牛逼'</span>,</span><br><span class="line"> <span class="string">'go牛逼'</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"> * <span class="doctag">@param</span> array $tableHeader 表头</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> array $tableDefaultData 需要导出数据</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">($tableHeader, $tableDefaultData)</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="keyword">if</span> (<span class="keyword">empty</span>($tableHeader)) {</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> BusiException(<span class="string">'export error'</span>, <span class="string">'请设置表头'</span>);</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>($tableDefaultData)) {</span><br><span class="line"> <span class="keyword">throw</span> <span class="keyword">new</span> BusiException(<span class="string">'export error'</span>, <span class="string">'请设置导出数据'</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">$this</span>->tableHeader = $tableHeader;</span><br><span class="line"> <span class="keyword">$this</span>->config[<span class="string">'column'</span>] = count($tableHeader);</span><br><span class="line"> <span class="keyword">$this</span>->tableDefaultData = $tableDefaultData;</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"> * 创建表格 createTable</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">createTable</span><span class="params">()</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> $spreadsheet = <span class="keyword">new</span> Spreadsheet();</span><br><span class="line"> $worksheet = $spreadsheet->getActiveSheet();</span><br><span class="line"></span><br><span class="line"> <span class="comment">//居中</span></span><br><span class="line"> $styleArray = [</span><br><span class="line"> <span class="string">'alignment'</span> => [</span><br><span class="line"> <span class="string">'horizontal'</span> => \PhpOffice\PhpSpreadsheet\Style\Alignment::HORIZONTAL_CENTER,</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"> $worksheet->setTitle(<span class="keyword">$this</span>->config[<span class="string">'title'</span>]);</span><br><span class="line"> $worksheet->getStyle(<span class="keyword">$this</span>->getColumn())->applyFromArray($styleArray)</span><br><span class="line"> ->getFont()</span><br><span class="line"> ->setBold(<span class="keyword">$this</span>->config[<span class="string">'bold'</span>])</span><br><span class="line"> ->setName(<span class="string">'Verdana'</span>)</span><br><span class="line"> ->setSize(<span class="keyword">$this</span>->config[<span class="string">'size'</span>]);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">foreach</span> (<span class="keyword">$this</span>->tableHeader <span class="keyword">as</span> $index => $name) {</span><br><span class="line"> $worksheet->setCellValue(<span class="keyword">$this</span>->cellIndex[$index] . <span class="string">'1'</span>, $name);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> $baseRow = <span class="number">2</span>;</span><br><span class="line"> <span class="keyword">foreach</span> (<span class="keyword">$this</span>->tableDefaultData <span class="keyword">as</span> $index => $data) {</span><br><span class="line"> $i = $index + $baseRow;</span><br><span class="line"> <span class="keyword">for</span> ($k = <span class="number">0</span>; $k <= <span class="keyword">$this</span>->config[<span class="string">'column'</span>] - <span class="number">1</span>; $k++) {</span><br><span class="line"> $item = $data[$k];</span><br><span class="line"> $worksheet->setCellValue(<span class="keyword">$this</span>->cellIndex[$k] . $i, <span class="string">' '</span> . $item);</span><br><span class="line"> <span class="comment">// 中文设置表格宽度</span></span><br><span class="line"> <span class="keyword">if</span> (preg_match(<span class="string">"/[\x7f-\xff]/"</span>, $data[$k])) {</span><br><span class="line"> $worksheet->getColumnDimension(<span class="keyword">$this</span>->cellIndex[$k])->setWidth(strlen($item));</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="comment">// 非中文自动设置宽度</span></span><br><span class="line"> $worksheet->getColumnDimension(<span class="keyword">$this</span>->cellIndex[$k])->setAutoSize(<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"> $worksheet->calculateColumnWidths();</span><br><span class="line"> <span class="keyword">self</span>::downloadExcel($spreadsheet, <span class="keyword">$this</span>->config[<span class="string">'name'</span>], <span class="string">'Xls'</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"> * 文件下载 downloadExcel</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> data $spreadsheet</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> string $filename</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@param</span> string $format</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> void</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">downloadExcel</span><span class="params">($spreadsheet, $filename, $format)</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="comment">// $format只能为 Xlsx 或 Xls</span></span><br><span class="line"> <span class="keyword">if</span> ($format == <span class="string">'Xlsx'</span>) {</span><br><span class="line"> header(<span class="string">'Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'</span>);</span><br><span class="line"> } <span class="keyword">elseif</span> ($format == <span class="string">'Xls'</span>) {</span><br><span class="line"> header(<span class="string">'Content-Type: application/vnd.ms-excel'</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> header(<span class="string">"Content-Disposition: attachment;filename="</span></span><br><span class="line"> . urlencode($filename) . <span class="string">'.'</span> . strtolower($format)); <span class="comment">//. date('Y-m-d')</span></span><br><span class="line"> header(<span class="string">'Cache-Control: max-age=0'</span>);</span><br><span class="line"> $objWriter = IOFactory::createWriter($spreadsheet, $format);</span><br><span class="line"> $objWriter->save(<span class="string">'php://output'</span>);</span><br><span class="line"> <span class="keyword">exit</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> <span class="function"><span class="keyword">function</span> <span class="title">getColumn</span><span class="params">($row = <span class="number">1</span>)</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> $index = <span class="keyword">$this</span>->cellIndex[<span class="keyword">$this</span>->config[<span class="string">'column'</span>]];</span><br><span class="line"> <span class="keyword">return</span> <span class="string">'A'</span> . $row . <span class="string">':'</span> . $index . $row;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">private</span> <span class="function"><span class="keyword">function</span> <span class="title">autoFitColumnWidthToContent</span><span class="params">($sheet, $fromCol, $toCol)</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="keyword">if</span> (<span class="keyword">empty</span>($toCol)) { <span class="comment">//not defined the last column, set it the max one</span></span><br><span class="line"> $toCol = $sheet->getColumnDimension($sheet->getHighestColumn())->getColumnIndex();</span><br><span class="line"> }</span><br><span class="line"> <span class="keyword">for</span> ($i = $fromCol; $i <= $toCol; $i++) {</span><br><span class="line"> $sheet->getColumnDimension($i)->setAutoSize(<span class="keyword">true</span>);</span><br><span class="line"> }</span><br><span class="line"> $sheet->calculateColumnWidths();</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h5 id="使用方法"><a href="#使用方法" class="headerlink" title="使用方法"></a>使用方法</h5><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="keyword">use</span> <span class="title">helper</span>\<span class="title">Export</span>;</span><br><span class="line">...</span><br><span class="line"><span class="comment">// 设置表头</span></span><br><span class="line">$export = <span class="keyword">new</span> Export(</span><br><span class="line"> [</span><br><span class="line"> <span class="string">'测试标题'</span>,</span><br><span class="line"> <span class="string">'测试标题2'</span>,</span><br><span class="line"> <span class="string">'时间'</span>,</span><br><span class="line"> ],</span><br><span class="line"> [</span><br><span class="line"> [<span class="string">'11111111111111'</span>, <span class="string">'测试数据2'</span>, <span class="string">'2020-04-30'</span>],</span><br><span class="line"> [<span class="string">'测试数据1-1'</span>, <span class="string">'测试数据2-2'</span>, <span class="string">'2020-04-30'</span>],</span><br><span class="line"> ]</span><br><span class="line">);</span><br><span class="line"><span class="keyword">echo</span> $export->createTable();</span><br><span class="line"><span class="keyword">exit</span>;</span><br></pre></td></tr></table></figure><h4 id="效果"><a href="#效果" class="headerlink" title="效果"></a>效果</h4><img src="/phpOffice-phpSpreadsheet导出excel/img/3.gif">]]></content>
<summary type="html">
<h4 id="初识phpSpreadsheet"><a href="#初识phpSpreadsheet" class="headerlink" title="初识phpSpreadsheet"></a>初识phpSpreadsheet</h4><p>&emsp;PHPSpreadsheet是由老外使用纯PHP编写的Excel文件处理扩展,他使用的是最新写法,相比PHPExcel(已不再维护)性能提升巨大,使用方法和函数基本相同,可以完全的替代PHPExcel。使用PhpSpreadsheet可以轻松读取和写入Excel文档,支持Excel的所有操作。</p>
<h5 id="软件依赖"><a href="#软件依赖" class="headerlink" title="软件依赖"></a>软件依赖</h5><ul>
<li>PHP5.6或更高版本,推荐PHP7</li>
<li>php_zip扩展</li>
<li>php_gd2扩展</li></ul>
</summary>
<category term="php扩展类" scheme="http://www.daichongweb.com/tags/php%E6%89%A9%E5%B1%95%E7%B1%BB/"/>
</entry>
<entry>
<title>nginx负载均衡的实现</title>
<link href="http://www.daichongweb.com/nginx%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1%E7%9A%84%E5%AE%9E%E7%8E%B0/"/>
<id>http://www.daichongweb.com/nginx负载均衡的实现/</id>
<published>2020-03-25T07:50:50.000Z</published>
<updated>2021-09-03T05:56:57.934Z</updated>
<content type="html"><![CDATA[<h4 id="负载均衡是什么?"><a href="#负载均衡是什么?" class="headerlink" title="负载均衡是什么?"></a>负载均衡是什么?</h4><p> 负载均衡建立在现有网络结构之上,它提供了一种廉价有效透明的方法扩展网络设备和服务器的带宽、增加吞吐量、加强网络数据处理能力、提高网络的灵活性和可用性。</p><p> 负载均衡(Load Balance)其意思就是分摊到多个操作单元上进行执行,例如Web服务器、FTP服务器、企业关键应用服务器和其它关键任务服务器等,从而共同完成工作任务。</p><h4 id="为什么要做负载均衡"><a href="#为什么要做负载均衡" class="headerlink" title="为什么要做负载均衡"></a>为什么要做负载均衡</h4><ul><li>服务器总是崩溃怎么办?</li><li>一台服务器扛不住大量的并发怎么办?</li><li>……</li></ul><p> 有了这些问题,我相信你一定会用得到这个技术。最让人高兴的一点是:只需要你懂点nginx的配置就能完美的驾驭负载均衡的配置,至于配置之后可能出现的问题,再慢慢去研究也不迟。<br><a id="more"></a></p><h4 id="架构图"><a href="#架构图" class="headerlink" title="架构图"></a>架构图</h4><img src="/nginx负载均衡的实现/img/1.png"><p> 从上图可以看出,我们利用负载均衡可以很好的应对并发请求过高的情况,使每一台服务器发挥最大的效用。</p><h4 id="负载均衡的实现方式"><a href="#负载均衡的实现方式" class="headerlink" title="负载均衡的实现方式"></a>负载均衡的实现方式</h4><ul><li><p>轮询(rr) :按时间顺序逐一分配到不同的后端服务器(默认);</p></li><li><p>权重(weight):加权轮询(wrr)。weight值越大,分配到的访问率越高;</p></li><li><p>源IP地址hash调度方法(ip_hash):将每个请求按访问IP的hash值来分配,来自同一个IP固定访问一个后端服务器;</p></li><li><p>最少连接数(least_conn):当server拥有不同的权重时为wlc,当所有后端主机;连接数相同时,则使用wrr,适用于长连接(keepalive_timeout不为0);</p></li></ul><h4 id="实战配置"><a href="#实战配置" class="headerlink" title="实战配置"></a>实战配置</h4><p> 准备三台服务器:(1)192.168.133.128(调度器)(2)192.168.133.129(服务器1)(3)192.168.133.130(服务器2)<br> 在调度服务器中配置:<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><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></pre></td><td class="code"><pre><span class="line">upstream 192.168.133.128{</span><br><span class="line"> server 192.168.133.129:80 weight=1;</span><br><span class="line"> server 192.168.133.130:80 weight=1;</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line">server {</span><br><span class="line"> listen 80;</span><br><span class="line"> server_name localhost;</span><br><span class="line"></span><br><span class="line"> <span class="comment">#charset koi8-r;</span></span><br><span class="line"> <span class="comment">#access_log /var/log/nginx/host.access.log main;</span></span><br><span class="line"></span><br><span class="line"> client_max_body_size 50m;</span><br><span class="line"> client_body_buffer_size 256k;</span><br><span class="line"></span><br><span class="line"> location / {</span><br><span class="line"> proxy_pass http://192.168.133.128;</span><br><span class="line"> proxy_set_header X-Forwarded-For <span class="variable">$remote_addr</span>;</span><br><span class="line"> proxy_set_header Host <span class="variable">$host</span>;</span><br><span class="line"></span><br><span class="line"> }</span><br></pre></td></tr></table></figure></p><p> 其他服务器server_name都配置成自己的IP就行。在各自的服务Html里命名,加以区分。</p><h4 id="测试"><a href="#测试" class="headerlink" title="测试"></a>测试</h4><img src="/nginx负载均衡的实现/img/2.gif">]]></content>
<summary type="html">
<h4 id="负载均衡是什么?"><a href="#负载均衡是什么?" class="headerlink" title="负载均衡是什么?"></a>负载均衡是什么?</h4><p>&emsp;负载均衡建立在现有网络结构之上,它提供了一种廉价有效透明的方法扩展网络设备和服务器的带宽、增加吞吐量、加强网络数据处理能力、提高网络的灵活性和可用性。</p>
<p>&emsp;负载均衡(Load Balance)其意思就是分摊到多个操作单元上进行执行,例如Web服务器、FTP服务器、企业关键应用服务器和其它关键任务服务器等,从而共同完成工作任务。</p>
<h4 id="为什么要做负载均衡"><a href="#为什么要做负载均衡" class="headerlink" title="为什么要做负载均衡"></a>为什么要做负载均衡</h4><ul>
<li>服务器总是崩溃怎么办?</li>
<li>一台服务器扛不住大量的并发怎么办?</li>
<li>……</li>
</ul>
<p> &nbsp;有了这些问题,我相信你一定会用得到这个技术。最让人高兴的一点是:只需要你懂点nginx的配置就能完美的驾驭负载均衡的配置,至于配置之后可能出现的问题,再慢慢去研究也不迟。<br></p>
</summary>
<category term="nginx" scheme="http://www.daichongweb.com/tags/nginx/"/>
</entry>
<entry>
<title>用最少的Sql实现一个特殊排行榜</title>
<link href="http://www.daichongweb.com/%E7%94%A8%E6%9C%80%E5%B0%91%E7%9A%84Sql%E5%AE%9E%E7%8E%B0%E4%B8%80%E4%B8%AA%E7%89%B9%E6%AE%8A%E6%8E%92%E8%A1%8C%E6%A6%9C/"/>
<id>http://www.daichongweb.com/用最少的Sql实现一个特殊排行榜/</id>
<published>2020-01-21T00:24:28.000Z</published>
<updated>2021-09-03T05:56:57.986Z</updated>
<content type="html"><![CDATA[<h4 id="引言"><a href="#引言" class="headerlink" title="引言"></a>引言</h4><p> 说起排行榜上一篇已经介绍过了用Redis实现的方法,而这篇完全是用Sql来实现,不使用任何缓存。</p><h4 id="需求功能(1)"><a href="#需求功能(1)" class="headerlink" title="需求功能(1)"></a>需求功能(1)</h4><p> 现有十个同学,年龄分布如下图所示,假设你是<code>戴七</code>,请根据年龄获得你在这十人中排第几?同时请获得你的前一名和后一名各是哪一位同学?</p><img src="/用最少的Sql实现一个特殊排行榜/img/1.png"><p> 这个题是我去年在一家公司被问到的面试题。根据上图分析,获取到自己的排名并不是难事,那前一名和后一名也非常简单了。<br><a id="more"></a></p><h5 id="自己的排名"><a href="#自己的排名" class="headerlink" title="自己的排名"></a>自己的排名</h5><figure class="highlight sql"><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><br><span class="line"><span class="keyword">select</span> <span class="keyword">count</span>(*) <span class="keyword">from</span> <span class="string">`rank`</span> <span class="keyword">where</span> <span class="string">`age`</span> > <span class="number">22</span> <span class="keyword">or</span> (<span class="string">`age`</span> = <span class="number">22</span> <span class="keyword">and</span> <span class="string">`created_at`</span> > <span class="string">'2020-01-21 09:05:34'</span>);</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></pre></td><td class="code"><pre><span class="line"><span class="comment">// Laravel框架写法</span></span><br><span class="line">$my = DB::table(<span class="string">'rank'</span>)->where(<span class="string">'name'</span>, <span class="string">'戴七'</span>)->first();</span><br><span class="line">$rank = DB::table(<span class="string">'rank'</span>)->where(<span class="string">'age'</span>, <span class="string">'>'</span>, $my->age)->orWhere(<span class="function"><span class="keyword">function</span> <span class="params">($query)</span> <span class="title">use</span> <span class="params">($my)</span> </span>{</span><br><span class="line"> $query->where(<span class="string">'age'</span>, <span class="string">'='</span>, $my->age)->where(<span class="string">'created_at'</span>, <span class="string">'>'</span>, $my->created_at);</span><br><span class="line">})->count();</span><br><span class="line">$myRank = $rank + <span class="number">1</span>;</span><br></pre></td></tr></table></figure><p> 这里要注意的是:如果两个人的年龄相同,那么就要比较时间。最终得到的是年龄大于自己人有多少个,+1就是自己的排名。</p><h5 id="前一名"><a href="#前一名" class="headerlink" title="前一名"></a>前一名</h5><figure class="highlight sql"><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">// 通过上面的Sql得知年龄大于自己的人数是6人</span><br><span class="line">$rankNum = 6;</span><br><span class="line">$top = $rankNum - 1;</span><br><span class="line"><span class="keyword">select</span> * <span class="keyword">from</span> <span class="keyword">rank</span> <span class="keyword">where</span> age > <span class="number">22</span> <span class="keyword">order</span> <span class="keyword">by</span> age <span class="keyword">desc</span> <span class="keyword">limit</span> $top,<span class="number">1</span></span><br></pre></td></tr></table></figure><h5 id="后一名"><a href="#后一名" class="headerlink" title="后一名"></a>后一名</h5><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">select</span> * <span class="keyword">from</span> <span class="string">`rank`</span> <span class="keyword">where</span> <span class="string">`age`</span> < <span class="number">22</span> <span class="keyword">or</span> (<span class="string">`age`</span> = <span class="number">22</span> <span class="keyword">and</span> <span class="string">`created_at`</span> < <span class="string">'2020-01-21 09:05:34'</span>) <span class="keyword">order</span> <span class="keyword">by</span> age <span class="keyword">desc</span>,created_at <span class="keyword">desc</span> <span class="keyword">limit</span> <span class="number">1</span></span><br></pre></td></tr></table></figure><p> 这里和原始Sql不同的是:年龄是<code><22</code>,时间也是<code><自己的出生时间</code>。</p><h4 id="需求功能(2)"><a href="#需求功能(2)" class="headerlink" title="需求功能(2)"></a>需求功能(2)</h4><p> 还是这十名同学,假设<code>戴七</code>同学就是本人,现需要五名同学的年龄作为参考,要求这分别得知你本人的前两名同学和后两名同学都是谁(五名同学中必须包含你自己)?</p><h5 id="特殊情况:"><a href="#特殊情况:" class="headerlink" title="特殊情况:"></a>特殊情况:</h5><p> (1)如果你是第一名,那么就获得你后面的四位同学。<br> (2)如果你是第二名,那么就获得你前面的一名+后面的三名同学。<br> (3)如果你是倒数第一名,那么就获得你前面的四位同学。<br> (4)如果你是倒数第二名,那么就获得你前面的三名+后面的一位同学。<br> (5)可使用其他语言辅助解决问题,但尽可能的简单清晰。</p><h4 id="答案"><a href="#答案" class="headerlink" title="答案"></a>答案</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></pre></td><td class="code"><pre><span class="line">$myRank = $rank + <span class="number">1</span>;</span><br><span class="line">$total = Db::table(<span class="string">'rank'</span>)->count();</span><br><span class="line"><span class="comment">// 如果排名是在前三名</span></span><br><span class="line"><span class="keyword">if</span> ($myRank <= <span class="number">3</span>) {</span><br><span class="line"> select * from rank where <span class="number">1</span> order by age desc,created_at desc limit <span class="number">5</span>;</span><br><span class="line">} <span class="keyword">else</span> <span class="keyword">if</span> (($total - $myRank) <= <span class="number">2</span>) { <span class="comment">// 倒数两名</span></span><br><span class="line"> $unRank = $total - $myRank + <span class="number">1</span>;</span><br><span class="line"> $offset = $myRank - <span class="number">6</span> + $unRank;</span><br><span class="line"> select * from rank where <span class="number">1</span> order by age desc,created_at desc limit $offset,<span class="number">5</span>;</span><br><span class="line">} <span class="keyword">else</span> {</span><br><span class="line"> $offset = $myRank - <span class="number">3</span>;</span><br><span class="line"> select * from rank where <span class="number">1</span> order by age desc,created_at desc limit $offset,<span class="number">5</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure>]]></content>
<summary type="html">
<h4 id="引言"><a href="#引言" class="headerlink" title="引言"></a>引言</h4><p>&emsp;说起排行榜上一篇已经介绍过了用Redis实现的方法,而这篇完全是用Sql来实现,不使用任何缓存。</p>
<h4 id="需求功能(1)"><a href="#需求功能(1)" class="headerlink" title="需求功能(1)"></a>需求功能(1)</h4><p>&emsp;现有十个同学,年龄分布如下图所示,假设你是<code>戴七</code>,请根据年龄获得你在这十人中排第几?同时请获得你的前一名和后一名各是哪一位同学?</p>
<img src="/用最少的Sql实现一个特殊排行榜/img/1.png">
<p>&emsp;这个题是我去年在一家公司被问到的面试题。根据上图分析,获取到自己的排名并不是难事,那前一名和后一名也非常简单了。<br></p>
</summary>
<category term="mysql" scheme="http://www.daichongweb.com/tags/mysql/"/>
</entry>
<entry>
<title>php+redis实现实时排行榜</title>
<link href="http://www.daichongweb.com/php-redis%E5%AE%9E%E7%8E%B0%E5%AE%9E%E6%97%B6%E6%8E%92%E8%A1%8C%E6%A6%9C/"/>
<id>http://www.daichongweb.com/php-redis实现实时排行榜/</id>
<published>2019-12-19T05:14:25.000Z</published>
<updated>2021-09-03T05:56:57.941Z</updated>
<content type="html"><![CDATA[<h4 id="介绍"><a href="#介绍" class="headerlink" title="介绍"></a>介绍</h4><p> 说起排行榜大家肯定不陌生,在项目开发中排行榜的运用非常的多。如王者农药的天梯排行榜、商城的销量排行榜、热卖榜、用户积分排行榜等等。不管他是什么类型的排行榜,其业务逻辑、实现方法几乎是完全相同的。<br> 如这样的一个手机和笔记本的销量排行榜是如何实现的呢?<br><a id="more"></a></p><h4 id="例子"><a href="#例子" class="headerlink" title="例子"></a>例子</h4><img src="/php-redis实现实时排行榜/img/1.png"><h4 id="榜单实现"><a href="#榜单实现" class="headerlink" title="榜单实现"></a>榜单实现</h4><p> 假设做一个如上图一样的排行榜,规定榜单必须是实时更新的,你会使用什么技术来实现呢?</p><h5 id="方案一"><a href="#方案一" class="headerlink" title="方案一"></a>方案一</h5><p> 在数据库新建一张数据表,通过下单事件钩子来更新这张表的数据,记录销量情况。<br><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">select</span> <span class="keyword">id</span>,<span class="keyword">name</span>,image <span class="keyword">from</span> goods <span class="keyword">left</span> <span class="keyword">join</span> goods_top <span class="keyword">on</span> goods.id=goods_top.goods_id <span class="keyword">where</span> sales > <span class="number">0</span> <span class="keyword">order</span> <span class="keyword">by</span> sales <span class="keyword">desc</span> <span class="keyword">limit</span> <span class="number">10</span>;</span><br></pre></td></tr></table></figure></p><p> 最常见、最简单的写法莫过于此,但这个写法有一个非常严重的问题。假设<code>goods</code>中数据规模极大,记录表<code>goods_top</code>表中数据规模也不小,在每次查询的性能消耗无疑是很大的,在极端的情况下甚至可能会出现请求超时的情况。</p><p> 这个方案在实际的项目运用中也很少出现,除非你能确定数据表规模一定会非常的小,或者你根本不考虑什么性能的情况下才会使用。</p><h5 id="方案二"><a href="#方案二" class="headerlink" title="方案二"></a>方案二</h5><p> 使用<code>redis</code>的<code>有序集合(zset)</code>来实现实时排行榜。<em style="font-size:12px;">关于redis有序集合的相关介绍、原理什么的大家自行百度</em></p><p> (1)<code>Redis</code> 有序集合和集合一样也是<code>string</code>类型元素的集合,且不允许重复的成员。<br> (2)不同的是每个元素都会关联一个double类型的分数。redis正是通过分数来为集合中的成员进行从小到大的排序。<br> (3)有序集合的成员是唯一的,但分数(score)却可以重复。<br> (4)集合是通过哈希表实现的,所以添加,删除,查找的复杂度都是O(1)。 集合中最大的成员数为 232 - 1 (4294967295, 每个集合可存储40多亿个成员)。</p><p> 也就是说,我们可以通过下单事件钩子创建一个<code>zset集合</code>,我们通过<code>value</code>来区分是哪个商品,通过<code>score</code>来排名。</p><img src="/php-redis实现实时排行榜/img/2.png"><h5 id="具体代码"><a href="#具体代码" class="headerlink" title="具体代码"></a>具体代码</h5><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><br><span class="line"><span class="keyword">use</span> <span class="title">Illuminate</span>\<span class="title">Support</span>\<span class="title">Facades</span>\<span class="title">Redis</span>;</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="class"><span class="keyword">class</span> <span class="title">Rank</span></span></span><br><span class="line"><span class="class"></span>{</span><br><span class="line"> <span class="comment">// key</span></span><br><span class="line"> <span class="keyword">private</span> <span class="keyword">static</span> <span class="function"><span class="keyword">function</span> <span class="title">key</span><span class="params">()</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> $activeActivityId = Main::info();</span><br><span class="line"> <span class="keyword">return</span> <span class="string">"goods_top"</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">public</span> <span class="keyword">static</span> <span class="function"><span class="keyword">function</span> <span class="title">add</span><span class="params">($id, $number)</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="keyword">return</span> Redis::zIncrBy(<span class="keyword">self</span>::key(), $number, $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"> <span class="keyword">static</span> <span class="function"><span class="keyword">function</span> <span class="title">get</span><span class="params">($id)</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="keyword">return</span> Redis::zScore(<span class="keyword">self</span>::key(), $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"> <span class="keyword">static</span> <span class="function"><span class="keyword">function</span> <span class="title">getRank</span><span class="params">($id)</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="keyword">return</span> Redis::zrevrank(<span class="keyword">self</span>::key(), $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"> <span class="keyword">static</span> <span class="function"><span class="keyword">function</span> <span class="title">getRevRange</span><span class="params">($start, $stop)</span>: <span class="title">array</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="keyword">return</span> Redis::zRevRange(<span class="keyword">self</span>::key(), $start, $stop);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h5 id="如何使用"><a href="#如何使用" class="headerlink" title="如何使用"></a>如何使用</h5><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">Rank::add(<span class="number">1008</span>,<span class="number">10</span>); <span class="comment">// 商品ID为1008的销量增加10</span></span><br><span class="line">Rank::get(<span class="number">1008</span>); <span class="comment">// 获取商品ID为1008的销量</span></span><br><span class="line">Rank::getRank(<span class="number">1008</span>); <span class="comment">// 获取商品ID为1008的排名</span></span><br><span class="line">Rank::getRevRange(<span class="number">0</span>,<span class="number">9</span>); <span class="comment">// 获取排名前十的商品ID,返回数组</span></span><br></pre></td></tr></table></figure><h4 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h4><p> 实现排行榜的方式有很多,大家根据具体需求和现有技术来确定实现方案。不要过分的追求性能或者是开发速度,欲速则不达。</p>]]></content>
<summary type="html">
<h4 id="介绍"><a href="#介绍" class="headerlink" title="介绍"></a>介绍</h4><p>&emsp;说起排行榜大家肯定不陌生,在项目开发中排行榜的运用非常的多。如王者农药的天梯排行榜、商城的销量排行榜、热卖榜、用户积分排行榜等等。不管他是什么类型的排行榜,其业务逻辑、实现方法几乎是完全相同的。<br>&emsp;如这样的一个手机和笔记本的销量排行榜是如何实现的呢?<br></p>
</summary>
<category term="php" scheme="http://www.daichongweb.com/tags/php/"/>
</entry>
<entry>
<title>php7.4预加载与swoole常驻内存有何区别?</title>
<link href="http://www.daichongweb.com/php7-4%E9%A2%84%E5%8A%A0%E8%BD%BD%E4%B8%8Eswoole%E5%B8%B8%E9%A9%BB%E5%86%85%E5%AD%98%E6%9C%89%E4%BD%95%E5%8C%BA%E5%88%AB%EF%BC%9F/"/>
<id>http://www.daichongweb.com/php7-4预加载与swoole常驻内存有何区别?/</id>
<published>2019-12-14T01:52:57.000Z</published>
<updated>2021-09-03T05:56:57.942Z</updated>
<content type="html"><![CDATA[<h4 id="重大新闻"><a href="#重大新闻" class="headerlink" title="重大新闻"></a>重大新闻</h4><img src="/php7-4预加载与swoole常驻内存有何区别?/img/1.png"><p>php7.4在2019/11/28日发布!<br><a id="more"></a><br>其中RFC: Preloading(预加载)最引人瞩目。这一新特性的诞生标志着php作为解释型语言在性能瓶颈上再次突破。</p><p>根据各大网友的测试统计,php7.4与php7.0相比提升将近10%。</p><h4 id="特性介绍"><a href="#特性介绍" class="headerlink" title="特性介绍"></a>特性介绍</h4><h5 id="php生命周期"><a href="#php生命周期" class="headerlink" title="php生命周期"></a>php生命周期</h5><img src="/php7-4预加载与swoole常驻内存有何区别?/img/3.png"><p>每次请求php都会从0到1重复上图所示的操作,每次带来的内存、IO方面的消耗无疑是很大的。</p><h5 id="预加载"><a href="#预加载" class="headerlink" title="预加载"></a>预加载</h5><img src="/php7-4预加载与swoole常驻内存有何区别?/img/2.png" title="网图"><p>在预加载的特性下,php会当预加载完成后的请求直接会命中缓存,省下了编译、语法解析、语法分析、类库引入等等操作。</p><p>这里你会发现怎么和swoole的常驻内存有点像?</p><p>不过说实话,在没有真正使用的情况下还真没法判断两者的区别。</p><p>关于更详细的预加载使用大家可以看这里:<a href="https://blog.csdn.net/qmhball/article/details/103503939" target="_blank" rel="noopener">php7.4 preload(预加载)</a></p><p>欢迎大家来讨论有关于预加载和常驻内存的区别到底是什么?</p>]]></content>
<summary type="html">
<h4 id="重大新闻"><a href="#重大新闻" class="headerlink" title="重大新闻"></a>重大新闻</h4><img src="/php7-4预加载与swoole常驻内存有何区别?/img/1.png">
<p>php7.4在2019/11/28日发布!<br></p>
</summary>
<category term="php" scheme="http://www.daichongweb.com/tags/php/"/>
</entry>
<entry>
<title>php+element+aliyunOss实现单图web直传</title>
<link href="http://www.daichongweb.com/php-element-aliyunOss%E5%AE%9E%E7%8E%B0%E5%8D%95%E5%9B%BEweb%E7%9B%B4%E4%BC%A0/"/>
<id>http://www.daichongweb.com/php-element-aliyunOss实现单图web直传/</id>
<published>2019-12-07T09:45:43.000Z</published>
<updated>2021-09-03T05:56:57.937Z</updated>
<content type="html"><![CDATA[<h4 id="业务逻辑"><a href="#业务逻辑" class="headerlink" title="业务逻辑"></a>业务逻辑</h4><h5 id="原有业务"><a href="#原有业务" class="headerlink" title="原有业务"></a>原有业务</h5><img src="/php-element-aliyunOss实现单图web直传/img/1.png"><a id="more"></a><p>和数据直传到 OSS 相比,以上方法有三个缺点:</p><ul><li>上传慢:用户数据需先上传到应用服务器,之后再上传到OSS。网络传输时间比直传到OSS多一倍。如果用户数据不通过应用服务器中转,而是直传到OSS,速度将大大提升。而且OSS采用BGP带宽,能保证各地各运营商之间的传输速度。</li><li>扩展性差:如果后续用户多了,应用服务器会成为瓶颈。</li><li>费用高:需要准备多台应用服务器。由于OSS上传流量是免费的,如果数据直传到OSS,不通过应用服务器,那么将能省下几台应用服务器。</li></ul><h5 id="代替业务"><a href="#代替业务" class="headerlink" title="代替业务"></a>代替业务</h5><img src="/php-element-aliyunOss实现单图web直传/img/2.png"><p>使用Oss web直传,能有效的解决上传速度过慢的问题。</p><h4 id="实践"><a href="#实践" class="headerlink" title="实践"></a>实践</h4><h5 id="php后端签名代码"><a href="#php后端签名代码" class="headerlink" title="php后端签名代码"></a>php后端签名代码</h5><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></pre></td><td class="code"><pre><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * 阿里Oss上传验签类</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">OssPolicy</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">gmtIso8601</span><span class="params">($time)</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> $dtStr = date(<span class="string">"c"</span>, $time);</span><br><span class="line"> $mydatetime = <span class="keyword">new</span> DateTime($dtStr);</span><br><span class="line"> $expiration = $mydatetime->format(DateTime::ISO8601);</span><br><span class="line"> $pos = strpos($expiration, <span class="string">'+'</span>);</span><br><span class="line"> $expiration = substr($expiration, <span class="number">0</span>, $pos);</span><br><span class="line"> <span class="keyword">return</span> $expiration . <span class="string">"Z"</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="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">policy</span><span class="params">()</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> $id = Config(<span class="string">'aliyun.webOss.accessKeyId'</span>); <span class="comment">// oss accessKeyId</span></span><br><span class="line"> $key = Config(<span class="string">'aliyun.webOss.accessKeySecret'</span>); <span class="comment">// oss accessKeySecret</span></span><br><span class="line"> $host = Config(<span class="string">'aliyun.webOss.host'</span>); <span class="comment">// oss 上传地址</span></span><br><span class="line"> $callbackUrl = Config(<span class="string">'aliyun.webOss.callbackUrl'</span>);<span class="comment">// 回调地址 这个可以忽略</span></span><br><span class="line"> $dir = Config(<span class="string">'aliyun.webOss.dir'</span>); <span class="comment">// 存放的文件夹</span></span><br><span class="line"></span><br><span class="line"> $callback_param = <span class="keyword">array</span>(</span><br><span class="line"> <span class="string">'callbackUrl'</span> => $callbackUrl,</span><br><span class="line"> <span class="string">'callbackBody'</span> => <span class="string">'filename=${object}&size=${size}&mimeType=${mimeType}&height=${imageInfo.height}&width=${imageInfo.width}'</span>,</span><br><span class="line"> <span class="string">'callbackBodyType'</span> => <span class="string">"application/x-www-form-urlencoded"</span></span><br><span class="line"> );</span><br><span class="line"> $callback_string = json_encode($callback_param);</span><br><span class="line"> $base64_callback_body = base64_encode($callback_string);</span><br><span class="line"> $now = time();</span><br><span class="line"> $expire = <span class="number">30</span>;</span><br><span class="line"> $end = $now + $expire;</span><br><span class="line"> $expiration = <span class="keyword">$this</span>->gmtIso8601($end);</span><br><span class="line"></span><br><span class="line"> $condition = <span class="keyword">array</span>(<span class="number">0</span> => <span class="string">'content-length-range'</span>, <span class="number">1</span> => <span class="number">0</span>, <span class="number">2</span> => <span class="number">1048576000</span>);</span><br><span class="line"> $conditions[] = $condition;</span><br><span class="line"></span><br><span class="line"> $start = <span class="keyword">array</span>(<span class="number">0</span> => <span class="string">'starts-with'</span>, <span class="number">1</span> => <span class="string">'$key'</span>, <span class="number">2</span> => $dir);</span><br><span class="line"> $conditions[] = $start;</span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> $arr = <span class="keyword">array</span>(<span class="string">'expiration'</span> => $expiration, <span class="string">'conditions'</span> => $conditions);</span><br><span class="line"> $policy = json_encode($arr);</span><br><span class="line"> $base64_policy = base64_encode($policy);</span><br><span class="line"> $string_to_sign = $base64_policy;</span><br><span class="line"> $signature = base64_encode(hash_hmac(<span class="string">'sha1'</span>, $string_to_sign, $key, <span class="keyword">true</span>));</span><br><span class="line"></span><br><span class="line"> $response = <span class="keyword">array</span>();</span><br><span class="line"> $response[<span class="string">'accessid'</span>] = $id;</span><br><span class="line"> $response[<span class="string">'host'</span>] = $host;</span><br><span class="line"> $response[<span class="string">'policy'</span>] = $base64_policy;</span><br><span class="line"> $response[<span class="string">'signature'</span>] = $signature;</span><br><span class="line"> $response[<span class="string">'expire'</span>] = $end;</span><br><span class="line"> $response[<span class="string">'callback'</span>] = $base64_callback_body;</span><br><span class="line"> $response[<span class="string">'dir'</span>] = $dir;</span><br><span class="line"> <span class="keyword">return</span> $response;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h5 id="封装组件-ossSingleUpload-vue"><a href="#封装组件-ossSingleUpload-vue" class="headerlink" title="封装组件 ossSingleUpload.vue"></a>封装组件 ossSingleUpload.vue</h5><figure class="highlight js"><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></pre></td><td class="code"><pre><span class="line"><template></span><br><span class="line"> <div></span><br><span class="line"> <el-upload</span><br><span class="line"> list-type=<span class="string">"picture-card"</span></span><br><span class="line"> <span class="class"><span class="keyword">class</span></span>=<span class="string">"avatar-uploader"</span></span><br><span class="line"> action=<span class="string">"http://daichongwbe.oss-cn-beijing.aliyuncs.com"</span> <span class="comment">// 上传地址</span></span><br><span class="line"> :data=<span class="string">"dataObj"</span></span><br><span class="line"> accept=<span class="string">".jpeg, .png, .jpg"</span> <span class="comment">// 允许上传的文件</span></span><br><span class="line"> :multiple=<span class="string">"false"</span> <span class="comment">// 禁止多图上传</span></span><br><span class="line"> :before-upload=<span class="string">"beforeUpload"</span> <span class="comment">// 上传前回调</span></span><br><span class="line"> :on-success=<span class="string">"handleUploadSuccess"</span> <span class="comment">// 上传成功后回调</span></span><br><span class="line"> :limit=<span class="string">"limit"</span> <span class="comment">// 限制上传数量</span></span><br><span class="line"> :show-file-list=<span class="string">"false"</span> <span class="comment">// 禁止列表展示</span></span><br><span class="line"> ref=<span class="string">"upload"</span></span><br><span class="line"> ></span><br><span class="line"> <img v-<span class="keyword">if</span>=<span class="string">"imageUrl"</span> :src=<span class="string">"imageUrl"</span> <span class="class"><span class="keyword">class</span></span>=<span class="string">"avatar"</span> /></span><br><span class="line"> <i v-<span class="keyword">else</span> <span class="class"><span class="keyword">class</span></span>=<span class="string">"el-icon-plus avatar-uploader-icon"</span>><<span class="regexp">/i></span></span><br><span class="line"><span class="regexp"> </</span>el-upload></span><br><span class="line"> <<span class="regexp">/div></span></span><br><span class="line"><span class="regexp"></</span>template></span><br><span class="line"><script></span><br><span class="line"><span class="keyword">import</span> { getPolicy } <span class="keyword">from</span> <span class="string">"@/api/oss/token"</span>; <span class="comment">// 后端验签接口</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> {</span><br><span class="line"> name: <span class="string">"ossSingleUpload"</span>, <span class="comment">//组件命名</span></span><br><span class="line"> props: {</span><br><span class="line"> limit: <span class="built_in">Number</span>, <span class="comment">// 参数</span></span><br><span class="line"> imgCover: <span class="built_in">String</span> <span class="comment">// 参数</span></span><br><span class="line"> },</span><br><span class="line"> data() {</span><br><span class="line"> <span class="keyword">return</span> {</span><br><span class="line"> dataObj: {</span><br><span class="line"> policy: <span class="string">""</span>,</span><br><span class="line"> signature: <span class="string">""</span>,</span><br><span class="line"> key: <span class="string">""</span>,</span><br><span class="line"> ossaccessKeyId: <span class="string">""</span>,</span><br><span class="line"> dir: <span class="string">""</span>,</span><br><span class="line"> host: <span class="string">""</span>,</span><br><span class="line"> callback: <span class="string">""</span></span><br><span class="line"> },</span><br><span class="line"> imageUrl: <span class="string">""</span></span><br><span class="line"> };</span><br><span class="line"> },</span><br><span class="line"> created() {</span><br><span class="line"> setTimeout(<span class="function"><span class="params">()</span> =></span> {</span><br><span class="line"> <span class="keyword">this</span>.imageUrl = <span class="keyword">this</span>.imgCover;</span><br><span class="line"> }, <span class="number">500</span>);</span><br><span class="line"> },</span><br><span class="line"> methods: {</span><br><span class="line"> emitInput(val) { <span class="comment">// 组件交互</span></span><br><span class="line"> <span class="keyword">this</span>.$emit(<span class="string">"input"</span>, val);</span><br><span class="line"> },</span><br><span class="line"> beforeUpload(file) { <span class="comment">// 上传前钩子</span></span><br><span class="line"> <span class="keyword">let</span> _self = <span class="keyword">this</span>;</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> <span class="built_in">Promise</span>(<span class="function">(<span class="params">resolve, reject</span>) =></span> {</span><br><span class="line"> getPolicy()</span><br><span class="line"> .then(<span class="function"><span class="params">response</span> =></span> {</span><br><span class="line"> _self.dataObj.policy = response.data.policy;</span><br><span class="line"> _self.dataObj.signature = response.data.signature;</span><br><span class="line"> _self.dataObj.ossaccessKeyId = response.data.accessid;</span><br><span class="line"> _self.dataObj.key = response.data.dir + <span class="string">"${filename}"</span>;</span><br><span class="line"> _self.dataObj.dir = response.data.dir;</span><br><span class="line"> _self.dataObj.host = response.data.host;</span><br><span class="line"> _self.dataObj.callback = response.data.callback;</span><br><span class="line"> resolve(<span class="literal">true</span>);</span><br><span class="line"> })</span><br><span class="line"> .catch(<span class="function"><span class="params">err</span> =></span> {</span><br><span class="line"> <span class="built_in">console</span>.log(err);</span><br><span class="line"> reject(<span class="literal">false</span>);</span><br><span class="line"> });</span><br><span class="line"> });</span><br><span class="line"> },</span><br><span class="line"> handleUploadSuccess(res, file) { <span class="comment">// 上传成功后</span></span><br><span class="line"> <span class="comment">// 清除上次的上传记录,这里如果不清除会导致第二次上传无效。</span></span><br><span class="line"> <span class="keyword">this</span>.$refs.upload.clearFiles(); </span><br><span class="line"> <span class="comment">// 组装图片路径,这里根据业务需要来。</span></span><br><span class="line"> <span class="keyword">this</span>.imageUrl = <span class="keyword">this</span>.dataObj.host + <span class="string">"/"</span> + <span class="keyword">this</span>.dataObj.dir + file.name; </span><br><span class="line"> <span class="comment">// 组件交互,把图片路径发送给页面</span></span><br><span class="line"> <span class="keyword">this</span>.$emit(<span class="string">"getMessage"</span>, <span class="keyword">this</span>.imageUrl); </span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">};</span><br><span class="line"><<span class="regexp">/script></span></span><br></pre></td></tr></table></figure><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><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="selector-class">.avatar-uploader</span> <span class="selector-class">.el-upload</span> {</span><br><span class="line"> <span class="attribute">border</span>: <span class="number">1px</span> dashed <span class="number">#d9d9d9</span>;</span><br><span class="line"> <span class="attribute">border-radius</span>: <span class="number">6px</span>;</span><br><span class="line"> <span class="attribute">cursor</span>: pointer;</span><br><span class="line"> <span class="attribute">position</span>: relative;</span><br><span class="line"> <span class="attribute">overflow</span>: hidden;</span><br><span class="line">}</span><br><span class="line"><span class="selector-class">.avatar-uploader</span> <span class="selector-class">.el-upload</span><span class="selector-pseudo">:hover</span> {</span><br><span class="line"> <span class="attribute">border-color</span>: <span class="number">#409eff</span>;</span><br><span class="line">}</span><br><span class="line"><span class="selector-class">.avatar-uploader-icon</span> {</span><br><span class="line"> <span class="attribute">width</span>: <span class="number">100%</span>;</span><br><span class="line"> <span class="attribute">font-size</span>: <span class="number">28px</span>;</span><br><span class="line"> <span class="attribute">color</span>: <span class="number">#8c939d</span>;</span><br><span class="line"> <span class="attribute">text-align</span>: center;</span><br><span class="line">}</span><br><span class="line"><span class="selector-class">.avatar</span> {</span><br><span class="line"> <span class="attribute">width</span>: <span class="number">100%</span>;</span><br><span class="line"> <span class="attribute">display</span>: block;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h5 id="页面调用"><a href="#页面调用" class="headerlink" title="页面调用"></a>页面调用</h5><figure class="highlight js"><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"><template></span><br><span class="line"> <div <span class="class"><span class="keyword">class</span></span>=<span class="string">"app-container"</span>></span><br><span class="line"> <oss-single-upload @getMessage=<span class="string">"coverImg"</span> :imgCover=<span class="string">"imgCover"</span> :limit=<span class="string">"1"</span>><<span class="regexp">/oss-single-upload></span></span><br><span class="line"><span class="regexp"> </</span>div></span><br><span class="line"><<span class="regexp">/template></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">import ossSingleUpload from "@/</span>components/Upload/ossSingleUpload<span class="string">"; // 引入组件</span></span><br><span class="line"><span class="string">export default {</span></span><br><span class="line"><span class="string"> components: { ossSingleUpload },</span></span><br><span class="line"><span class="string"> data() {</span></span><br><span class="line"><span class="string"> return {</span></span><br><span class="line"><span class="string"> imgCover:"</span><span class="string">"</span></span><br><span class="line"><span class="string"> };</span></span><br><span class="line"><span class="string"> },</span></span><br><span class="line"><span class="string"> methods: {</span></span><br><span class="line"><span class="string"> coverImg(imgUrl) {</span></span><br><span class="line"><span class="string"> console.log(imgUrl); //得到的上传图片路径</span></span><br><span class="line"><span class="string"> }</span></span><br><span class="line"><span class="string"> }</span></span><br><span class="line"><span class="string">};</span></span><br><span class="line"><span class="string"></script></span></span><br></pre></td></tr></table></figure><h4 id="请求结果"><a href="#请求结果" class="headerlink" title="请求结果"></a>请求结果</h4><img src="/php-element-aliyunOss实现单图web直传/img/3.png"><p>在callbackurl为空或者callbackurl文件内容错误的情况下,这里是没有返回值的。</p><img src="/php-element-aliyunOss实现单图web直传/img/4.png"><h4 id="效果展示"><a href="#效果展示" class="headerlink" title="效果展示"></a>效果展示</h4><img src="/php-element-aliyunOss实现单图web直传/img/5.gif"><h4 id="github仓库"><a href="#github仓库" class="headerlink" title="github仓库"></a>github仓库</h4><p><a href="https://github.com/DaiChongyu/osswebupload" target="_blank" rel="noopener">点击查看源代码</a></p>]]></content>
<summary type="html">
<h4 id="业务逻辑"><a href="#业务逻辑" class="headerlink" title="业务逻辑"></a>业务逻辑</h4><h5 id="原有业务"><a href="#原有业务" class="headerlink" title="原有业务"></a>原有业务</h5><img src="/php-element-aliyunOss实现单图web直传/img/1.png">
</summary>
<category term="vue" scheme="http://www.daichongweb.com/tags/vue/"/>
</entry>
<entry>
<title>Laravel消息队列</title>
<link href="http://www.daichongweb.com/Laravel%E6%B6%88%E6%81%AF%E9%98%9F%E5%88%97/"/>
<id>http://www.daichongweb.com/Laravel消息队列/</id>
<published>2019-12-05T02:56:23.000Z</published>
<updated>2021-09-03T05:56:57.874Z</updated>
<content type="html"><![CDATA[<h4 id="思维导图"><a href="#思维导图" class="headerlink" title="思维导图"></a>思维导图</h4><img src="/Laravel消息队列/img/2.png"><a id="more"></a><h4 id="消息队列(MQ)"><a href="#消息队列(MQ)" class="headerlink" title="消息队列(MQ)"></a>消息队列(MQ)</h4><h5 id="什么是消息队列-MQ"><a href="#什么是消息队列-MQ" class="headerlink" title="什么是消息队列(MQ)"></a>什么是消息队列(MQ)</h5><p>关于消息队列大家肯定都不陌生,基本上每个项目中都会使用到的技术,在我前几期的博文中也有介绍。</p><p> 消息队列本质就是逻辑执行顺序,队列就如同一摞碗堆放在一起,你每放一个碗都会放在这螺碗的最上面,当你拿碗的时候也是只能从最上面拿。这个如同队列的消费特性(队列的特性是先进先出,先进后出,道理是一样的)。<br><img src="/Laravel消息队列/img/1.png"></p><h5 id="为什么要使用消息队列?"><a href="#为什么要使用消息队列?" class="headerlink" title="为什么要使用消息队列?"></a>为什么要使用消息队列?</h5><ul><li>提高系统性能(削峰,减少响应时间)。<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"># 假设你有一个这样的接口</span><br><span class="line"># 新用户注册发送邮件验证码</span><br><span class="line">public function SendMailCode(Request $request){</span><br><span class="line"> $mail = $request->input('mail);</span><br><span class="line"> SendReminderEmail::dispatch($mail); // 把邮箱加入队列</span><br><span class="line"> return '验证码发送成功,请注意查收!';</span><br><span class="line">}</span><br></pre></td></tr></table></figure></li></ul><p> 假设注册接口的并发在1秒100,在使用队列的情况下发送邮件这个操作是异步的,也就是说当第100名用户点击获取验证码后立刻就能获得响应,无需等待前99名所有邮件发送成功后才能得到相应,这就是不阻塞。<br>当<code>SendReminderEmail::dispatch($mail)</code>执行之后立刻就会执行 <code>return '验证码发送成功,请注意查收!'</code>,控制器不需要知道邮件是否发送成功,减少了阻塞的等待时间。</p><ul><li>降低系统的耦合性。<br>传统写法<img src="/Laravel消息队列/img/3.png">消息队列(MQ)写法<img src="/Laravel消息队列/img/4.png"><h5 id="消息队列(MQ)的优缺点"><a href="#消息队列(MQ)的优缺点" class="headerlink" title="消息队列(MQ)的优缺点"></a>消息队列(MQ)的优缺点</h5></li><li>优点:上边已经讲过了。</li><li>缺点:<br>  (1)系统可用性降低:可以看出引入了MQ之后,如果MQ挂了相当于整个日志系统也随之崩溃。<br>  (2)系统复杂性提高:引入MQ增加了维护系统的工作量,出现问题的可能性会更高。<br>  (3)一致性问题。</li></ul><h4 id="队列的应用"><a href="#队列的应用" class="headerlink" title="队列的应用"></a>队列的应用</h4><p> Laravel中的消息队列就非常简单了,他可以设置驱动和执行方式。</p><h5 id="安装扩展"><a href="#安装扩展" class="headerlink" title="安装扩展"></a>安装扩展</h5><ul><li>aws/aws-sdk-php ~3.0</li><li>pda/pheanstalk ~3.0</li><li>predis/predis ~1.0</li></ul><h5 id="生成任务类"><a href="#生成任务类" class="headerlink" title="生成任务类"></a>生成任务类</h5><figure class="highlight bash"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">php artisan make:job SendReminderEmail</span><br></pre></td></tr></table></figure><h5 id="任务类结构"><a href="#任务类结构" class="headerlink" title="任务类结构"></a>任务类结构</h5><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><br><span class="line"><span class="keyword">namespace</span> <span class="title">App</span>\<span class="title">Jobs</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">use</span> <span class="title">Illuminate</span>\<span class="title">Bus</span>\<span class="title">Queueable</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">Illuminate</span>\<span class="title">Contracts</span>\<span class="title">Queue</span>\<span class="title">ShouldQueue</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">Illuminate</span>\<span class="title">Foundation</span>\<span class="title">Bus</span>\<span class="title">Dispatchable</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">Illuminate</span>\<span class="title">Queue</span>\<span class="title">InteractsWithQueue</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">Illuminate</span>\<span class="title">Queue</span>\<span class="title">SerializesModels</span>;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">SendReminderEmail</span> <span class="keyword">implements</span> <span class="title">ShouldQueue</span></span></span><br><span class="line"><span class="class"></span>{</span><br><span class="line"> <span class="keyword">use</span> <span class="title">Dispatchable</span>, <span class="title">InteractsWithQueue</span>, <span class="title">Queueable</span>, <span class="title">SerializesModels</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">protected</span> $id; <span class="comment">// 接收外部传入的参数</span></span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * Create a new job instance.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> void</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">($id)</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="keyword">$this</span>->id = $id; <span class="comment">// 接收外部传入的参数</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"> * Execute the job.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> void</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">handle</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="string">'jobsss'</span> . <span class="keyword">$this</span>->id;</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h5 id="加入队列"><a href="#加入队列" class="headerlink" title="加入队列"></a>加入队列</h5><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"><span class="keyword">use</span> <span class="title">SendReminderEmail</span>;</span><br><span class="line">SendReminderEmail::dispatch($id); <span class="comment">// 加入队列</span></span><br><span class="line">ehco <span class="number">1</span>;</span><br></pre></td></tr></table></figure><h5 id="测试结果"><a href="#测试结果" class="headerlink" title="测试结果"></a>测试结果</h5><p> (1)当我未开启消息队列服务的情况下,直接请求接口,会返回1。<br> (2)开启消息队列<br><img src="/Laravel消息队列/img/5.png"></p><h4 id="消息队列的选择"><a href="#消息队列的选择" class="headerlink" title="消息队列的选择"></a>消息队列的选择</h4><p> 一般情况下大部分业务都使用的是redis的消息队列。加入你们公司业务量非常大,几千万甚至几亿就必须考虑使用其他的MQ工具。如<code>ActiveMQ</code>、<code>RabbitMQ</code>、<code>RocketMQ</code>、<code>Kafka</code>。</p><h4 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h4><p> Laravel的消息队列应用比较简单且非常的好用,建议大家可以尝试一下。具体可以看<a href="https://learnku.com/docs/laravel/6.x/queues/5168" target="_blank" rel="noopener">官方文档</a>。</p>]]></content>
<summary type="html">
<h4 id="思维导图"><a href="#思维导图" class="headerlink" title="思维导图"></a>思维导图</h4><img src="/Laravel消息队列/img/2.png">
</summary>
<category term="laravel" scheme="http://www.daichongweb.com/tags/laravel/"/>
</entry>
<entry>
<title>架构之路-mysql主从复制配置篇</title>
<link href="http://www.daichongweb.com/%E6%9E%B6%E6%9E%84%E4%B9%8B%E8%B7%AF-mysql%E4%B8%BB%E4%BB%8E%E5%A4%8D%E5%88%B6%E9%85%8D%E7%BD%AE%E7%AF%87/"/>
<id>http://www.daichongweb.com/架构之路-mysql主从复制配置篇/</id>
<published>2019-11-12T05:09:52.000Z</published>
<updated>2021-09-03T05:56:57.981Z</updated>
<content type="html"><![CDATA[<h4 id="前篇回忆"><a href="#前篇回忆" class="headerlink" title="前篇回忆"></a>前篇回忆</h4><p>上一篇介绍了主从复制的搭建的基础流程,为这篇的配置做了铺垫。便于理解是这篇最大的亮点,说实话经过亲手尝试了主从复制之后,感觉这个东西确实不难,就简单的改几个配置就可以搞定,但是作为高级程序优化的一部分,学习还是很有必要的。<br><a id="more"></a></p><h4 id="配置介绍"><a href="#配置介绍" class="headerlink" title="配置介绍"></a>配置介绍</h4><h5 id="确认环境"><a href="#确认环境" class="headerlink" title="确认环境"></a>确认环境</h5><p>1.服务器1号:192.168.22.130(主库服务器)<br><img src="/架构之路-mysql主从复制配置篇/img/1.png"><br>2.服务器2号:192.168.22.128(从库服务器)<br><img src="/架构之路-mysql主从复制配置篇/img/2.png"></p><h5 id="主库配置"><a href="#主库配置" class="headerlink" title="主库配置"></a>主库配置</h5><figure class="highlight shell"><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">vi /etc/my.cnf</span><br><span class="line"><span class="meta">#</span><span class="bash"> 配置主库标识(这里数字随意,但是一定要比从库配置的数字大,必须是数字)</span></span><br><span class="line">server_id=1</span><br><span class="line"><span class="meta">#</span><span class="bash"> 开启日志功能&配置日志文件</span></span><br><span class="line">log_bin=master_log</span><br><span class="line"><span class="meta">#</span><span class="bash"> 保存退出&重启mysql服务</span></span><br><span class="line">systemctl restart mysqld</span><br></pre></td></tr></table></figure><img src="/架构之路-mysql主从复制配置篇/img/3.png"><h5 id="配置从库连接用户"><a href="#配置从库连接用户" class="headerlink" title="配置从库连接用户"></a>配置从库连接用户</h5><figure class="highlight bash"><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="comment"># 登陆mysql</span></span><br><span class="line">mysql -uroot -p</span><br><span class="line"><span class="comment"># 进入mysql库</span></span><br><span class="line">use mysql</span><br><span class="line"><span class="comment"># 新增一个用户,并且绑定这个用户只能从192.168.22.128这个IP访问</span></span><br><span class="line">grant all privileges on *.* to <span class="string">'slave'</span>@<span class="string">'192.168.22.128'</span> identified by <span class="string">'slave123'</span> with grant option;</span><br><span class="line"><span class="comment"># 刷新权限</span></span><br><span class="line">flush privileges;</span><br><span class="line"><span class="comment"># 这里要注意,真实的正式环境配置需要规定从库的连接IP,不能设置为*。</span></span><br><span class="line"><span class="comment"># 密码不能设置过于简单,最少是字母和数字组合的6位,否则会报错。</span></span><br></pre></td></tr></table></figure><p>查看主库状态<code>show master status</code><br><img src="/架构之路-mysql主从复制配置篇/img/4.png"><br>这里的<code>File</code>就是主库的<code>binlog</code>文件。</p><h5 id="从库配置"><a href="#从库配置" class="headerlink" title="从库配置"></a>从库配置</h5><figure class="highlight bash"><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">vi /etc/my.cnf</span><br><span class="line"><span class="comment"># 这里只需要配置一个标识就行(一定要比主库的标识数字小)</span></span><br><span class="line">server_id=2</span><br><span class="line"><span class="comment"># 重启mysql服务</span></span><br><span class="line">systemctl restart mysqld</span><br><span class="line"><span class="comment"># 关闭slave</span></span><br><span class="line">stop slave</span><br><span class="line"><span class="comment"># 给从库配置主库参数</span></span><br><span class="line">mysql> change master to</span><br><span class="line">-> master_host=<span class="string">"ip地址"</span>,</span><br><span class="line">-> master_user=<span class="string">"授权时指定的用户名"</span>,</span><br><span class="line">-> master_password=<span class="string">"用户密码"</span>,</span><br><span class="line">-> master_log_file=<span class="string">"binlog日志"</span>,</span><br><span class="line">-> master_log_pos=偏移量;</span><br><span class="line"><span class="comment"># 重启从库服务</span></span><br><span class="line">start slave</span><br><span class="line"><span class="comment"># 测试是否正常连接</span></span><br><span class="line">show slave status \G;</span><br><span class="line"><span class="comment"># 如果报错error connecting to master '[email protected]:3306' - retry-time: 60 retries:1</span></span><br><span class="line"><span class="comment"># 请检查密码是不是配置错了</span></span><br></pre></td></tr></table></figure><h5 id="最后测试同步"><a href="#最后测试同步" class="headerlink" title="最后测试同步"></a>最后测试同步</h5><p>再主库创建一个数据表,然后刷新从库看看是否同步成功。<br><img src="/架构之路-mysql主从复制配置篇/img/5.gif"></p><h5 id="总结"><a href="#总结" class="headerlink" title="总结"></a>总结</h5><p>总体流程下来很简单、流程也不复杂、出现奇怪问题的几率小。<br>如果在配置中遇到问题,可在评论区提问,我会第一时间回复。<br><strong>预告:下一篇是读写分离的配置</strong></p>]]></content>
<summary type="html">
<h4 id="前篇回忆"><a href="#前篇回忆" class="headerlink" title="前篇回忆"></a>前篇回忆</h4><p>上一篇介绍了主从复制的搭建的基础流程,为这篇的配置做了铺垫。便于理解是这篇最大的亮点,说实话经过亲手尝试了主从复制之后,感觉这个东西确实不难,就简单的改几个配置就可以搞定,但是作为高级程序优化的一部分,学习还是很有必要的。<br></p>
</summary>
<category term="架构" scheme="http://www.daichongweb.com/tags/%E6%9E%B6%E6%9E%84/"/>
</entry>
<entry>
<title>架构之路-mysql主从复制基础搭建篇</title>
<link href="http://www.daichongweb.com/%E6%9E%B6%E6%9E%84%E4%B9%8B%E8%B7%AF-mysql%E4%B8%BB%E4%BB%8E%E5%A4%8D%E5%88%B6%E5%9F%BA%E7%A1%80%E6%90%AD%E5%BB%BA%E7%AF%87/"/>
<id>http://www.daichongweb.com/架构之路-mysql主从复制基础搭建篇/</id>
<published>2019-11-12T02:18:09.000Z</published>
<updated>2021-09-03T05:56:57.978Z</updated>
<content type="html"><![CDATA[<h4 id="引言"><a href="#引言" class="headerlink" title="引言"></a>引言</h4><p>本文介绍的是在虚拟机上搭建,实际情况其实和真正的线上环境一毛一样,使用的系统是Centos 7。</p><h4 id="什么是主从复制?原理是什么?"><a href="#什么是主从复制?原理是什么?" class="headerlink" title="什么是主从复制?原理是什么?"></a>什么是主从复制?原理是什么?</h4><p>答:简单点理解,主从复制其实就是两个数据库数据的项目备份过程。其原理就是主库产生的操作都会生成<code>binlog</code>传入从库,从库通过<code>I/O</code>线程把<code>binlog</code>写入<code>relaylog</code>,然后从库创建<code>I/O</code>线程执行<code>relaylog</code>进行数据备份。<br><a id="more"></a></p><h4 id="流程图"><a href="#流程图" class="headerlink" title="流程图"></a>流程图</h4><img src="/架构之路-mysql主从复制基础搭建篇/img/1.png"><h4 id="为什么要做主从复制?"><a href="#为什么要做主从复制?" class="headerlink" title="为什么要做主从复制?"></a>为什么要做主从复制?</h4><p>答:一方面是为了备份数据,防止数据丢失和破坏,另一方面是为读写分离做铺垫。</p><h4 id="搭建步骤"><a href="#搭建步骤" class="headerlink" title="搭建步骤"></a>搭建步骤</h4><h5 id="新建虚拟机"><a href="#新建虚拟机" class="headerlink" title="新建虚拟机"></a>新建虚拟机</h5><p>首先在本地安装虚拟机,我个人比较推荐 <code>VMware Workstation Pro</code>,当然也可以是使用其他的。<br>虚拟机的安装就不做介绍了,无非都是下一步下一步。安装好之后在需要下载对用的系统镜像,因为本文主要是在<code>Centos</code>上做演示,所以我就下载了<code>Centos</code>的镜像,但是无法分享给大家,因为太大了,足足<code>4G</code>。</p><p>安装好之后新建两个虚拟机(怎么新建虚拟机就不做介绍了):<br><img src="/架构之路-mysql主从复制基础搭建篇/img/2.png"></p><h5 id="安装mysql"><a href="#安装mysql" class="headerlink" title="安装mysql"></a>安装mysql</h5><p>注意:尽量两个虚拟机上的mysql版本保持一直,避免出现不可预知的错误。<br>我安装的版本是5.7.<br><figure class="highlight shell"><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">#</span><span class="bash"> 进入</span></span><br><span class="line">cd /usr/local/src</span><br><span class="line"><span class="meta">#</span><span class="bash"> 下载rpm包</span></span><br><span class="line">wget https://dev.mysql.com/get/mysql57-community-release-el7-11.noarch.rpm</span><br><span class="line"><span class="meta">#</span><span class="bash"> 安装rpm</span></span><br><span class="line">rpm -ivh mysql57-community-release-el7-11.noarch.rpm</span><br><span class="line"><span class="meta">#</span><span class="bash"> 安装 mysql-server</span></span><br><span class="line">yum install -y mysql-server</span><br><span class="line"><span class="meta">#</span><span class="bash"> 启动 </span></span><br><span class="line">systemctl start mysqld</span><br><span class="line"><span class="meta">#</span><span class="bash"> 设置开机自启</span></span><br><span class="line">systemctl enable mysqld</span><br><span class="line"><span class="meta">#</span><span class="bash"> 登陆mysql</span></span><br><span class="line">mysql -uroot -p</span><br></pre></td></tr></table></figure></p><p>因为5.7之后的版本都是禁止匿名登陆的,你可以通过查看密码并登陆,然后修改密码,或者直接修改<code>my.cnf</code>来禁止登陆验证。<br><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">cat /var/log/mysqld.log|grep 'A temporary password'</span><br></pre></td></tr></table></figure></p><p>因为系统给我的默认密码含有一些特殊符号,我没法输入,我只能使用第二种方法:<br><figure class="highlight shell"><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">vi \etc\my.cnf</span><br><span class="line"><span class="meta">#</span><span class="bash"> 在最后增加一行</span></span><br><span class="line">skip-grant-tables=1</span><br><span class="line"><span class="meta">#</span><span class="bash"> 登陆mysql,刷新权限</span></span><br><span class="line">flush privileges;</span><br><span class="line"><span class="meta">#</span><span class="bash"> 修改密码</span></span><br><span class="line">use mysql;</span><br><span class="line">update user set password='password' where user='root';</span><br><span class="line"><span class="meta">#</span><span class="bash"> 修改成功后再次刷新权限</span></span><br><span class="line"><span class="meta">#</span><span class="bash"> 最后重启一下mysql服务</span></span><br></pre></td></tr></table></figure></p><h5 id="本地连接虚拟机上的mysql"><a href="#本地连接虚拟机上的mysql" class="headerlink" title="本地连接虚拟机上的mysql"></a>本地连接虚拟机上的mysql</h5><figure class="highlight shell"><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="bash"> 查看IP</span></span><br><span class="line">ifconfig</span><br><span class="line"><span class="meta">#</span><span class="bash"> 在本地Cmd中ping这个IP</span></span><br></pre></td></tr></table></figure><h5 id="使用telnet测试mysql连接状态"><a href="#使用telnet测试mysql连接状态" class="headerlink" title="使用telnet测试mysql连接状态"></a>使用telnet测试mysql连接状态</h5><figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">telnet 192.168.22.130 3360</span><br></pre></td></tr></table></figure><h5 id="错误的情况(因我这里是好的,所以我把3306填成了3360)"><a href="#错误的情况(因我这里是好的,所以我把3306填成了3360)" class="headerlink" title="错误的情况(因我这里是好的,所以我把3306填成了3360)"></a>错误的情况(因我这里是好的,所以我把3306填成了3360)</h5><img src="/架构之路-mysql主从复制基础搭建篇/img/3.png"><h5 id="检查虚拟机是否安装了iptables"><a href="#检查虚拟机是否安装了iptables" class="headerlink" title="检查虚拟机是否安装了iptables"></a>检查虚拟机是否安装了iptables</h5><figure class="highlight shell"><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><span class="bash"> 关闭防火墙</span></span><br><span class="line">systemctl stop firewalld</span><br><span class="line"><span class="meta">#</span><span class="bash"> 禁止防火墙</span></span><br><span class="line">systemctl mask firewalld</span><br><span class="line"><span class="meta">#</span><span class="bash"> 禁止开机启动</span></span><br><span class="line">systemctl disable firewalld</span><br><span class="line"><span class="meta">#</span><span class="bash"> 如果实在不行,还要把selinux关闭</span></span><br><span class="line">vi /etc/selinux/config</span><br><span class="line">SELINUX=disabled</span><br></pre></td></tr></table></figure><img src="/架构之路-mysql主从复制基础搭建篇/img/4.png"><img src="/架构之路-mysql主从复制基础搭建篇/img/5.png"><p>再次使用<code>telnet 192.168.22.130 3306</code>还是报错上边图片所示时。</p><h5 id="配置权限"><a href="#配置权限" class="headerlink" title="配置权限"></a>配置权限</h5><figure class="highlight shell"><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><span class="bash"> 创建一个用户</span></span><br><span class="line">GRANT ALL PRIVILEGES ON *.* TO 'daichong'@'%' IDENTIFIED BY 'daichong' WITH GRANT OPTION;</span><br><span class="line"><span class="meta">#</span><span class="bash"> 刷新权限</span></span><br><span class="line">FLUSH PRIVILEGES;</span><br><span class="line"><span class="meta">#</span><span class="bash"> 这里注意真实线上情况权限不能这么开</span></span><br></pre></td></tr></table></figure><img src="/架构之路-mysql主从复制基础搭建篇/img/6.png"><p>出现这个说明已经成功了</p><h5 id="使用navicat连接"><a href="#使用navicat连接" class="headerlink" title="使用navicat连接"></a>使用navicat连接</h5><img src="/架构之路-mysql主从复制基础搭建篇/img/7.png"><p>到这里基础的安装已经完成了,如果遇到问题可在评论中提问,下一篇介绍主从复制如何配置。</p>]]></content>
<summary type="html">
<h4 id="引言"><a href="#引言" class="headerlink" title="引言"></a>引言</h4><p>本文介绍的是在虚拟机上搭建,实际情况其实和真正的线上环境一毛一样,使用的系统是Centos 7。</p>
<h4 id="什么是主从复制?原理是什么?"><a href="#什么是主从复制?原理是什么?" class="headerlink" title="什么是主从复制?原理是什么?"></a>什么是主从复制?原理是什么?</h4><p>答:简单点理解,主从复制其实就是两个数据库数据的项目备份过程。其原理就是主库产生的操作都会生成<code>binlog</code>传入从库,从库通过<code>I/O</code>线程把<code>binlog</code>写入<code>relaylog</code>,然后从库创建<code>I/O</code>线程执行<code>relaylog</code>进行数据备份。<br></p>
</summary>
<category term="架构" scheme="http://www.daichongweb.com/tags/%E6%9E%B6%E6%9E%84/"/>
</entry>
<entry>
<title>laravel模型关联查询与JOIN哪个性能好</title>
<link href="http://www.daichongweb.com/laravel%E6%A8%A1%E5%9E%8B%E5%85%B3%E8%81%94%E6%9F%A5%E8%AF%A2%E4%B8%8EJOIN%E5%93%AA%E4%B8%AA%E6%80%A7%E8%83%BD%E5%A5%BD/"/>
<id>http://www.daichongweb.com/laravel模型关联查询与JOIN哪个性能好/</id>
<published>2019-11-08T08:34:03.000Z</published>
<updated>2021-09-03T05:56:57.930Z</updated>
<content type="html"><![CDATA[<p><strong>初学Laravel</strong></p><p>最近接手一个新项目,整个项目完全看不到<code>left join</code>这样的写法,我打印了模型关联查询后的<code>sql</code>后发现跟常有的查询写法完全不同。<br>原谅我一直是个码农,几乎没见过这样的写法,一直想对比一下这样的写法和常用的写法性能方面到底有什么差别。<br><a id="more"></a><br><strong>一个小栗子</strong></p><p>模型关联生成的sql<br><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">select</span> * <span class="keyword">from</span> <span class="string">`comment`</span> <span class="keyword">where</span> <span class="keyword">exists</span> (<span class="keyword">select</span> * <span class="keyword">from</span> <span class="string">`post_comment`</span> <span class="keyword">where</span> <span class="string">`comment`</span>.<span class="string">`id`</span> = <span class="string">`post_comment`</span>.<span class="string">`comment_id`</span> <span class="keyword">and</span> <span class="string">`post_id`</span> = ?)</span><br></pre></td></tr></table></figure></p><p>常用查询<br><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">SELECT</span> <span class="string">`comment`</span>.id,<span class="string">`comment`</span>.info,<span class="string">`comment`</span>.user_id <span class="keyword">from</span> <span class="string">`comment`</span> <span class="keyword">left</span> <span class="keyword">join</span> post_comment <span class="keyword">on</span> <span class="string">`comment`</span>.id = <span class="string">`post_comment`</span>.comment_id <span class="keyword">where</span> post_comment.post_id = ?</span><br></pre></td></tr></table></figure></p><p>单从<code>sql</code>上看区别还是挺大的,再做码农的期间,最常听到的就是链表查询性能不好。但是还真不能确定这两个<code>sql</code>到底哪个性能好一点,没办法只能测试一下。</p><h3 id="posts-Tables"><a href="#posts-Tables" class="headerlink" title="posts Tables"></a>posts Tables</h3><table><thead><tr><th style="text-align:left">id</th><th style="text-align:center">title</th><th style="text-align:right">time</th></tr></thead><tbody><tr><td style="text-align:left">1</td><td style="text-align:center">模型关联查询</td><td style="text-align:right">2019-11-08</td></tr><tr><td style="text-align:left">2</td><td style="text-align:center">left join 查询</td><td style="text-align:right">2019-11-08</td></tr></tbody></table><h3 id="comment-Tables"><a href="#comment-Tables" class="headerlink" title="comment Tables"></a>comment Tables</h3><table><thead><tr><th style="text-align:left">id</th><th style="text-align:center">info</th><th style="text-align:right">time</th></tr></thead><tbody><tr><td style="text-align:left">1</td><td style="text-align:center">模型关联查询的性能好</td><td style="text-align:right">2019-11-08</td></tr><tr><td style="text-align:left">2</td><td style="text-align:center">left join 查询的性能好</td><td style="text-align:right">2019-11-08</td></tr><tr><td style="text-align:left">3</td><td style="text-align:center">两个都挺好</td><td style="text-align:right">2019-11-08</td></tr></tbody></table><h3 id="post-comment-Tables"><a href="#post-comment-Tables" class="headerlink" title="post_comment Tables"></a>post_comment Tables</h3><table><thead><tr><th style="text-align:left">id</th><th style="text-align:center">post_id</th><th style="text-align:right">comment_id</th></tr></thead><tbody><tr><td style="text-align:left">1</td><td style="text-align:center">1</td><td style="text-align:right">1</td></tr><tr><td style="text-align:left">2</td><td style="text-align:center">2</td><td style="text-align:right">2</td></tr><tr><td style="text-align:left">3</td><td style="text-align:center">3</td><td style="text-align:right">2</td></tr></tbody></table><p>为了避免争议,我添加了一些比较合理的数据。</p><h4 id="数据量"><a href="#数据量" class="headerlink" title="数据量"></a>数据量</h4><table><thead><tr><th style="text-align:left">posts</th><th style="text-align:center">comment</th><th style="text-align:right">post_comment</th></tr></thead><tbody><tr><td style="text-align:left">29999条</td><td style="text-align:center">29999条</td><td style="text-align:right">29999条</td></tr></tbody></table><h4 id="下面使用EXPLAIN进行分析"><a href="#下面使用EXPLAIN进行分析" class="headerlink" title="下面使用EXPLAIN进行分析"></a>下面使用EXPLAIN进行分析</h4><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">EXPLAIN</span> <span class="keyword">select</span> * <span class="keyword">from</span> <span class="string">`comment`</span> <span class="keyword">where</span> <span class="keyword">exists</span> (<span class="keyword">select</span> * <span class="keyword">from</span> <span class="string">`post_comment`</span> <span class="keyword">where</span> <span class="string">`comment`</span>.<span class="string">`id`</span> = <span class="string">`post_comment`</span>.<span class="string">`comment_id`</span> <span class="keyword">and</span> <span class="string">`post_id`</span> = <span class="number">2</span>)</span><br></pre></td></tr></table></figure><table><thead><tr><th style="text-align:center">select_type</th><th style="text-align:right">table</th><th style="text-align:right">partitions</th><th style="text-align:right">type</th></tr></thead><tbody><tr><td style="text-align:center">PRIMARY</td><td style="text-align:right">comment</td><td style="text-align:right">NULL</td><td style="text-align:right">ALL</td></tr><tr><td style="text-align:center">DEPENDENT SUBQUERY</td><td style="text-align:right">post_comment</td><td style="text-align:right">NULL</td><td style="text-align:right">ref</td></tr></tbody></table><table><thead><tr><th style="text-align:right">possible_keys</th><th style="text-align:right">key</th><th style="text-align:right">key_len</th><th style="text-align:right">ref</th></tr></thead><tbody><tr><td style="text-align:right">NULL</td><td style="text-align:right">NULL</td><td style="text-align:right">NULL</td><td style="text-align:right">NULL</td></tr><tr><td style="text-align:right">post_id,comment_id</td><td style="text-align:right">post_id</td><td style="text-align:right">5</td><td style="text-align:right">const</td></tr></tbody></table><table><thead><tr><th style="text-align:right">rows</th><th style="text-align:right">filtered</th><th style="text-align:right">Extra</th></tr></thead><tbody><tr><td style="text-align:right">29999</td><td style="text-align:right">100.00</td><td style="text-align:right">Using where</td></tr><tr><td style="text-align:right">1</td><td style="text-align:right">10.00</td><td style="text-align:right">Using where</td></tr></tbody></table><figure class="highlight sql"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">EXPLAIN</span> <span class="keyword">SELECT</span> <span class="string">`comment`</span>.id,<span class="string">`comment`</span>.info,<span class="string">`comment`</span>.user_id <span class="keyword">from</span> <span class="string">`comment`</span> <span class="keyword">left</span> <span class="keyword">join</span> post_comment <span class="keyword">on</span> <span class="string">`comment`</span>.id = <span class="string">`post_comment`</span>.comment_id <span class="keyword">where</span> post_comment.post_id = <span class="number">2</span></span><br></pre></td></tr></table></figure><table><thead><tr><th style="text-align:left">select_type</th><th style="text-align:center">table</th><th style="text-align:right">partitions</th></tr></thead><tbody><tr><td style="text-align:left">SIMPLE</td><td style="text-align:center">post_comment</td><td style="text-align:right">NULL</td></tr><tr><td style="text-align:left">SIMPLE</td><td style="text-align:center">comment</td><td style="text-align:right">NULL</td></tr></tbody></table><table><thead><tr><th style="text-align:right">type</th><th style="text-align:right">possible_keys</th><th style="text-align:right">key</th><th style="text-align:right">key_len</th></tr></thead><tbody><tr><td style="text-align:right">ref</td><td style="text-align:right">post_id,comment_id</td><td style="text-align:right">post_id</td><td style="text-align:right">5</td></tr><tr><td style="text-align:right">eq_ref</td><td style="text-align:right">PRIMARY</td><td style="text-align:right">PRIMARY</td><td style="text-align:right">4</td></tr></tbody></table><table><thead><tr><th style="text-align:right">ref</th><th style="text-align:right">rows</th><th style="text-align:right">filtered</th><th style="text-align:right">Extra</th></tr></thead><tbody><tr><td style="text-align:right">const</td><td style="text-align:right">1</td><td style="text-align:right">100.00</td><td style="text-align:right">Using where</td></tr><tr><td style="text-align:right">test.post_comment.comment_id</td><td style="text-align:right">1</td><td style="text-align:right">100.00</td><td style="text-align:right">NULL</td></tr></tbody></table><p>从上边的<code>EXPLAIN</code>结果来看,<code>left join</code>比模型关联的写法效率高太多了,之后我在<code>laravel</code>社区也发布了相关的提问,得到的结论是<code>数据量大的时候用JOIN,数据量小的时候用模型</code>。</p><p>从得的的结论来看,模型并适合大数据查询,但是对一些新增、修改、删除操作提供了很好的效果!</p>]]></content>
<summary type="html">
<p><strong>初学Laravel</strong></p>
<p>最近接手一个新项目,整个项目完全看不到<code>left join</code>这样的写法,我打印了模型关联查询后的<code>sql</code>后发现跟常有的查询写法完全不同。<br>原谅我一直是个码农,几乎没见过这样的写法,一直想对比一下这样的写法和常用的写法性能方面到底有什么差别。<br></p>
</summary>
<category term="laravel" scheme="http://www.daichongweb.com/tags/laravel/"/>
</entry>
<entry>
<title>laravel模型关联</title>
<link href="http://www.daichongweb.com/laravel%E6%A8%A1%E5%9E%8B%E5%85%B3%E8%81%94/"/>
<id>http://www.daichongweb.com/laravel模型关联/</id>
<published>2019-11-06T09:30:11.000Z</published>
<updated>2021-09-03T05:56:57.929Z</updated>
<content type="html"><![CDATA[<p><b>一对一</b></p><p> 什么是一对多?</p><p> 在程序角度讲:一对多基本上都是用来描述两个数据表之间的关系。</p><p> 假设现有两个数据表:(1)文章表posts (2)评论表comment。一个文章可以有多个评论,但一个评论只能属于一个文章,相对于评论来说它与文章的关系是多对一,相对与文章来说它与评论的关系是一对多,这也就是laravel里反向关联的基础。</p><p><em>文章表posts</em></p><table><th>id</th><th>title</th><th>time</th><tr><td>1</td><td>什么是一对一?</td><td>2019-11-07</td></tr><tr><td>2</td><td>什么是一对多?</td><td>2019-11-08</td></tr><tr><td>3</td><td>什么是多对多?</td><td>2019-11-06</td></tr></table><br><a id="more"></a><br><br><em>评论表comment</em><br><br><table><th>id</th><th>info</th><th>user_id</th><tr><td>1</td><td>我知道什么是一对一。</td><td>10086</td></tr><tr><td>2</td><td>我知道什么是一对多。</td><td>10085</td></tr><tr><td>3</td><td>我知道什么是多对多。</td><td>10084</td></tr><td>4</td><td>这谁不知道啊!</td><td>10084</td></table><p><em>中间表posts_comment(也可以叫做关系表)</em></p><table><th>id</th><th>post_id</th><th>comment_id</th><tr><td>1</td><td>1</td><td>1</td></tr><tr><td>2</td><td>2</td><td>2</td></tr><tr><td>3</td><td>3</td><td>3</td></tr><tr><td>4</td><td>3</td><td>4</td></tr></table><p> 从表的结构可以看出来,ID=1、2的文章只有一条评论,ID=3的文章有两条评论。</p><p> 那么这是要有个业务,已知文章的ID=3,请使用laravel的模型关联找出该文章下的所有评论。</p><p> 首先确认两个表之间的关系,一个评论在中间表只有一条数据,中间表里的comment_id肯定是唯一的,不可能出现一个评论同时属于两个文章,所以它们之间的关系是<em>一对一</em>。<a>但是,你会发现使用hasMany(多对多)关联方法获取的数据居然是一样的</a>。</p><figure class="highlight plain"><figcaption><span>模型关联</span></figcaption><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><br><span class="line">public function comments()</span><br><span class="line">{</span><br><span class="line"> return $this->hasMany('App\Models\PostComment', 'comment_id', 'id');</span><br><span class="line">}</span><br><span class="line"># 一对一写法</span><br><span class="line">public function comment()</span><br><span class="line">{</span><br><span class="line"> return $this->hasOne('App\Models\PostComment', 'comment_id', 'id');</span><br><span class="line">}</span><br></pre></td></tr></table></figure><figure class="highlight plain"><figcaption><span>查询写法使用(with)</span></figcaption><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">public function list()</span><br><span class="line">{</span><br><span class="line"> $postId = 3;</span><br><span class="line"> $data = \App\Models\Comment::with('comments')->whereHas("comments", function ($query) use ($postId) {</span><br><span class="line"> return $query->where("post_id", $postId);</span><br><span class="line"> })->get();</span><br><span class="line"> dump($data->toArray());</span><br><span class="line">}</span><br></pre></td></tr></table></figure><figure class="highlight plain"><figcaption><span>获取的数据结果(使用with)</span></figcaption><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></pre></td><td class="code"><pre><span class="line"># with('comments);</span><br><span class="line">array:2 [▼</span><br><span class="line"> 0 => array:4 [▼</span><br><span class="line"> "id" => 3</span><br><span class="line"> "info" => "\t我知道什么是多对多"</span><br><span class="line"> "user_id" => 10084</span><br><span class="line"> "comments" => array:1 [▼</span><br><span class="line"> 0 => array:3 [▼</span><br><span class="line"> "id" => 3</span><br><span class="line"> "post_id" => 3</span><br><span class="line"> "comment_id" => 3</span><br><span class="line"> ]</span><br><span class="line"> ]</span><br><span class="line"> ]</span><br><span class="line"> 1 => array:4 [▼</span><br><span class="line"> "id" => 4</span><br><span class="line"> "info" => "这谁不知道啊!"</span><br><span class="line"> "user_id" => 10084</span><br><span class="line"> "comments" => array:1 [▼</span><br><span class="line"> 0 => array:3 [▼</span><br><span class="line"> "id" => 4</span><br><span class="line"> "post_id" => 3</span><br><span class="line"> "comment_id" => 4</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"># with('comment);</span><br><span class="line">array:2 [▼</span><br><span class="line"> 0 => array:4 [▼</span><br><span class="line"> "id" => 3</span><br><span class="line"> "info" => "\t我知道什么是多对多"</span><br><span class="line"> "user_id" => 10084</span><br><span class="line"> "comment" => array:3 [▼</span><br><span class="line"> "id" => 3</span><br><span class="line"> "post_id" => 3</span><br><span class="line"> "comment_id" => 3</span><br><span class="line"> ]</span><br><span class="line"> ]</span><br><span class="line"> 1 => array:4 [▼</span><br><span class="line"> "id" => 4</span><br><span class="line"> "info" => "这谁不知道啊!"</span><br><span class="line"> "user_id" => 10084</span><br><span class="line"> "comment" => array:3 [▼</span><br><span class="line"> "id" => 4</span><br><span class="line"> "post_id" => 3</span><br><span class="line"> "comment_id" => 4</span><br><span class="line"> ]</span><br><span class="line"> ]</span><br><span class="line">]</span><br></pre></td></tr></table></figure><figure class="highlight plain"><figcaption><span>执行的SQL(使用with)</span></figcaption><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"># 两次sql是一样的</span><br><span class="line">array:2 [▼</span><br><span class="line"> 0 => array:3 [▼</span><br><span class="line"> "query" => "select * from `comment` where exists (select * from `post_comment` where `comment`.`id` = `post_comment`.`comment_id` and `post_id` = ?)"</span><br><span class="line"> "bindings" => array:1 [▶]</span><br><span class="line"> "time" => 12.67</span><br><span class="line"> ]</span><br><span class="line"> 1 => array:3 [▼</span><br><span class="line"> "query" => "select * from `post_comment` where `post_comment`.`comment_id` in (3, 4)"</span><br><span class="line"> "bindings" => []</span><br><span class="line"> "time" => 0.21</span><br><span class="line"> ]</span><br><span class="line">]</span><br></pre></td></tr></table></figure><p> 我们分析一下laravel底层的处理逻辑,从上边的sql可以看出使用模型关联第一步会使用一个嵌套查询找出comment在post_comment里存在的结果集,最终的得到的结果是3、4。随后会做一个IN查询得到最终comment.id=3、4的数据最后合并成结果集返回。</p><figure class="highlight plain"><figcaption><span>查询写法使用(不使用with)</span></figcaption><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">public function list()</span><br><span class="line">{</span><br><span class="line"> $postId = 3;</span><br><span class="line"></span><br><span class="line"> $data = \App\Models\Comment::whereHas("comment", function ($query) use ($postId) {</span><br><span class="line"> return $query->where("post_id", $postId);</span><br><span class="line"> })->get();</span><br><span class="line"> dump($data->toArray());</span><br><span class="line">}</span><br></pre></td></tr></table></figure><figure class="highlight plain"><figcaption><span>执行的SQL(不使用with)</span></figcaption><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"># 两次执行sql也是一样的</span><br><span class="line">array:1 [▼</span><br><span class="line"> 0 => array:3 [▼</span><br><span class="line"> "query" => "select * from `comment` where exists (select * from `post_comment` where `comment`.`id` = `post_comment`.`comment_id` and `post_id` = ?)"</span><br><span class="line"> "bindings" => array:1 [▶]</span><br><span class="line"> "time" => 2.82</span><br><span class="line"> ]</span><br><span class="line">]</span><br></pre></td></tr></table></figure><figure class="highlight plain"><figcaption><span>查询的结果(不使用with)</span></figcaption><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><br><span class="line">array:2 [▼</span><br><span class="line"> 0 => array:3 [▼</span><br><span class="line"> "id" => 3</span><br><span class="line"> "info" => "\t我知道什么是多对多"</span><br><span class="line"> "user_id" => 10084</span><br><span class="line"> ]</span><br><span class="line"> 1 => array:3 [▼</span><br><span class="line"> "id" => 4</span><br><span class="line"> "info" => "这谁不知道啊!"</span><br><span class="line"> "user_id" => 10084</span><br><span class="line"> ]</span><br><span class="line">]</span><br></pre></td></tr></table></figure><p> 两种写法的端异想必大家都能看得出来,就不再介绍了。</p><p><b>那么问题来了,为什么要使用模型关联呢?</b></p><p> 假设某一个文章被评论了,在不使用模型关联的情况下需要这样写:</p><figure class="highlight plain"><figcaption><span>普通写法</span></figcaption><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">$mode = new \App\Models\Comment();</span><br><span class="line">$mode->info = '测试';</span><br><span class="line">$mode->user_id = 11;</span><br><span class="line">$mode->save();</span><br><span class="line"></span><br><span class="line">\App\Models\PostComment::create([</span><br><span class="line"> 'post_id' => 3,</span><br><span class="line"> 'comment_id' => $mode->id</span><br><span class="line">]);</span><br></pre></td></tr></table></figure><figure class="highlight plain"><figcaption><span>模型关联写法</span></figcaption><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">$mode = new \App\Models\Comment();</span><br><span class="line">$mode->info = '测试';</span><br><span class="line">$mode->user_id = 11;</span><br><span class="line">$mode->save();</span><br><span class="line"></span><br><span class="line">$mode->comment()->create([</span><br><span class="line"> 'post_id' => 3,</span><br><span class="line">]);</span><br></pre></td></tr></table></figure><p> 而且我的公司有规定不能使用left join写法,而且模型中不允许写有关业务的代码,这样大大限制了随心所欲开发,降低了项目的维护成本。并且在使用模型关联后,一切的代码变得简单了,可读性提高,倒是性能这块我没有真正的测试过,之后肯定会研究一下。</p>]]></content>
<summary type="html">
<p><b>一对一</b></p>
<p>&emsp;什么是一对多?</p>
<p>&emsp;在程序角度讲:一对多基本上都是用来描述两个数据表之间的关系。</p>
<p>&emsp;假设现有两个数据表:(1)文章表posts (2)评论表comment。一个文章可以有多个评论,但一个评论只能属于一个文章,相对于评论来说它与文章的关系是多对一,相对与文章来说它与评论的关系是一对多,这也就是laravel里反向关联的基础。</p>
<p><em>文章表posts</em></p>
<table><th>id</th><th>title</th><th>time</th><tr><td>1</td><td>什么是一对一?</td><td>2019-11-07</td></tr><tr><td>2</td><td>什么是一对多?</td><td>2019-11-08</td></tr><tr><td>3</td><td>什么是多对多?</td><td>2019-11-06</td></tr></table><br>
</summary>
<category term="laravel" scheme="http://www.daichongweb.com/tags/laravel/"/>
</entry>
</feed>