-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsearch.xml
447 lines (213 loc) · 240 KB
/
search.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
<?xml version="1.0" encoding="utf-8"?>
<search>
<entry>
<title>(技術)十分鐘內架設好Terraria遊戲伺服器</title>
<link href="/(%E6%8A%80%E8%A1%93)%E5%8D%81%E5%88%86%E9%90%98%E5%85%A7%E6%9E%B6%E8%A8%AD%E5%A5%BDTerraria%E9%81%8A%E6%88%B2%E4%BC%BA%E6%9C%8D%E5%99%A8/"/>
<url>/(%E6%8A%80%E8%A1%93)%E5%8D%81%E5%88%86%E9%90%98%E5%85%A7%E6%9E%B6%E8%A8%AD%E5%A5%BDTerraria%E9%81%8A%E6%88%B2%E4%BC%BA%E6%9C%8D%E5%99%A8/</url>
<content type="html"><![CDATA[<h2 id="多人遊戲"><a href="#多人遊戲" class="headerlink" title="多人遊戲"></a>多人遊戲</h2><p>開設一個遊戲伺服器大概有2種方式,透過本機開設伺服器或是使用第三方託管伺服器,前者需要自行處理軟硬體設定,防火牆<br>、路由轉發,下載並設定伺服器軟體,遇到DDOS時相當難處哩,但也有自由度高的優點,使用雲端遊戲伺服器變成更好的選擇,可以在幾分鐘內設定好,隨時依照需求拓展伺服器規格,<a href="https://godlike.host/">godlike</a>提供了市面熱門遊戲的整合,<br>TF、Minecraft、GTA5、CS、Terraria,費用也相當實惠,8人以下規格,每月僅需要200多台幣,以下會介紹設定。</p><h2 id="雲端託管伺服器"><a href="#雲端託管伺服器" class="headerlink" title="雲端託管伺服器"></a>雲端託管伺服器</h2><h3 id="選擇方案並付款"><a href="#選擇方案並付款" class="headerlink" title="選擇方案並付款"></a>選擇方案並付款</h3><p><img src="/images/terraria/godlike/1.webp"></p><h3 id="伺服器面板"><a href="#伺服器面板" class="headerlink" title="伺服器面板"></a>伺服器面板</h3><p>透過按鈕啟動、關閉伺服器,也可以透過指令控制伺服器</p><p>help Displays a list of commands.<br>playing Shows the list of players.<br>clear Clear the console window.<br>exit Shutdown the server and save.<br>exit-nosave Shutdown the server without saving.<br>save Save the game world.<br>kick player Kicks a player from the server.<br>ban player Bans a player from the server.<br>password Show password.<br>password pass Change password.<br>version Print version number.<br>time Display game time.<br>port Print the listening port.<br>maxplayers Print the max number of players.<br>say words Send a message.<br>motd Print MOTD.<br>motd words Change MOTD.<br>dawn Change time to dawn.<br>noon Change time to noon.<br>dusk Change time to dusk.<br>midnight Change time to midnight.<br>settle Settle all water.<br>seed Displays the world seed.</p><p><img src="/images/terraria/godlike/2.webp"><br><img src="/images/terraria/godlike/3.webp"></p><h3 id="複製IP、PORT"><a href="#複製IP、PORT" class="headerlink" title="複製IP、PORT"></a>複製IP、PORT</h3><p><img src="/images/terraria/godlike/4.webp"></p><h3 id="遊戲中輸入IP、PORT來加入"><a href="#遊戲中輸入IP、PORT來加入" class="headerlink" title="遊戲中輸入IP、PORT來加入"></a>遊戲中輸入IP、PORT來加入</h3><p><img src="/images/terraria/godlike/5.webp"><br><img src="/images/terraria/godlike/6.webp"><br><img src="/images/terraria/godlike/7.webp"><br><img src="/images/terraria/godlike/8.webp"></p>]]></content>
</entry>
<entry>
<title>(技術)開發一隻高防禦血量的變態屠夫</title>
<link href="/(%E6%8A%80%E8%A1%93)%E9%96%8B%E7%99%BC%E4%B8%80%E9%9A%BB%E9%AB%98%E9%98%B2%E7%A6%A6%E8%A1%80%E9%87%8F%E7%9A%84%E8%AE%8A%E6%85%8B%E5%B1%A0%E5%A4%AB/"/>
<url>/(%E6%8A%80%E8%A1%93)%E9%96%8B%E7%99%BC%E4%B8%80%E9%9A%BB%E9%AB%98%E9%98%B2%E7%A6%A6%E8%A1%80%E9%87%8F%E7%9A%84%E8%AE%8A%E6%85%8B%E5%B1%A0%E5%A4%AB/</url>
<content type="html"><![CDATA[<h2 id="設計"><a href="#設計" class="headerlink" title="設計"></a>設計</h2><p>泰拉瑞亞困難模式前的小怪,血量大約在200以下,這時候的武器傷害大多在50以下,直到打敗血肉墻後的血月,會出現像是釘頭這樣血量4000多的精英怪,今天想要設計一款血量、高防禦、高抗擊退的肥胖殭屍,其原型參考CSO的達叔,也是我最喜歡的一隻殭屍。</p><h2 id="sprite"><a href="#sprite" class="headerlink" title="sprite"></a>sprite</h2><p><img src="/images/terraria/npcs/giantBee.jpg"><br>「Sprite」是指 2D 遊戲中常見的 2D 圖形,在單一影像中具有多個“幀”,被稱為精靈表。用於動畫或變化,上圖的蜂王有4個幀,遊戲知道將 96 像素高的分成4個大小相等、24像素高的部分,遊戲會在這4幀之間循環,另外規定sprite必須是png檔,表中的圖必須被2像素分割,人物面向左側。</p><p>先用小畫家畫一張圖<br><img src="/images/terraria/npcs/TestZombie3.webp"></p><h2 id="高防禦血量且有獨特掉落物的殭屍"><a href="#高防禦血量且有獨特掉落物的殭屍" class="headerlink" title="高防禦血量且有獨特掉落物的殭屍"></a>高防禦血量且有獨特掉落物的殭屍</h2><figure class="highlight csharp"><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">using</span> Terraria;</span><br><span class="line"><span class="keyword">using</span> Terraria.ID;</span><br><span class="line"><span class="keyword">using</span> Terraria.ModLoader;</span><br><span class="line"><span class="keyword">using</span> Terraria.ModLoader.Utilities;</span><br><span class="line"><span class="keyword">using</span> Terraria.GameContent.Bestiary;</span><br><span class="line"><span class="keyword">using</span> Terraria.GameContent.ItemDropRules;</span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> <span class="title">TestMod.Content.NPCs</span></span><br><span class="line">{ </span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">class</span> <span class="title">TestZombie</span> : <span class="title">ModNPC</span></span><br><span class="line"> {</span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">override</span> <span class="keyword">void</span> <span class="title">SetStaticDefaults</span>()</span></span><br><span class="line"> {</span><br><span class="line"> <span class="comment">// 殭屍幀數</span></span><br><span class="line"> Main.npcFrameCount[Type] = Main.npcFrameCount[NPCID.Zombie];</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 微光轉變成骷髏(減肥的概念)</span></span><br><span class="line"> NPCID.Sets.ShimmerTransformToNPC[NPC.type] = NPCID.Skeleton;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 怪物圖鑑動畫</span></span><br><span class="line"> NPCID.Sets.NPCBestiaryDrawModifiers <span class="keyword">value</span> = <span class="keyword">new</span>()</span><br><span class="line"> {</span><br><span class="line"> Velocity = <span class="number">1f</span></span><br><span class="line"> };</span><br><span class="line"> NPCID.Sets.NPCBestiaryDrawOffset.Add(Type, <span class="keyword">value</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">override</span> <span class="keyword">void</span> <span class="title">SetDefaults</span>()</span></span><br><span class="line"> {</span><br><span class="line"> NPC.CloneDefaults(NPCID.Zombie);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 高血量、防禦、擊退</span></span><br><span class="line"> NPC.damage = <span class="number">10</span>;</span><br><span class="line"> NPC.defense = <span class="number">12</span>;</span><br><span class="line"> NPC.lifeMax = <span class="number">2000</span>;</span><br><span class="line"> NPC.<span class="keyword">value</span> = <span class="number">60f</span>;</span><br><span class="line"> NPC.knockBackResist = <span class="number">0.9f</span>;</span><br><span class="line"> AIType = NPCID.Zombie;</span><br><span class="line"> AnimationType = NPCID.Zombie;</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 掉落殭屍旗</span></span><br><span class="line"> Banner = Item.NPCtoBanner(NPCID.Zombie);</span><br><span class="line"> BannerItem = Item.BannerToItem(Banner);</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="function"><span class="keyword">public</span> <span class="keyword">override</span> <span class="keyword">void</span> <span class="title">ModifyNPCLoot</span>(<span class="params">NPCLoot npcLoot</span>)</span></span><br><span class="line"> {</span><br><span class="line"> npcLoot.Add(ItemDropRule.Common(ItemID.PsychoKnife, <span class="number">25</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="function"><span class="keyword">public</span> <span class="keyword">override</span> <span class="built_in">float</span> <span class="title">SpawnChance</span>(<span class="params">NPCSpawnInfo spawnInfo</span>)</span></span><br><span class="line"> {</span><br><span class="line"> <span class="keyword">return</span> SpawnCondition.OverworldNightMonster.Chance - <span class="number">0.45f</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="function"><span class="keyword">public</span> <span class="keyword">override</span> <span class="keyword">void</span> <span class="title">SetBestiary</span>(<span class="params">BestiaryDatabase database, BestiaryEntry bestiaryEntry</span>)</span></span><br><span class="line"> {</span><br><span class="line"> bestiaryEntry.Info.AddRange(<span class="keyword">new</span> IBestiaryInfoElement[]</span><br><span class="line"> {</span><br><span class="line"> BestiaryDatabaseNPCsPopulator.CommonTags.SpawnConditions.Times.NightTime,</span><br><span class="line"> <span class="keyword">new</span> FlavorTextBestiaryInfoElement(<span class="string">"Psycho Zombie"</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></pre></td></tr></table></figure><h2 id="遊戲畫面-大師困難模式"><a href="#遊戲畫面-大師困難模式" class="headerlink" title="遊戲畫面(大師困難模式)"></a>遊戲畫面(大師困難模式)</h2><p><img src="/images/terraria/npcs/zombieInGame.webp"></p>]]></content>
</entry>
<entry>
<title>(技術)開發一把Terraria超級酷炫的莫托洛夫之劍</title>
<link href="/(%E6%8A%80%E8%A1%93)%E9%96%8B%E7%99%BC%E4%B8%80%E6%8A%8ATerraria%E8%B6%85%E7%B4%9A%E9%85%B7%E7%82%AB%E7%9A%84%E8%8E%AB%E6%89%98%E6%B4%9B%E5%A4%AB%E4%B9%8B%E5%8A%8D/"/>
<url>/(%E6%8A%80%E8%A1%93)%E9%96%8B%E7%99%BC%E4%B8%80%E6%8A%8ATerraria%E8%B6%85%E7%B4%9A%E9%85%B7%E7%82%AB%E7%9A%84%E8%8E%AB%E6%89%98%E6%B4%9B%E5%A4%AB%E4%B9%8B%E5%8A%8D/</url>
<content type="html"><![CDATA[<h2 id="Terraria"><a href="#Terraria" class="headerlink" title="Terraria"></a>Terraria</h2><blockquote><p>《泰拉瑞亞》(英語:Terraria)是一款2D沙盒模擬遊戲,由Re-Logic開發。名稱來自土族缸。《泰拉瑞亞》的遊戲特色是在一個隨機生成的2D世界裡探索、創造、建築,並與各種生物戰鬥,類似於銀河戰士系列和《惡魔城X 月下夜想曲》。[6][7][8]遊戲2011年5月16日最初發布在Windows平台,此後,陸續發布了支援其他作業系統、主機、智慧型手機和平板電腦等的版本。遊戲發布時受到普遍正面評價,其沙盒元素頗受好評。截止到2022年5月全平台累積銷量逾4450萬套,成為有史以來銷量最好的遊戲之一。</p></blockquote><h2 id="tModLoader"><a href="#tModLoader" class="headerlink" title="tModLoader"></a>tModLoader</h2><blockquote><p>tModLoader(TML)是一個免費的程序,允許使用模組遊玩泰拉瑞亞。其內置的模組瀏覽器能夠下載並更新模組,也能上傳自己製作的模組。tModLoader 由 TML 團隊開發製作,並由其發布為獨立程序,不過它也可在 Steam 上作為泰拉瑞亞的可下載內容(DLC)獲取。關於包含製作模組和使用 tModLoader 的信息的官方 tModLoader Wiki 可以在 GitHub 上找到。</p></blockquote><h2 id="開發準備"><a href="#開發準備" class="headerlink" title="開發準備"></a>開發準備</h2><p>1.<code>.NET 8 SDK</code><br>2.<a href="https://https//visualstudio.microsoft.com/zh-hant/vs/">Visual Studio 2022</a><br>3.<a href="https://docs.google.com/document/d/1xRz3kFNbewb8DI29AKXuyi6O327IcxlgihZ7sdK_IuE/edit">Quick Terraria-specific C# crash course</a><br>4.<a href="https://steamcommunity.com/sharedfiles/filedetails/?id=2563784437">CheatSheet</a></p><h2 id="C-OOP"><a href="#C-OOP" class="headerlink" title="C# OOP"></a>C# OOP</h2><p>1.抽象類別不能實作<br>2.繼承抽象類別的子類必須複寫父類的的抽象方法<br>3.呼叫衍生類的虛擬類都是最終衍生類的實現<br>4.覆寫(Override)子類別可以覆寫父類別的方法<br>5.多載(Overload)一個類別中,定義多個名稱相同,但參數不同的方法<br>6.多型(Polymorphism)是指父類別可透過子類別衍伸成多種型態</p><h2 id="自動生成模組"><a href="#自動生成模組" class="headerlink" title="自動生成模組"></a>自動生成模組</h2><h3 id="架構"><a href="#架構" class="headerlink" title="架構"></a>架構</h3><p>1.[ModName].cs-唯一模組檔<br>2.description.txt-模組說明<br>3.build.txt-版本、作者、顯示名稱<br>4.icon.png -模組圖標<br>5.[ModName].csproj<br>6.Properties/launchSettings.json- tModLoader debug路徑<br>7.Content/Items/[ItemName].cs-自定義的核心邏輯<br>8.Content/Items/[ItemName].png-圖片<br>9.Localization/en-US_Mods.[ModName].hjson-物品名、物品說明</p><h3 id="流程"><a href="#流程" class="headerlink" title="流程"></a>流程</h3><p>創建模組>vs打開<code>C:\Users\USER\Documents\My Games\Terraria\tModLoader\ModSources\TestMod</code>編輯>熱加載/手動加載<br><img src="/images/terraria/1.webp"><br><img src="/images/terraria/2.webp"><br><img src="/images/terraria/3.webp"></p><h2 id="開發須知"><a href="#開發須知" class="headerlink" title="開發須知"></a>開發須知</h2><p>1.ModItem 有不同的 hook 可以被玩家改寫,hook會被在遊戲更新迴圈中呼叫,想更改手槍發射的邏輯,可以修改<code>ModItem.Shoot</code></p><p>2.每個物品都有唯一的<code>Type</code>,以及被存在物品陣列的<code>Index</code>,兩者獨立無關聯性</p><p>3.Sprite 是指 2D 遊戲中常見的 2D 圖形,必須是 .png 檔案,動態sprite例如蜂王,必須使用2像素來分割</p><p>4.約定方向,NPC向左,箭頭往上,法杖往右上</p><h2 id="超級酷炫的莫托洛夫之劍"><a href="#超級酷炫的莫托洛夫之劍" class="headerlink" title="超級酷炫的莫托洛夫之劍"></a>超級酷炫的莫托洛夫之劍</h2><p>我想要一把能夠射出持續燃燒火焰,同時具有酷炫燃燒特效、音效的刀</p><figure class="highlight csharp"><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="keyword">using</span> Terraria;</span><br><span class="line"><span class="keyword">using</span> Terraria.ID;</span><br><span class="line"><span class="keyword">using</span> Terraria.ModLoader;</span><br><span class="line"><span class="keyword">using</span> Microsoft.Xna.Framework;</span><br><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> <span class="title">TestMod.Content.Items</span></span><br><span class="line">{ </span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">class</span> <span class="title">TestSword</span> : <span class="title">ModItem</span></span><br><span class="line"> {</span><br><span class="line"> <span class="comment">// 設定劍的數值,長、寬、擊退等</span></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">override</span> <span class="keyword">void</span> <span class="title">SetDefaults</span>()</span></span><br><span class="line"> {</span><br><span class="line"> Item.damage = <span class="number">50</span>;</span><br><span class="line"> Item.DamageType = DamageClass.Melee;</span><br><span class="line"> Item.width = <span class="number">40</span>;</span><br><span class="line"> Item.height = <span class="number">40</span>;</span><br><span class="line"> Item.useTime = <span class="number">20</span>;</span><br><span class="line"> Item.useAnimation = <span class="number">20</span>;</span><br><span class="line"> Item.useStyle = ItemUseStyleID.Swing;</span><br><span class="line"> Item.knockBack = <span class="number">6</span>;</span><br><span class="line"> Item.<span class="keyword">value</span> = Item.buyPrice(silver: <span class="number">1</span>);</span><br><span class="line"> Item.rare = ItemRarityID.Blue;</span><br><span class="line"> Item.UseSound = SoundID.Item1;</span><br><span class="line"> Item.autoReuse = <span class="literal">true</span>;</span><br><span class="line"> Item.shoot = ProjectileID.MolotovFire;</span><br><span class="line"> Item.shootSpeed = <span class="number">10f</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="function"><span class="keyword">public</span> <span class="keyword">override</span> <span class="keyword">void</span> <span class="title">MeleeEffects</span>(<span class="params">Player player, Rectangle hitbox</span>)</span></span><br><span class="line"> {</span><br><span class="line"> <span class="built_in">int</span> dust = Dust.NewDust(<span class="keyword">new</span> Vector2(hitbox.X, hitbox.Y), hitbox.Width, hitbox.Height, DustID.AmberBolt);</span><br><span class="line"> Main.dust[dust].noGravity = <span class="literal">true</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 註冊到品項集合中</span></span><br><span class="line"> <span class="function"><span class="keyword">public</span> <span class="keyword">override</span> <span class="keyword">void</span> <span class="title">AddRecipes</span>()</span></span><br><span class="line"> {</span><br><span class="line"> Recipe recipe = CreateRecipe();</span><br><span class="line"> recipe.AddIngredient(ItemID.DirtBlock, <span class="number">10</span>);</span><br><span class="line"> recipe.AddTile(TileID.WorkBenches);</span><br><span class="line"> recipe.Register();</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><p><img src="/images/terraria/4.webp"></p><h2 id="Ref"><a href="#Ref" class="headerlink" title="Ref"></a>Ref</h2><p><a href="https://zh.wikipedia.org/zh-tw/%E6%B3%B0%E6%8B%89%E7%91%9E%E4%BA%9A">https://zh.wikipedia.org/zh-tw/%E6%B3%B0%E6%8B%89%E7%91%9E%E4%BA%9A</a><br><a href="https://terraria.wiki.gg/zh/wiki/TModLoader?variant=zh-tw">https://terraria.wiki.gg/zh/wiki/TModLoader?variant=zh-tw</a><br><a href="https://github.com/tModLoader/tModLoader/wiki/Basic-tModLoader-Modding-Guide">https://github.com/tModLoader/tModLoader/wiki/Basic-tModLoader-Modding-Guide</a><br><a href="https://docs.tmodloader.net/docs/stable/class_mod_item.html">https://docs.tmodloader.net/docs/stable/class_mod_item.html</a></p>]]></content>
</entry>
<entry>
<title>(心得)免費修復開機鍵故障節省 500 元以上</title>
<link href="/(%E5%BF%83%E5%BE%97)%E5%85%8D%E8%B2%BB%E4%BF%AE%E5%BE%A9%E9%96%8B%E6%A9%9F%E9%8D%B5%E6%95%85%E9%9A%9C%E7%AF%80%E7%9C%81-500-%E5%85%83%E4%BB%A5%E4%B8%8A/"/>
<url>/(%E5%BF%83%E5%BE%97)%E5%85%8D%E8%B2%BB%E4%BF%AE%E5%BE%A9%E9%96%8B%E6%A9%9F%E9%8D%B5%E6%95%85%E9%9A%9C%E7%AF%80%E7%9C%81-500-%E5%85%83%E4%BB%A5%E4%B8%8A/</url>
<content type="html"><![CDATA[<p>大多數預設開機方式是點擊開機鍵,但彈簧老化,按下去沒反應,檢修行情一次落在500以上,不保證修好,相當不划算,提供以下替代方案</p><p>1.定時開機<br>進入 BIOS 介面,搜尋 RTC Alarm,要檢查系統時間是否正確</p><p>2.PS2 鍵盤滑鼠開機<br>進入 BIOS 介面,搜尋 Power on by ps/2 keyboard,通常不支援 USB 輸入</p><p>3.網卡開機<br>進入 BIOS 介面,搜尋 WOL(Wake on Lan),下載並設定 magic packet</p><p>4.reset 開機<br>將開機鍵拔起來,重開機鍵插上去,但不是每台電腦都有重開機鍵</p><p>5.過電開機<br>進入 BIOS 介面,搜尋 AC POWER,設為 Power on</p><p>我選擇過電開機,1~3 設定麻煩,4 針腳插不好可能壞掉,過電開機是最輕鬆的方式,打開延長線開關即可,也沒有開機鍵硬體老化等問題。</p>]]></content>
</entry>
<entry>
<title>(遊戲)獨自殲滅11名PUBG玩家並吃雞</title>
<link href="/(%E9%81%8A%E6%88%B2)%E7%8D%A8%E8%87%AA%E6%AE%B2%E6%BB%8511%E5%90%8DPUBG%E7%8E%A9%E5%AE%B6%E4%B8%A6%E5%90%83%E9%9B%9E/"/>
<url>/(%E9%81%8A%E6%88%B2)%E7%8D%A8%E8%87%AA%E6%AE%B2%E6%BB%8511%E5%90%8DPUBG%E7%8E%A9%E5%AE%B6%E4%B8%A6%E5%90%83%E9%9B%9E/</url>
<content type="html"><![CDATA[<h1 id="遊戲-獨自殲滅11名PUBG玩家並吃雞"><a href="#遊戲-獨自殲滅11名PUBG玩家並吃雞" class="headerlink" title="(遊戲)獨自殲滅11名PUBG玩家並吃雞"></a>(遊戲)獨自殲滅11名PUBG玩家並吃雞</h1><p><img src="/images/pubg/pro.jpg"></p><p>開放免費後,入坑 PUBG 兩個賽季了,對 LITE 沒有的武器感到新奇,Lynx AMR 反器材炮、P90 零後座衝鋒、MG3 異次元火力、Groza 近距步槍之王、Famas 遠距步槍之王、Dragunov 連發栓狙,但我最喜歡的還是 Beryl M762,高居第一位的非空投 DPS 五秒內能秒掉一隊。</p><p>超高輸出的代價就是超高後座力,選用補償器 + 水平握把能夠抵銷成 k2 的手感,頭線加上預開,100 等以前玩家隨便虐,策略上來說,採用壓線進圈,比起先進圈。</p><h2 id="壓線進圈"><a href="#壓線進圈" class="headerlink" title="壓線進圈"></a>壓線進圈</h2><h3 id="優點"><a href="#優點" class="headerlink" title="優點"></a>優點</h3><ul><li>抓跑圈仔屁股</li><li>不擔心被後面偷襲</li><li>槍法夠準滾人頭快</li></ul><h3 id="缺點"><a href="#缺點" class="headerlink" title="缺點"></a>缺點</h3><ul><li>害怕伏地魔</li><li>害怕高位槍線</li><li>對投擲物、藥品需求高</li></ul><p>像我這種單人組四排的玩家,不太可能像戰隊直接在自閉城獵殺玩家,比較多的是掌握資訊後偷襲,想要一打多的策略是逐一擊破,從高位槍線逐一抓掉,封煙扶人立刻補手榴彈,低段位玩家不擅長使用投擲物,事實上這遊戲的掩體優勢並沒有如此巨大,只要手榴彈丟的夠準,沒掩體也不是大問題。</p><h2 id="吃雞"><a href="#吃雞" class="headerlink" title="吃雞"></a>吃雞</h2><p>這遊戲七成吃運氣,等待時隊友等級太低直接跳 game (不算戰績),運氣很背沒掩體又被刷出圈只能認了,有一種說法是空投會落在下一個圈內(未經證實),前期遊走在邊線抓人,後期在圈中心當伏地魔,選高地,選掩體,剩下交給時間跟運氣。</p><p><img src="/images/pubg/season-stat-27.jpg"></p>]]></content>
<categories>
<category> Diary </category>
</categories>
</entry>
<entry>
<title>(技術)使用Laravel-Batch與Pusher上傳20萬筆庫存</title>
<link href="/(%E6%8A%80%E8%A1%93)%E4%BD%BF%E7%94%A8Laravel-Batch%E8%88%87Pusher%E4%B8%8A%E5%82%B320%E8%90%AC%E7%AD%86%E5%BA%AB%E5%AD%98/"/>
<url>/(%E6%8A%80%E8%A1%93)%E4%BD%BF%E7%94%A8Laravel-Batch%E8%88%87Pusher%E4%B8%8A%E5%82%B320%E8%90%AC%E7%AD%86%E5%BA%AB%E5%AD%98/</url>
<content type="html"><![CDATA[<h2 id="Queue"><a href="#Queue" class="headerlink" title="Queue"></a>Queue</h2><ul><li>異步</li><li>重試</li></ul><h2 id="應用"><a href="#應用" class="headerlink" title="應用"></a>應用</h2><ul><li>建立、取消訂單</li><li>電子郵件</li><li>webhook</li><li>自動付款、退款</li><li>每月報表、帳單</li><li>圖片、視頻上傳</li><li>更新索引</li></ul><h2 id="流程"><a href="#流程" class="headerlink" title="流程"></a>流程</h2><p>1.設定<code>config/queue.php</code>、<code>.env</code><br>2.<code>php artisan queue:table / php artisan migrate</code><br>3.<code>php artisan make:job <name></code><br>4.<code>啟動 Queue Listener</code><br>5.<code>Supervisor / Horizon 監控 </code></p><h2 id="介面"><a href="#介面" class="headerlink" title="介面"></a>介面</h2><ul><li>單例 <code>ShouldBeUnique</code></li><li>加密 <code>ShouldBeEncrypted</code></li></ul><h2 id="自選"><a href="#自選" class="headerlink" title="自選"></a>自選</h2><p>class 屬性優先於指令</p><p>1.重試</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">php artisan queue:work --tries 3</span><br></pre></td></tr></table></figure><p>2.優先</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">php artisan queue:work --queue</span><br></pre></td></tr></table></figure><p>3.超時</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">php artisan queue:work --timeout</span><br></pre></td></tr></table></figure><p>4.middleware</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">middleware</span>(<span class="params"></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> [<span class="keyword">new</span> <span class="title class_">RateLimited</span>];</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="Batch"><a href="#Batch" class="headerlink" title="Batch"></a>Batch</h2><ul><li>追蹤同類型作業</li><li>執行工作並更新進度</li></ul><h2 id="建表"><a href="#建表" class="headerlink" title="建表"></a>建表</h2><figure class="highlight plaintext"><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">php artisan queue:table</span><br><span class="line"></span><br><span class="line">php artisan queue:batches-table</span><br><span class="line"> </span><br><span class="line">php artisan migrate</span><br></pre></td></tr></table></figure><h2 id="use"><a href="#use" class="headerlink" title="use"></a>use</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">use Batchable</span><br></pre></td></tr></table></figure><h2 id="dispatch"><a href="#dispatch" class="headerlink" title="dispatch"></a>dispatch</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Bus::batch</span><br></pre></td></tr></table></figure><h2 id="worker"><a href="#worker" class="headerlink" title="worker"></a>worker</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">php artisan queue:work</span><br></pre></td></tr></table></figure><h2 id="架構設計"><a href="#架構設計" class="headerlink" title="架構設計"></a>架構設計</h2><ul><li>websocket及時更新</li><li>非同步</li><li>pub-sub</li></ul><p>每1000筆資料分塊上傳,worker完成job後查詢進度,發佈到客戶端</p><h2 id="views"><a href="#views" class="headerlink" title="views"></a>views</h2><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><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></pre></td><td class="code"><pre><span class="line"><!DOCTYPE html></span><br><span class="line"><html lang=<span class="string">"en"</span>></span><br><span class="line"></span><br><span class="line"><head></span><br><span class="line"> <meta charset=<span class="string">"UTF-8"</span>></span><br><span class="line"> <meta name=<span class="string">"viewport"</span> content=<span class="string">"width=device-width, initial-scale=1.0"</span>></span><br><span class="line"> <title>PusherBatchUploader</title></span><br><span class="line"> <link rel=<span class="string">"stylesheet"</span> href=<span class="string">"{{ asset('build/assets/app-00ef6d16.css') }}"</span>></span><br><span class="line"> <link rel=<span class="string">"stylesheet"</span> href=<span class="string">"https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.css"</span>></span><br><span class="line"> <link rel=<span class="string">"stylesheet"</span> href=<span class="string">"https://cdn.datatables.net/1.10.19/css/dataTables.bootstrap4.min.css"</span>></span><br><span class="line"></head></span><br><span class="line"></span><br><span class="line"><body></span><br><span class="line"> <script src=<span class="string">"https://code.jquery.com/jquery-3.6.0.min.js"</span>></script></span><br><span class="line"> <script src=<span class="string">"https://cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js"</span>></script></span><br><span class="line"> <script src=<span class="string">"https://cdn.datatables.net/1.10.19/js/dataTables.bootstrap4.min.js"</span>></script></span><br><span class="line"> <script src=<span class="string">"https://js.pusher.com/8.2.0/pusher.min.js"</span>></script></span><br><span class="line"> <script></span><br><span class="line"> Pusher.logToConsole = <span class="literal">true</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">var</span> pusher = <span class="keyword">new</span> <span class="title class_">Pusher</span>(<span class="string">'4ba467a4d146b608c291'</span>, {</span><br><span class="line"> cluster: <span class="string">'ap3'</span></span><br><span class="line"> });</span><br><span class="line"> <span class="keyword">var</span> channel = pusher.<span class="title function_ invoke__">subscribe</span>(<span class="string">'batch-progress'</span>);</span><br><span class="line"> channel.<span class="title function_ invoke__">bind</span>(<span class="string">'pusher:subscription_succeeded'</span>, function (data) {</span><br><span class="line"> console.<span class="title function_ invoke__">log</span>(data);</span><br><span class="line"> });</span><br><span class="line"> channel.<span class="title function_ invoke__">bind</span>(<span class="string">'batch-progress-updated'</span>, function (data) {</span><br><span class="line"> $(<span class="string">'#uploadStatus'</span>).<span class="title function_ invoke__">html</span>(<span class="string">'處理中'</span>);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">if</span> (data.progress === <span class="number">100</span>) {</span><br><span class="line"> location.<span class="title function_ invoke__">reload</span>();</span><br><span class="line"> }</span><br><span class="line"> $(<span class="string">'.progressBarValue'</span>).<span class="title function_ invoke__">css</span>(<span class="string">'width'</span>, data.progress + <span class="string">"%"</span>);</span><br><span class="line"></span><br><span class="line"> console.<span class="title function_ invoke__">log</span>(data);</span><br><span class="line"> });</span><br><span class="line"> </script></span><br><span class="line"></span><br><span class="line"> <div id=<span class="string">"form"</span>></span><br><span class="line"> <form id=<span class="string">"uploadForm"</span> action=<span class="string">"/uploadCsv"</span> method=<span class="string">"post"</span> enctype=<span class="string">"multipart/form-data"</span>></span><br><span class="line"> @csrf</span><br><span class="line"> <input type=<span class="string">"file"</span> name=<span class="string">"mycsv"</span> id=<span class="string">"mycsv"</span>></span><br><span class="line"> <button type=<span class="string">"button"</span> onclick=<span class="string">"uploadFile()"</span>></span><br><span class="line"> Upload</span><br><span class="line"> </button></span><br><span class="line"> </form></span><br><span class="line"> </div></span><br><span class="line"></span><br><span class="line"> <div <span class="class"><span class="keyword">class</span>="<span class="title">progressBar</span>"></span></span><br><span class="line"><span class="class"> <<span class="title">div</span> <span class="title">id</span>="<span class="title">uploadStatus</span>"></<span class="title">div</span>></span></span><br><span class="line"><span class="class"> <<span class="title">div</span> <span class="title">class</span>="<span class="title">progressBarcontainer</span>"></span></span><br><span class="line"><span class="class"> <<span class="title">div</span> <span class="title">class</span>="<span class="title">progressBarValue</span>"></<span class="title">div</span>></span></span><br><span class="line"><span class="class"> </<span class="title">div</span>></span></span><br><span class="line"><span class="class"> </<span class="title">div</span>></span></span><br><span class="line"><span class="class"></span></span><br><span class="line"><span class="class"> <<span class="title">div</span> <span class="title">class</span>="<span class="title">table</span>-<span class="title">reponsive</span> <span class="title">box</span>"></span></span><br><span class="line"><span class="class"> <<span class="title">table</span> <span class="title">id</span>="<span class="title">example</span>" <span class="title">class</span>="<span class="title">table</span> <span class="title">table</span>-<span class="title">striped</span> <span class="title">table</span>-<span class="title">bordered</span>"></span></span><br><span class="line"><span class="class"> <<span class="title">thead</span>></span></span><br><span class="line"><span class="class"> <<span class="title">tr</span>></span></span><br><span class="line"><span class="class"> <<span class="title">th</span>><span class="title">Id</span></<span class="title">th</span>></span></span><br><span class="line"><span class="class"> <<span class="title">th</span>><span class="title">Batch</span> <span class="title">Id</span></<span class="title">th</span>></span></span><br><span class="line"><span class="class"> <<span class="title">th</span>><span class="title">Pending</span> <span class="title">Jobs</span></<span class="title">th</span>></span></span><br><span class="line"><span class="class"> <<span class="title">th</span>><span class="title">Total</span> <span class="title">Jobs</span></<span class="title">th</span>></span></span><br><span class="line"><span class="class"> <<span class="title">th</span>><span class="title">Created</span> <span class="title">At</span></<span class="title">th</span>></span></span><br><span class="line"><span class="class"> <<span class="title">th</span>><span class="title">Finished</span> <span class="title">At</span></<span class="title">th</span>></span></span><br><span class="line"><span class="class"> </<span class="title">tr</span>></span></span><br><span class="line"><span class="class"> </<span class="title">thead</span>></span></span><br><span class="line"><span class="class"> <<span class="title">tbody</span>></span></span><br><span class="line"><span class="class"> @<span class="title">foreach</span>($<span class="title">allBatches</span> <span class="title">as</span> $<span class="title">key</span> => $<span class="title">data</span>)</span></span><br><span class="line"><span class="class"> <<span class="title">tr</span>></span></span><br><span class="line"><span class="class"> <<span class="title">td</span>></span>{{ <span class="variable">$key</span>+<span class="number">1</span> }}</td></span><br><span class="line"> <td>{{ <span class="variable">$data</span>->id }}</td></span><br><span class="line"> <td>{{ <span class="variable">$data</span>->pending_jobs }}</td></span><br><span class="line"> <td>{{ <span class="variable">$data</span>->total_jobs }}</td></span><br><span class="line"> <td>{{ <span class="title function_ invoke__">date</span>(<span class="string">'Y-m-d H:i'</span>,<span class="variable">$data</span>->created_at) }}</td></span><br><span class="line"> <td>{{ <span class="title function_ invoke__">date</span>(<span class="string">'Y-m-d H:i'</span>,<span class="variable">$data</span>->finished_at) }}</td></span><br><span class="line"> </tr></span><br><span class="line"> @<span class="keyword">endforeach</span></span><br><span class="line"> </tbody></span><br><span class="line"> </table></span><br><span class="line"> </div></span><br><span class="line"></span><br><span class="line"></span><br><span class="line"> </div></span><br><span class="line"></span><br><span class="line"> <script></span><br><span class="line"> $(document).<span class="title function_ invoke__">ready</span>(function () {</span><br><span class="line"> $(<span class="string">'#example'</span>).<span class="title function_ invoke__">DataTable</span>();</span><br><span class="line"> });</span><br><span class="line"></span><br><span class="line"> <span class="keyword">var</span> allBatches = {!! <span class="title function_ invoke__">json_encode</span>(<span class="variable">$allBatches</span>)!!};</span><br><span class="line"> console.<span class="title function_ invoke__">log</span>(allBatches);</span><br><span class="line"></span><br><span class="line"> <span class="function"><span class="keyword">function</span> <span class="title">uploadFile</span>(<span class="params"></span>) </span>{</span><br><span class="line"> <span class="keyword">var</span> formData = <span class="keyword">new</span> <span class="title class_">FormData</span>(document.<span class="title function_ invoke__">getElementById</span>(<span class="string">'uploadForm'</span>));</span><br><span class="line"></span><br><span class="line"> formData.<span class="title function_ invoke__">append</span>(<span class="string">'_token'</span>, <span class="string">'{{ csrf_token() }}'</span>);</span><br><span class="line"></span><br><span class="line"> $.<span class="title function_ invoke__">ajax</span>({</span><br><span class="line"> <span class="attr">type</span>: <span class="string">'POST'</span>,</span><br><span class="line"> <span class="attr">url</span>: <span class="string">'/uploadCsv'</span>,</span><br><span class="line"> <span class="attr">data</span>: formData,</span><br><span class="line"> <span class="attr">processData</span>: <span class="literal">false</span>,</span><br><span class="line"> <span class="attr">contentType</span>: <span class="literal">false</span>,</span><br><span class="line"> <span class="attr">success</span>: function (response) {</span><br><span class="line"> $(<span class="string">'#uploadStatus'</span>).<span class="title function_ invoke__">html</span>(<span class="string">'上傳中'</span>);</span><br><span class="line"> },</span><br><span class="line"> error: <span class="function"><span class="keyword">function</span> (<span class="params">error</span>) </span>{</span><br><span class="line"> $(<span class="string">'#uploadStatus'</span>).<span class="title function_ invoke__">html</span>(<span class="string">'Error uploading'</span>);</span><br><span class="line"> }</span><br><span class="line"> });</span><br><span class="line"> }</span><br><span class="line"> </script></span><br><span class="line"></body></span><br><span class="line"></span><br><span class="line"></html></span><br></pre></td></tr></table></figure><h2 id="controller"><a href="#controller" class="headerlink" title="controller"></a>controller</h2><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></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">uploadCsv</span>(<span class="params"></span>)</span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="keyword">if</span> (<span class="title function_ invoke__">request</span>()-><span class="title function_ invoke__">has</span>(<span class="string">'mycsv'</span>)) {</span><br><span class="line"> <span class="variable">$batch</span> = <span class="title class_">Bus</span>::<span class="title function_ invoke__">batch</span>([])-><span class="title function_ invoke__">then</span>(function (Batch <span class="variable">$batch</span>) {</span><br><span class="line"> <span class="variable">$progress</span> = <span class="title class_">Bus</span>::<span class="title function_ invoke__">findBatch</span>(<span class="variable">$batch</span>->id);</span><br><span class="line"></span><br><span class="line"> <span class="title function_ invoke__">event</span>(<span class="keyword">new</span> <span class="title class_">BatchProcessingProgressUpdated</span>(<span class="variable">$progress</span>-><span class="title function_ invoke__">toArray</span>()));</span><br><span class="line"> })-><span class="title function_ invoke__">dispatch</span>();</span><br><span class="line"></span><br><span class="line"> <span class="variable">$data</span> = <span class="title function_ invoke__">file</span>(<span class="title function_ invoke__">request</span>()->mycsv);</span><br><span class="line"> <span class="variable">$chunks</span> = <span class="title function_ invoke__">array_chunk</span>(<span class="variable">$data</span>, <span class="number">1000</span>);</span><br><span class="line"> <span class="variable">$header</span> = [];</span><br><span class="line"></span><br><span class="line"> <span class="keyword">foreach</span> (<span class="variable">$chunks</span> <span class="keyword">as</span> <span class="variable">$key</span> => <span class="variable">$chunk</span>) {</span><br><span class="line"> <span class="variable">$data</span> = <span class="title function_ invoke__">array_map</span>(<span class="string">'str_getcsv'</span>, <span class="variable">$chunk</span>);</span><br><span class="line"> <span class="keyword">if</span> (<span class="variable">$key</span> === <span class="number">0</span>) {</span><br><span class="line"> <span class="variable">$header</span> = <span class="title function_ invoke__">array_shift</span>(<span class="variable">$data</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="variable">$batch</span>-><span class="title function_ invoke__">add</span>(<span class="keyword">new</span> <span class="title class_">SalesCsvProcess</span>(<span class="variable">$data</span>, <span class="variable">$header</span>, <span class="variable">$batch</span>->id));</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line"> }</span><br></pre></td></tr></table></figure><h2 id="jobs"><a href="#jobs" class="headerlink" title="jobs"></a>jobs</h2><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><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></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 class_">App</span>\<span class="title class_">Jobs</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">use</span> <span class="title">Throwable</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">App</span>\<span class="title">Models</span>\<span class="title">Sales</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">Illuminate</span>\<span class="title">Bus</span>\<span class="title">Batchable</span>;</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">Queue</span>\<span class="title">SerializesModels</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">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">Support</span>\<span class="title">Facades</span>\<span class="title">Bus</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">App</span>\<span class="title">Events</span>\<span class="title">BatchProcessingProgressUpdated</span>;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">SalesCsvProcess</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">Batchable</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">public</span> <span class="variable">$data</span>;</span><br><span class="line"> <span class="keyword">public</span> <span class="variable">$header</span>;</span><br><span class="line"> <span class="keyword">public</span> <span class="variable">$batchId</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"><span class="variable">$data</span>, <span class="variable">$header</span>,<span class="variable">$batchId</span></span>)</span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="variable language_">$this</span>->data = <span class="variable">$data</span>;</span><br><span class="line"> <span class="variable language_">$this</span>->header = <span class="variable">$header</span>;</span><br><span class="line"> <span class="variable language_">$this</span>->batchId = <span class="variable">$batchId</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">foreach</span> (<span class="variable language_">$this</span>->data <span class="keyword">as</span> <span class="variable">$sale</span>) {</span><br><span class="line"> <span class="variable">$saleData</span> = <span class="title function_ invoke__">array_combine</span>(<span class="variable">$this</span>->header, <span class="variable">$sale</span>);</span><br><span class="line"> <span class="title class_">Sales</span>::<span class="title function_ invoke__">create</span>(<span class="variable">$saleData</span>);</span><br><span class="line"> }</span><br><span class="line"> <span class="variable">$progress</span>=<span class="title class_">Bus</span>::<span class="title function_ invoke__">findBatch</span>(<span class="variable">$this</span>->batchId);</span><br><span class="line"> <span class="title function_ invoke__">event</span>(<span class="keyword">new</span> <span class="title class_">BatchProcessingProgressUpdated</span>(<span class="variable">$progress</span>-><span class="title function_ invoke__">toArray</span>()));</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">failed</span>(<span class="params"><span class="built_in">Throwable</span> <span class="variable">$exception</span></span>)</span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="廣播失敗"><a href="#廣播失敗" class="headerlink" title="廣播失敗"></a>廣播失敗</h2><p><a href="https://stackoverflow.com/questions/74755444/laravel-run-event-inside-job-queue-async">laravel-run-event-inside-job-queue-async</a></p><h2 id="ref"><a href="#ref" class="headerlink" title="ref"></a>ref</h2><p><a href="https://laravelacademy.org/post/22252">Laravel 消息队列实战</a><br><a href="https://laravel.com/docs/10.x/queues">Queues</a><br><a href="https://shouts.dev/articles/laravel-upload-large-file-with-resumablejs-and-laravel-chunk-upload">laravel-upload-large-file-with-resumablejs-and-laravel-chunk-upload</a><br><a href="https://stackoverflow.com/questions/50576569/multiple-queues-in-laravel">multiple-queues-in-laravel</a><br><a href="https://martinjoo.dev/laravel-queues-and-workers-in-production">laravel-queues-and-workers-in-production</a><br><a href="https://www.honeybadger.io/blog/laravel-queues-deep-dive/">laravel-queues-deep-dive</a><br><a href="https://laravel.com/docs/10.x/queues#job-batching">queues#job-batching</a><br><a href="https://www.youtube.com/watch?v=aYpPswG1Op8&list=PLe30vg_FG4OTrILM1C9NvCgujTRKGsAwB&ab_channel=Bitfumes">Laravel Job Batching</a><br><a href="https://pusher.com/docs/channels/using_channels/presence-channels/#pusher-subscription-succeeded">pusher-subscription-succeeded</a><br><a href="https://codepen.io/FluidOfInsanity/pen/yaLRjd">Responsive Table</a></p>]]></content>
<tags>
<tag> Batch </tag>
<tag> Queue </tag>
</tags>
</entry>
<entry>
<title>(心得)不合邏輯的一周</title>
<link href="/(%E5%BF%83%E5%BE%97)%E4%B8%8D%E5%90%88%E9%82%8F%E8%BC%AF%E7%9A%84%E4%B8%80%E5%91%A8/"/>
<url>/(%E5%BF%83%E5%BE%97)%E4%B8%8D%E5%90%88%E9%82%8F%E8%BC%AF%E7%9A%84%E4%B8%80%E5%91%A8/</url>
<content type="html"><![CDATA[<h1 id="不合邏輯的一周"><a href="#不合邏輯的一周" class="headerlink" title="不合邏輯的一周"></a>不合邏輯的一周</h1><ul><li><p>申請租屋補助不需要房東同意,但如果房東沒有照建物謄本寫合約地址,補件需要房東簽名</p></li><li><p>隔年會寄稅率變動單給房東,制式租約清楚寫著因稅率變動產生費用由房客承擔</p></li><li><p>玩 pubg 被莫名其妙的爆炸擊殺,攻擊者顯示為空,伺服器的除錯訊息被印到客戶端,”empty strings table”。</p></li><li><p>隊友被飢餓者施加負面效果時,我幫忙解除到一半時跑走,變成只能半蹲爬全場,要修復 bug 只能找到同一個隊友重置。</p></li><li><p>被 C4 飢餓者擊倒後,隊友救我起來,但是負面效果音效沒有解除,整場都是被殭屍抓起來摔的聲音</p></li><li><p>地圖建模有 bug,住宅區 B 可以在天空趴趴走,而且殭屍抓不到</p></li><li><p>開發全聯報表發現兩筆資料異常,一家改名稱,另一家倒掉。</p></li><li><p>有幾家全聯門市庫存是負的</p></li><li><p>某 Web worker 庫,API 主要兩個方法,start 跟 stop,但是前人傳入完全不相關的 callback ,一行就能解決的功能變成十幾行,而且效率更差。</p></li><li><p>View 完全不切元件,用一大包的參數、嵌套邏輯來判斷,檔案命名與內容幾乎沒有關聯</p></li><li><p>買飲料時發現喝波霸的吸管變成細的,買飯時 50 號但店員卻拿 49 號的餐給我。</p></li><li><p>被煙味臭醒,樓下兩層有人手夾著菸伸出窗戶。</p></li><li><p>椅子整個髒掉,原以為沾到油漆,後發現是舊外套的膠,衛生紙越擦越大片,拿護手霜抹了 2 小時才清乾淨。</p></li><li><p>隔壁辦公室冷氣壞掉,水像瀑布一樣從天而降,伺服器都濕了,只能搬超大垃圾桶裝水。</p></li><li><p>大媽理直氣壯的逆向朝我衝來</p></li><li><p>還是大媽,在平均車速 50、60 的馬路上仰著頭,哼著歌闖紅燈 </p></li><li><p>8:30 找機車位時完全沒有位置</p></li><li><p>進電梯時被保全拿酒精亂噴,還說等噴完再搭就好</p></li></ul>]]></content>
<tags>
<tag> Diary </tag>
</tags>
</entry>
<entry>
<title>(技術)使用Swagger生成Laravel的API文件</title>
<link href="/(%E6%8A%80%E8%A1%93)%E4%BD%BF%E7%94%A8Swagger%E7%94%9F%E6%88%90Laravel%E7%9A%84API%E6%96%87%E4%BB%B6/"/>
<url>/(%E6%8A%80%E8%A1%93)%E4%BD%BF%E7%94%A8Swagger%E7%94%9F%E6%88%90Laravel%E7%9A%84API%E6%96%87%E4%BB%B6/</url>
<content type="html"><![CDATA[<p>Swagger 可以用來生成 Laravel API 文件,輕鬆地記錄和分享 API 的資訊,提供了清晰的介面,<br>讓開發人員更容易了解和使用您的 API。這有助於提高開發效率並確保 API 文檔的一致性</p><h2 id="安裝"><a href="#安裝" class="headerlink" title="安裝"></a>安裝</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">composer require "darkaonline/l5-swagger"</span><br></pre></td></tr></table></figure><h2 id="Controller"><a href="#Controller" class="headerlink" title="Controller"></a>Controller</h2><p>加入文件版本、標題、描述、授權</p><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">namespace</span> <span class="title class_">App</span>\<span class="title class_">Http</span>\<span class="title class_">Controllers</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">use</span> <span class="title">OpenApi</span>\<span class="title">Annotations</span> <span class="keyword">as</span> <span class="title">OA</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">Illuminate</span>\<span class="title">Foundation</span>\<span class="title">Auth</span>\<span class="title">Access</span>\<span class="title">AuthorizesRequests</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">DispatchesJobs</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">Illuminate</span>\<span class="title">Foundation</span>\<span class="title">Validation</span>\<span class="title">ValidatesRequests</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">Illuminate</span>\<span class="title">Routing</span>\<span class="title">Controller</span> <span class="keyword">as</span> <span class="title">BaseController</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@OA</span>\Info(</span></span><br><span class="line"><span class="comment"> * version="1.0.0",</span></span><br><span class="line"><span class="comment"> * title="Book-RESTful-API",</span></span><br><span class="line"><span class="comment"> * description="Login to obtain a JWT, with bearer authorization",</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@OA</span>\Contact(</span></span><br><span class="line"><span class="comment"> * email="demo<span class="doctag">@example</span>.com"</span></span><br><span class="line"><span class="comment"> * ),</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@OA</span>\License(</span></span><br><span class="line"><span class="comment"> * name="Apache 2.0",</span></span><br><span class="line"><span class="comment"> * url="http://www.apache.org/licenses/LICENSE-2.0.html"</span></span><br><span class="line"><span class="comment"> * )</span></span><br><span class="line"><span class="comment"> * )</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">Controller</span> <span class="keyword">extends</span> <span class="title">BaseController</span></span></span><br><span class="line"><span class="class"></span>{</span><br><span class="line"> <span class="keyword">use</span> <span class="title">AuthorizesRequests</span>, <span class="title">DispatchesJobs</span>, <span class="title">ValidatesRequests</span>;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="BookController"><a href="#BookController" class="headerlink" title="BookController"></a>BookController</h2><p>新增CRUD註解</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><span class="line">153</span><br><span class="line">154</span><br><span class="line">155</span><br><span class="line">156</span><br><span class="line">157</span><br><span class="line">158</span><br><span class="line">159</span><br><span class="line">160</span><br><span class="line">161</span><br><span class="line">162</span><br><span class="line">163</span><br><span class="line">164</span><br><span class="line">165</span><br><span class="line">166</span><br><span class="line">167</span><br><span class="line">168</span><br><span class="line">169</span><br><span class="line">170</span><br><span class="line">171</span><br><span class="line">172</span><br><span class="line">173</span><br><span class="line">174</span><br><span class="line">175</span><br><span class="line">176</span><br><span class="line">177</span><br><span class="line">178</span><br><span class="line">179</span><br><span class="line">180</span><br><span class="line">181</span><br><span class="line">182</span><br><span class="line">183</span><br><span class="line">184</span><br><span class="line">185</span><br><span class="line">186</span><br><span class="line">187</span><br><span class="line">188</span><br><span class="line">189</span><br><span class="line">190</span><br><span class="line">191</span><br><span class="line">192</span><br><span class="line">193</span><br><span class="line">194</span><br><span class="line">195</span><br><span class="line">196</span><br><span class="line">197</span><br><span class="line">198</span><br><span class="line">199</span><br><span class="line">200</span><br><span class="line">201</span><br><span class="line">202</span><br><span class="line">203</span><br><span class="line">204</span><br><span class="line">205</span><br><span class="line">206</span><br><span class="line">207</span><br><span class="line">208</span><br><span class="line">209</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="keyword">namespace</span> <span class="title class_">App</span>\<span class="title class_">Http</span>\<span class="title class_">Controllers</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">use</span> <span class="title">App</span>\<span class="title">Models</span>\<span class="title">Book</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">App</span>\<span class="title">Http</span>\<span class="title">Resources</span>\<span class="title">BookResource</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">Illuminate</span>\<span class="title">Http</span>\<span class="title">Request</span>;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">BookController</span> <span class="keyword">extends</span> <span class="title">Controller</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"> * Display a listing of the resource.</span></span><br><span class="line"><span class="comment"> *</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@return</span> \Illuminate\Http\Response</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__construct</span>(<span class="params"></span>)</span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="variable language_">$this</span>-><span class="title function_ invoke__">middleware</span>(<span class="string">'auth:api'</span>)-><span class="title function_ invoke__">except</span>([<span class="string">'index'</span>, <span class="string">'show'</span>]);</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@OA</span>\Get(</span></span><br><span class="line"><span class="comment"> * path="/api/books",</span></span><br><span class="line"><span class="comment"> * summary="取得最多25筆的書本與評分",</span></span><br><span class="line"><span class="comment"> * tags={"Book"},</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@OA</span>\Response(response="200", description="成功",<span class="doctag">@OA</span>\JsonContent()),</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">index</span>(<span class="params"></span>)</span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="title class_">BookResource</span>::<span class="title function_ invoke__">collection</span>(<span class="title class_">Book</span>::<span class="title function_ invoke__">with</span>(<span class="string">'ratings'</span>)-><span class="title function_ invoke__">paginate</span>(<span class="number">25</span>));</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@OA</span>\POST(</span></span><br><span class="line"><span class="comment"> * path="/api/books",</span></span><br><span class="line"><span class="comment"> * summary="創建書本",</span></span><br><span class="line"><span class="comment"> * tags={"Book"},</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@OA</span>\RequestBody(</span></span><br><span class="line"><span class="comment"> * required=true,</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@OA</span>\MediaType(</span></span><br><span class="line"><span class="comment"> * mediaType="application/json",</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@OA</span>\Schema(</span></span><br><span class="line"><span class="comment"> * required={"title", "description"},</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@OA</span>\Property(</span></span><br><span class="line"><span class="comment"> * property="title",</span></span><br><span class="line"><span class="comment"> * type="string",</span></span><br><span class="line"><span class="comment"> * description="標題"</span></span><br><span class="line"><span class="comment"> * ),</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@OA</span>\Property(</span></span><br><span class="line"><span class="comment"> * property="description",</span></span><br><span class="line"><span class="comment"> * type="string",</span></span><br><span class="line"><span class="comment"> * description="簡介"</span></span><br><span class="line"><span class="comment"> * )</span></span><br><span class="line"><span class="comment"> * )</span></span><br><span class="line"><span class="comment"> * )</span></span><br><span class="line"><span class="comment"> * ),</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@OA</span>\Response(</span></span><br><span class="line"><span class="comment"> * response=201,</span></span><br><span class="line"><span class="comment"> * description="創建成功"</span></span><br><span class="line"><span class="comment"> * ),</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@OA</span>\Response(</span></span><br><span class="line"><span class="comment"> * response=401,</span></span><br><span class="line"><span class="comment"> * description="未驗證"</span></span><br><span class="line"><span class="comment"> * ),</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@OA</span>\Response(</span></span><br><span class="line"><span class="comment"> * response=404,</span></span><br><span class="line"><span class="comment"> * description="資源不存在"</span></span><br><span class="line"><span class="comment"> * ),</span></span><br><span class="line"><span class="comment"> * security={{ "bearer_token": {} }}</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><br><span class="line"> <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">store</span>(<span class="params">Request <span class="variable">$request</span></span>)</span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="variable">$book</span> = <span class="title class_">Book</span>::<span class="title function_ invoke__">create</span>([</span><br><span class="line"> <span class="string">'user_id'</span> => <span class="variable">$request</span>-><span class="title function_ invoke__">user</span>()->id,</span><br><span class="line"> <span class="string">'title'</span> => <span class="variable">$request</span>->title,</span><br><span class="line"> <span class="string">'description'</span> => <span class="variable">$request</span>->description,</span><br><span class="line"> ]);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">BookResource</span>(<span class="variable">$book</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@OA</span>\Get(</span></span><br><span class="line"><span class="comment"> * path="/api/books/{bookId}",</span></span><br><span class="line"><span class="comment"> * summary="取得書本",</span></span><br><span class="line"><span class="comment"> * tags={"Book"},</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@OA</span>\Parameter(</span></span><br><span class="line"><span class="comment"> * name="bookId",</span></span><br><span class="line"><span class="comment"> * description="Book id",</span></span><br><span class="line"><span class="comment"> * required=true,</span></span><br><span class="line"><span class="comment"> * in="path",</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@OA</span>\Schema(</span></span><br><span class="line"><span class="comment"> * type="integer"</span></span><br><span class="line"><span class="comment"> * )</span></span><br><span class="line"><span class="comment"> * ),</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@OA</span>\Response(</span></span><br><span class="line"><span class="comment"> * response=200,</span></span><br><span class="line"><span class="comment"> * description="成功"</span></span><br><span class="line"><span class="comment"> * ),</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@OA</span>\Response(</span></span><br><span class="line"><span class="comment"> * response=404,</span></span><br><span class="line"><span class="comment"> * description="資源不存在"</span></span><br><span class="line"><span class="comment"> * )</span></span><br><span class="line"><span class="comment"> * )</span></span><br><span class="line"><span class="comment"> */</span></span><br><span class="line"> <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">show</span>(<span class="params">Book <span class="variable">$book</span></span>)</span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">BookResource</span>(<span class="variable">$book</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@OA</span>\Patch(</span></span><br><span class="line"><span class="comment"> * path="/api/books/{bookId}",</span></span><br><span class="line"><span class="comment"> * summary="更新書本",</span></span><br><span class="line"><span class="comment"> * tags={"Book"},</span></span><br><span class="line"><span class="comment"> * description="更新書本",</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@OA</span>\Parameter(</span></span><br><span class="line"><span class="comment"> * name="bookId",</span></span><br><span class="line"><span class="comment"> * description="Book id",</span></span><br><span class="line"><span class="comment"> * required=true,</span></span><br><span class="line"><span class="comment"> * in="path",</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@OA</span>\Schema(</span></span><br><span class="line"><span class="comment"> * type="integer"</span></span><br><span class="line"><span class="comment"> * )</span></span><br><span class="line"><span class="comment"> * ),</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@OA</span>\RequestBody(</span></span><br><span class="line"><span class="comment"> * description="更新書本的內容",</span></span><br><span class="line"><span class="comment"> * required=true,</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@OA</span>\MediaType(</span></span><br><span class="line"><span class="comment"> * mediaType="application/json",</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@OA</span>\Schema(</span></span><br><span class="line"><span class="comment"> * type="object",</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@OA</span>\Property(</span></span><br><span class="line"><span class="comment"> * property="title",</span></span><br><span class="line"><span class="comment"> * description="標題",</span></span><br><span class="line"><span class="comment"> * type="string"</span></span><br><span class="line"><span class="comment"> * ),</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@OA</span>\Property(</span></span><br><span class="line"><span class="comment"> * property="description",</span></span><br><span class="line"><span class="comment"> * description="內容",</span></span><br><span class="line"><span class="comment"> * type="string"</span></span><br><span class="line"><span class="comment"> * ),</span></span><br><span class="line"><span class="comment"> * )</span></span><br><span class="line"><span class="comment"> * )</span></span><br><span class="line"><span class="comment"> * ),</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@OA</span>\Response(</span></span><br><span class="line"><span class="comment"> * response=200,</span></span><br><span class="line"><span class="comment"> * description="成功",</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@OA</span>\JsonContent()</span></span><br><span class="line"><span class="comment"> * ),</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@OA</span>\Response(</span></span><br><span class="line"><span class="comment"> * response=401,</span></span><br><span class="line"><span class="comment"> * description="未驗證",</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@OA</span>\JsonContent()</span></span><br><span class="line"><span class="comment"> * ),</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@OA</span>\Response(</span></span><br><span class="line"><span class="comment"> * response=404,</span></span><br><span class="line"><span class="comment"> * description="資源不存在",</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@OA</span>\JsonContent()</span></span><br><span class="line"><span class="comment"> * ),</span></span><br><span class="line"><span class="comment"> * security={{ "bearer_token": {} }}</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">update</span>(<span class="params">Request <span class="variable">$request</span>, Book <span class="variable">$book</span></span>)</span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="keyword">if</span> (<span class="variable">$request</span>-><span class="title function_ invoke__">user</span>()->id !== <span class="variable">$book</span>->user_id) {</span><br><span class="line"> <span class="keyword">return</span> <span class="title function_ invoke__">response</span>()-><span class="title function_ invoke__">json</span>([<span class="string">'error'</span> => <span class="string">'You can only edit your own books.'</span>], <span class="number">403</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="variable">$book</span>-><span class="title function_ invoke__">update</span>(<span class="variable">$request</span>-><span class="title function_ invoke__">only</span>([<span class="string">'title'</span>, <span class="string">'description'</span>]));</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">BookResource</span>(<span class="variable">$book</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">/**</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@OA</span>\Delete(</span></span><br><span class="line"><span class="comment"> * path="/api/books/{bookId}",</span></span><br><span class="line"><span class="comment"> * summary="刪除書本",</span></span><br><span class="line"><span class="comment"> * tags={"Book"},</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@OA</span>\Parameter(</span></span><br><span class="line"><span class="comment"> * name="bookId",</span></span><br><span class="line"><span class="comment"> * description="Book id",</span></span><br><span class="line"><span class="comment"> * required=true,</span></span><br><span class="line"><span class="comment"> * in="path",</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@OA</span>\Schema(</span></span><br><span class="line"><span class="comment"> * type="integer"</span></span><br><span class="line"><span class="comment"> * )</span></span><br><span class="line"><span class="comment"> * ),</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@OA</span>\Response(</span></span><br><span class="line"><span class="comment"> * response=204,</span></span><br><span class="line"><span class="comment"> * description="刪除成功",</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@OA</span>\JsonContent()</span></span><br><span class="line"><span class="comment"> * ),</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@OA</span>\Response(</span></span><br><span class="line"><span class="comment"> * response=404,</span></span><br><span class="line"><span class="comment"> * description="資源不存在",</span></span><br><span class="line"><span class="comment"> * <span class="doctag">@OA</span>\JsonContent()</span></span><br><span class="line"><span class="comment"> * ),</span></span><br><span class="line"><span class="comment"> * security={{ "bearer_token": {} }}</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">destroy</span>(<span class="params">Book <span class="variable">$book</span></span>)</span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="variable">$book</span>-><span class="title function_ invoke__">delete</span>();</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> <span class="title function_ invoke__">response</span>()-><span class="title function_ invoke__">json</span>(<span class="literal">null</span>, <span class="number">204</span>);</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="生成文件"><a href="#生成文件" class="headerlink" title="生成文件"></a>生成文件</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">php artisan l5-swagger:generate</span><br></pre></td></tr></table></figure><p>訪問以下路由即可看到文件</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line"><server>/api/documention</span><br></pre></td></tr></table></figure><h2 id="demo"><a href="#demo" class="headerlink" title="demo"></a>demo</h2><p><a href="https://github.com/chienniman/REST-API">範例在這</a></p><h2 id="Ref"><a href="#Ref" class="headerlink" title="Ref"></a>Ref</h2><p><a href="https://github.com/DarkaOnLine/L5-Swagger">L5-Swagger</a><br><a href="https://petstore.swagger.io/#/pet/uploadFile">swagger-demo</a><br><a href="https://stackoverflow.com/questions/50614594/use-jwt-bearer-token-in-swagger-laravel">use JWT Bearer token in swagger Laravel</a></p>]]></content>
<tags>
<tag> Swagger </tag>
</tags>
</entry>
<entry>
<title>(技術)實作Laravel-RESTful-API與JWT驗證</title>
<link href="/(%E6%8A%80%E8%A1%93)%E5%AF%A6%E4%BD%9CLaravel-RESTful-API%E8%88%87JWT%E9%A9%97%E8%AD%89/"/>
<url>/(%E6%8A%80%E8%A1%93)%E5%AF%A6%E4%BD%9CLaravel-RESTful-API%E8%88%87JWT%E9%A9%97%E8%AD%89/</url>
<content type="html"><![CDATA[<h2 id="RESTful-API"><a href="#RESTful-API" class="headerlink" title="RESTful API"></a>RESTful API</h2><blockquote><p>Representational State Transfer (REST) 是一種軟體架構,它對 API 的運作方式施加了條件。REST 最初是作為管理複雜網路 (如網際網路) 上的通訊指導方針而建立。您可以使用以 REST 為基礎的架構,來支援大規模的高效能和可靠的通訊。您可以輕鬆實作和修改,為任何 API 系統提供可視性和跨平台可移植性。</p></blockquote><h2 id="風格"><a href="#風格" class="headerlink" title="風格"></a>風格</h2><ul><li>統一介面</li><li>無狀態</li><li>分層系統</li><li>可快取性</li><li>隨需編碼</li></ul><h2 id="方法"><a href="#方法" class="headerlink" title="方法"></a>方法</h2><ul><li>URL</li><li>GET</li><li>POST</li><li>PUT</li><li>DELETE</li></ul><h2 id="幂等"><a href="#幂等" class="headerlink" title="幂等"></a>幂等</h2><p>同樣的請求被執行一次與連續執行多次,在伺服器的效果是一樣的,GET、HEAD、PUT、DELETE 是冪等的,POST 方法不是</p><h2 id="JWT"><a href="#JWT" class="headerlink" title="JWT"></a>JWT</h2><p>JSON Web Token,在伺服器間將訊息作為 JSON 物件傳輸,由 header、payload、signature 組成,<br>常搭配 RESTful API 作為身分驗證。</p><h2 id="實作"><a href="#實作" class="headerlink" title="實作"></a>實作</h2><h3 id="安裝"><a href="#安裝" class="headerlink" title="安裝"></a>安裝</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">composer require tymon/jwt-auth</span><br></pre></td></tr></table></figure><h3 id="生成密鑰"><a href="#生成密鑰" class="headerlink" title="生成密鑰"></a>生成密鑰</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">php artisan jwt:secret</span><br></pre></td></tr></table></figure><h3 id="創建-BookResource、BookController"><a href="#創建-BookResource、BookController" class="headerlink" title="創建 BookResource、BookController"></a>創建 BookResource、BookController</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">php artisan make:resource BookResource</span><br></pre></td></tr></table></figure><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">php artisan make:controller BookController --api</span><br></pre></td></tr></table></figure><h3 id="加入-Middleware"><a href="#加入-Middleware" class="headerlink" title="加入 Middleware"></a>加入 Middleware</h3><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</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">__construct</span>(<span class="params"></span>)</span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="variable language_">$this</span>-><span class="title function_ invoke__">middleware</span>(<span class="string">'auth:api'</span>)-><span class="title function_ invoke__">except</span>([<span class="string">'index'</span>, <span class="string">'show'</span>]);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="Postmon-測試"><a href="#Postmon-測試" class="headerlink" title="Postmon 測試"></a>Postmon 測試</h2><p>登入取得 access token,預設有效時間一小時</p><p><img src="/images/restfulApi/login.webp"></p><p>加入 API Header,用來驗證使用者身分</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">Authorization : Bearer <access token></span><br></pre></td></tr></table></figure><p>成功新增資源</p><p><img src="/images/restfulApi/post.webp"></p><h2 id="demo"><a href="#demo" class="headerlink" title="demo"></a>demo</h2><p><a href="https://github.com/chienniman/REST-API">範例在這</a></p><h2 id="Ref"><a href="#Ref" class="headerlink" title="Ref"></a>Ref</h2><p><a href="https://aws.amazon.com/tw/what-is/restful-api/">什麼是 RESTful API?</a><br><a href="https://developer.mozilla.org/zh-CN/docs/Glossary/Idempotent">冪等</a><br><a href="https://pusher.com/blog/build-rest-api-laravel-api-resources/#securing-the-api-endpoints">Build a REST API with Laravel API resources</a></p>]]></content>
<tags>
<tag> Laravel </tag>
<tag> RESTful API </tag>
<tag> JWT </tag>
</tags>
</entry>
<entry>
<title>(心得)Linda-Rising敏捷思維的力量</title>
<link href="/(%E5%BF%83%E5%BE%97)Linda-Rising%E6%95%8F%E6%8D%B7%E6%80%9D%E7%B6%AD%E7%9A%84%E5%8A%9B%E9%87%8F/"/>
<url>/(%E5%BF%83%E5%BE%97)Linda-Rising%E6%95%8F%E6%8D%B7%E6%80%9D%E7%B6%AD%E7%9A%84%E5%8A%9B%E9%87%8F/</url>
<content type="html"><![CDATA[<h2 id="敏捷-vs-固定"><a href="#敏捷-vs-固定" class="headerlink" title="敏捷 vs 固定"></a>敏捷 vs 固定</h2><p>實驗中,敏捷思維的學生更願意接受更難的考試、不確定性高的挑戰,固定思維的學生則傾向於證明自己,選擇簡單的考試,力求完美,總結來說,前者願意不斷接受新的挑戰、機會,讓自己成長,後者傾向滿足於過去的成就,力求穩定,實驗的結尾,具備敏捷思維的學生得益於過去的成長,因此有更佳的表現</p><table><thead><tr><th></th><th>固定</th><th>敏捷</th></tr></thead><tbody><tr><td>能力</td><td>靜態</td><td>動態</td></tr><tr><td>目的</td><td>看起來好</td><td>學習</td></tr><tr><td>挑戰</td><td>避免</td><td>接受</td></tr><tr><td>失敗</td><td>命中注定</td><td>獲得資訊</td></tr><tr><td>努力</td><td>因為沒天分</td><td>專精</td></tr><tr><td>態度</td><td>無助</td><td>有彈性</td></tr></tbody></table><h2 id="Enron-的固定思維"><a href="#Enron-的固定思維" class="headerlink" title="Enron 的固定思維"></a>Enron 的固定思維</h2><p>末位淘汰制下,人們破壞別人的專案,使別人看起來很差,讓自己看起來很好,提升自己的排名<br>,降低被淘汰的風險,但這樣有毒的政策,使公司很快倒閉</p><h2 id="西南航空的敏捷思維"><a href="#西南航空的敏捷思維" class="headerlink" title="西南航空的敏捷思維"></a>西南航空的敏捷思維</h2><p>西南態度,讓公司成長、學習、變得更好,也鼓勵員工有實驗精神</p><h2 id="總結"><a href="#總結" class="headerlink" title="總結"></a>總結</h2><p>生而敏捷,不斷地跌倒犯錯成長,成長環境不同,有人在一聲聲稱讚中迷失自我,變得保守,有人在過程中獲得成長,變得敏捷,不斷進步,筆者身邊的<a href="https://zh.wikipedia.org/zh-tw/%E5%81%9A%E9%A2%98%E5%AE%B6">小鎮做題家</a>,求學時期即非常優秀,成績名列前茅,擅長社交,通常原生家庭對他們有極高的要求,但人無完人,再優秀也會碰到難關,課業、感情、社交,但自尊心使他們不願意向外界求助,很遺憾地,有人就這樣被困在歷史的夾縫,努力保持過去的榮耀,卻駐足不前,敏捷思維能夠解決這樣的困境,卻不是每個人都可以接受。</p>]]></content>
<tags>
<tag> Agile </tag>
</tags>
</entry>
<entry>
<title>(技術)透過Github-Action實現CICD-Pipeline</title>
<link href="/(%E6%8A%80%E8%A1%93)%E9%80%8F%E9%81%8EGithub-Action%E5%AF%A6%E7%8F%BECICD-Pipeline/"/>
<url>/(%E6%8A%80%E8%A1%93)%E9%80%8F%E9%81%8EGithub-Action%E5%AF%A6%E7%8F%BECICD-Pipeline/</url>
<content type="html"><![CDATA[<p><img src="/images/cicdPipeline/pipeline.webp"></p><h2 id="How-to-use"><a href="#How-to-use" class="headerlink" title="How to use"></a>How to use</h2><ul><li><p>git clone</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">https://github.com/chienniman/mantine-vite-template.git</span><br></pre></td></tr></table></figure></li><li><p>download the ZIP<br><img src="/images/cicdPipeline/clone.webp"></p></li><li><p>fork the project<br><img src="/images/cicdPipeline/fork.webp"></p></li></ul><h2 id="Create-a-new-repository"><a href="#Create-a-new-repository" class="headerlink" title="Create a new repository"></a>Create a new repository</h2><div class="note danger no-icon flat"><p>Selected Public to host free gh-page app</p></div><p><img src="/images/cicdPipeline/public-private.webp"></p><h2 id="Create-CI-x2F-CD-workflow"><a href="#Create-CI-x2F-CD-workflow" class="headerlink" title="Create CI/CD workflow"></a>Create CI/CD workflow</h2><p><code>.github /workflows/main.yml</code></p><figure class="highlight yml"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br><span class="line">56</span><br><span class="line">57</span><br><span class="line">58</span><br><span class="line">59</span><br><span class="line">60</span><br><span class="line">61</span><br></pre></td><td class="code"><pre><span class="line"><span class="attr">name:</span> <span class="string">Deploy</span> <span class="string">to</span> <span class="string">gh-page</span></span><br><span class="line"><span class="attr">permissions:</span></span><br><span class="line"> <span class="attr">contents:</span> <span class="string">write</span></span><br><span class="line"><span class="attr">on:</span></span><br><span class="line"> <span class="attr">push:</span></span><br><span class="line"> <span class="attr">branches:</span> <span class="string">master</span></span><br><span class="line"></span><br><span class="line"><span class="attr">jobs:</span></span><br><span class="line"> <span class="attr">build:</span></span><br><span class="line"> <span class="attr">name:</span> <span class="string">Build</span></span><br><span class="line"> <span class="attr">runs-on:</span> <span class="string">ubuntu-latest</span></span><br><span class="line"></span><br><span class="line"> <span class="attr">steps:</span></span><br><span class="line"> <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">Checkout</span> <span class="string">repo</span></span><br><span class="line"> <span class="attr">uses:</span> <span class="string">actions/checkout@v3</span></span><br><span class="line"></span><br><span class="line"> <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">Setup</span> <span class="string">Node</span></span><br><span class="line"> <span class="attr">uses:</span> <span class="string">actions/setup-node@v2</span></span><br><span class="line"></span><br><span class="line"> <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">CI</span></span><br><span class="line"> <span class="attr">run:</span> <span class="string">npm</span> <span class="string">ci</span></span><br><span class="line"></span><br><span class="line"> <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">Typecheck</span></span><br><span class="line"> <span class="attr">run:</span> <span class="string">npm</span> <span class="string">run</span> <span class="string">typecheck</span></span><br><span class="line"></span><br><span class="line"> <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">Prettier</span></span><br><span class="line"> <span class="attr">run:</span> <span class="string">npm</span> <span class="string">run</span> <span class="string">prettier</span></span><br><span class="line"> </span><br><span class="line"> <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">Lint</span></span><br><span class="line"> <span class="attr">run:</span> <span class="string">npm</span> <span class="string">run</span> <span class="string">lint</span></span><br><span class="line"></span><br><span class="line"> <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">Jest</span></span><br><span class="line"> <span class="attr">run:</span> <span class="string">npm</span> <span class="string">run</span> <span class="string">jest</span></span><br><span class="line"></span><br><span class="line"> <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">Run</span> <span class="string">build</span></span><br><span class="line"> <span class="attr">run:</span> <span class="string">npm</span> <span class="string">run</span> <span class="string">build</span></span><br><span class="line"> </span><br><span class="line"> <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">Upload</span> <span class="string">production-ready</span> <span class="string">build</span> <span class="string">files</span></span><br><span class="line"> <span class="attr">uses:</span> <span class="string">actions/upload-artifact@v2</span></span><br><span class="line"> <span class="attr">with:</span></span><br><span class="line"> <span class="attr">name:</span> <span class="string">production-files</span></span><br><span class="line"> <span class="attr">path:</span> <span class="string">./dist</span></span><br><span class="line"></span><br><span class="line"> <span class="attr">deploy:</span></span><br><span class="line"> <span class="attr">name:</span> <span class="string">Deploy</span></span><br><span class="line"> <span class="attr">needs:</span> <span class="string">build</span></span><br><span class="line"> <span class="attr">runs-on:</span> <span class="string">ubuntu-latest</span></span><br><span class="line"> <span class="attr">if:</span> <span class="string">github.ref</span> <span class="string">==</span> <span class="string">'refs/heads/master'</span></span><br><span class="line"></span><br><span class="line"> <span class="attr">steps:</span></span><br><span class="line"> <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">Download</span> <span class="string">artifact</span></span><br><span class="line"> <span class="attr">uses:</span> <span class="string">actions/download-artifact@v2</span></span><br><span class="line"> <span class="attr">with:</span></span><br><span class="line"> <span class="attr">name:</span> <span class="string">production-files</span></span><br><span class="line"> <span class="attr">path:</span> <span class="string">./dist</span></span><br><span class="line"></span><br><span class="line"> <span class="bullet">-</span> <span class="attr">name:</span> <span class="string">Deploy</span> <span class="string">to</span> <span class="string">gh-pages</span></span><br><span class="line"> <span class="attr">uses:</span> <span class="string">peaceiris/actions-gh-pages@v3</span></span><br><span class="line"> <span class="attr">with:</span></span><br><span class="line"> <span class="attr">github_token:</span> <span class="string">${{</span> <span class="string">secrets.GITHUB_TOKEN</span> <span class="string">}}</span></span><br><span class="line"> <span class="attr">publish_dir:</span> <span class="string">./dist</span> </span><br></pre></td></tr></table></figure><h2 id="Local-development-and-usage"><a href="#Local-development-and-usage" class="headerlink" title="Local development and usage"></a>Local development and usage</h2><h3 id="install-yarn"><a href="#install-yarn" class="headerlink" title="install yarn"></a>install yarn</h3><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">yarn --version</span><br></pre></td></tr></table></figure><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">npm install --global yarn</span><br></pre></td></tr></table></figure><h3 id="install-node-modules"><a href="#install-node-modules" class="headerlink" title="install node_modules"></a>install node_modules</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">yarn install</span><br></pre></td></tr></table></figure><h3 id="add-homepage-to-package-json"><a href="#add-homepage-to-package-json" class="headerlink" title="add homepage to package.json"></a>add homepage to package.json</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">"homepage": "https://<githubusername>.github.io/<app>"</span><br></pre></td></tr></table></figure><h3 id="Start-the-vite-server-and-develop-new-features"><a href="#Start-the-vite-server-and-develop-new-features" class="headerlink" title="Start the vite server and develop new features."></a>Start the vite server and develop new features.</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm run dev</span><br></pre></td></tr></table></figure><h3 id="test"><a href="#test" class="headerlink" title="test"></a>test</h3><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm run test</span><br></pre></td></tr></table></figure><h2 id="Commit-to-master-branch"><a href="#Commit-to-master-branch" class="headerlink" title="Commit to master branch"></a>Commit to master branch</h2><figure class="highlight plaintext"><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">git init</span><br><span class="line">git add .</span><br><span class="line">git commit -m "xxx"</span><br></pre></td></tr></table></figure><h2 id="Enable-GitHub-Pages"><a href="#Enable-GitHub-Pages" class="headerlink" title="Enable GitHub Pages"></a>Enable GitHub Pages</h2><div class="note danger no-icon flat"><p>The source must be set to gh-pages instead of master/main, otherwise it will not be displayed.</p></div><p><img src="/images/cicdPipeline/github-page.webp"></p><h2 id="Done"><a href="#Done" class="headerlink" title="Done"></a>Done</h2><p><img src="/images/cicdPipeline/done.webp"></p><h2 id="Discussion"><a href="#Discussion" class="headerlink" title="Discussion"></a>Discussion</h2><h3 id="Assets-links"><a href="#Assets-links" class="headerlink" title="Assets links"></a>Assets links</h3><p>To fix the issue of resource <code>loading 404 errors</code> and modify the default path, you can achieve it through the configuration in vite.config.ts.</p><p><code>vite.config.ts</code></p><figure class="highlight typescript"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> { defineConfig } <span class="keyword">from</span> <span class="string">'vite'</span>;</span><br><span class="line"><span class="keyword">import</span> react <span class="keyword">from</span> <span class="string">'@vitejs/plugin-react'</span>;</span><br><span class="line"></span><br><span class="line"><span class="comment">// https://vitejs.dev/config/</span></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">default</span> <span class="title function_">defineConfig</span>({</span><br><span class="line"> <span class="attr">plugins</span>: [<span class="title function_">react</span>()],</span><br><span class="line"> <span class="attr">base</span>: <span class="string">'/mantine-vite-template/'</span>,</span><br><span class="line"> <span class="attr">build</span>: {</span><br><span class="line"> <span class="attr">assetsDir</span>: <span class="string">'assets'</span>,</span><br><span class="line"> },</span><br><span class="line">});</span><br><span class="line"></span><br></pre></td></tr></table></figure><h3 id="Pages-build-and-deployment"><a href="#Pages-build-and-deployment" class="headerlink" title="Pages build and deployment"></a>Pages build and deployment</h3><blockquote><p>I think there’s a lot of scope for confusion for users of this action, when pages build and deployment will also be running on every push and pushing pages assets.</p></blockquote><p>I think it’s impossible to really say right now what that looks like until GitHub announces what these actions intend to do in the long run. As the post suggests this is a necessary step that occurs after the push gets made, this was already occurring behind the scenes it just wasn’t made visible.</p><h2 id="Ref"><a href="#Ref" class="headerlink" title="Ref"></a>Ref</h2><p><a href="https://classic.yarnpkg.com/lang/en/docs/install/#windows-stable">yarn</a><br><a href="https://github.com/orgs/community/discussions/25682">What is actions/checkout@v2 in Github action</a><br><a href="https://github.com/marketplace/actions/deploy-to-github-pages">deploy-to-github-pages</a><br><a href="https://github.com/sitek94/vite-deploy-demo">vite-deploy-demo</a><br><a href="https://github.com/antonputra/tutorials/tree/main/lessons/100">antonputra/tutorials</a><br><a href="https://github.com/JamesIves/github-pages-deploy-action/discussions/1073">github-pages-deploy-action</a></p>]]></content>
<categories>
<category> CI/CD </category>
</categories>
<tags>
<tag> CI/CD </tag>
<tag> Github Action </tag>
<tag> CICD Pipeline </tag>
</tags>
</entry>
<entry>
<title>(遊戲)不靠T轉跟完美消除達到TETR的S牌位</title>
<link href="/(%E9%81%8A%E6%88%B2)%E4%B8%8D%E9%9D%A0T%E8%BD%89%E8%B7%9F%E5%AE%8C%E7%BE%8E%E6%B6%88%E9%99%A4%E9%81%94%E5%88%B0TETR%E7%9A%84S%E7%89%8C%E4%BD%8D/"/>
<url>/(%E9%81%8A%E6%88%B2)%E4%B8%8D%E9%9D%A0T%E8%BD%89%E8%B7%9F%E5%AE%8C%E7%BE%8E%E6%B6%88%E9%99%A4%E9%81%94%E5%88%B0TETR%E7%9A%84S%E7%89%8C%E4%BD%8D/</url>
<content type="html"><![CDATA[<p><img src="/images/tetris/s-rank.jpg"></p><div class="note info no-icon flat"><p>2022 年因為伺服器延遲問題從特戰英豪退坑後,每周零零散散的玩幾場 CSGO 競技,不得不說在基建的部分,V 社做得比拳頭好很多,像特戰英豪這種高強度競技射擊,PING 飆到 200、300 基本上走出去就被爆頭了(白金~鑽石),無遊戲體驗可言,心灰意冷轉戰 2021 年時發現的俄羅斯方塊,沒有搞氣氛的隊友,沒有馬鈴薯伺服器,勝負大機率取決於個人技巧。</p></div><p>介紹兩個特殊技巧,<a href="https://tetris.fandom.com/wiki/T-Spin">T 轉(T-Spin)</a>跟<a href="https://harddrop.com/wiki/Perfect_clear">完美消除(Perfect Clear)</a></p><h2 id="完美消除-Perfect-Clear"><a href="#完美消除-Perfect-Clear" class="headerlink" title="完美消除(Perfect Clear)"></a>完美消除(Perfect Clear)</h2><p>透過特殊擺法消除場上所有方塊,不包含垃圾<br><img src="/images/tetris/all-clear-setup.jpg"></p><p>開場造成 10 行以上的攻擊(取決於 B2B combo),非常致命<br><img src="/images/tetris/all-clear.jpg"></p><h2 id="T-Spin"><a href="#T-Spin" class="headerlink" title="T-Spin"></a>T-Spin</h2><p>顧名思義,透過旋轉 T 方塊的特殊消行技巧,每個遊戲有不同計算方式,以下是 4 個 T-spin Triple 加上一個 mini single 的示範<br><img src="/images/tetris/start-3T-spin.png"></p><h2 id="牌位"><a href="#牌位" class="headerlink" title="牌位"></a>牌位</h2><h3 id="D-C"><a href="#D-C" class="headerlink" title="D~C+"></a>D~C+</h3><p>先贏 3 場,入門級,速度緩慢,失誤多,方塊擺放不整齊就開始消行,注重自身的防守。</p><h3 id="B-B"><a href="#B-B" class="headerlink" title="B-~B+"></a>B-~B+</h3><p>先贏 3 場,頻繁使用連招,小失誤,比拚消行速度與時機點把握,推薦空 2、3 行,重點在懲罰對手的失誤。</p><h3 id="A-A"><a href="#A-A" class="headerlink" title="A-~A+"></a>A-~A+</h3><p>先贏 3 場,實力落差大,不穩定的玩家在 B+~A-震盪,穩定型會在 A+卡一陣子,專注於<a href="https://tetris.wiki/TETR.IO">B2B Combo</a>,雙方基本不失誤,差別於爆發總量,受到手感跟方塊擺放邏輯影響,不能有明顯弱點,方塊高低起伏過大、速度偏慢、COMBO 少、小失誤,容易被一波帶走。</p><h3 id="S-SS"><a href="#S-SS" class="headerlink" title="S-~SS"></a>S-~SS</h3><p>先贏 5場,T 轉跟完美消除是基本盤,手感、運氣下滑或 B2B Combo 中斷,被打亂節奏,高處被卡死是家常便飯。</p><h3 id="爆發型"><a href="#爆發型" class="headerlink" title="爆發型"></a>爆發型</h3><p>開局連續 T 轉、完美消除使對手來不及疊高 Combo 就被 KO</p><h4 id="優點"><a href="#優點" class="headerlink" title="優點"></a>優點</h4><ul><li>前期優勢</li><li>方塊高度低</li></ul><h4 id="缺點"><a href="#缺點" class="headerlink" title="缺點"></a>缺點</h4><ul><li>手感、運氣差容易被懲罰</li><li>過度依賴於特定方塊</li><li>容錯率低</li></ul><h3 id="穩定型"><a href="#穩定型" class="headerlink" title="穩定型"></a>穩定型</h3><p>持續疊高,留 1~3 空行</p><h4 id="優點-1"><a href="#優點-1" class="headerlink" title="優點"></a>優點</h4><ul><li>一行能保持 B2B Combo,二到三行能在後期大量轟炸</li><li>容錯高,堆疊快</li><li>可攻可守</li></ul><h4 id="缺點-1"><a href="#缺點-1" class="headerlink" title="缺點"></a>缺點</h4><ul><li>爆發總行少</li><li>開局劣勢</li></ul><div class="note warning no-icon flat"><p>S 級有不少手速快到令人咋舌的玩家,但還是能透過合理分析,選用策略來增加勝率,在開場時觀察,如果發現對手擺放固定套路,準備完美消除或是連續 T 轉,進行<strong>Quad(4 消行)循環</strong>,保持 B2B Combo(不參雜單、雙、三消行),能帶來<strong>額外的攻擊行數</strong>,對T轉苦手很有幫助。<br>對手將方塊疊高,留 1~3 行,短時間大量轟炸,如果自身手感下滑,建議將地基打掉扛住這波爆發,順著對手的步調走硬碰硬,因為對手的輸出總量等於自身累積+消除垃圾行,沒有足夠的行數抵銷,容易陷入劣勢。</p></div><h2 id="總結"><a href="#總結" class="headerlink" title="總結"></a>總結</h2><p>Tetr 鼓勵使用<strong>不中斷</strong>的 T 轉或是 Quad,<strong>不崇尚單消行防守</strong>,這點可以從<a href="https://tetris.wiki/TETR.IO">B2B Combo</a>累計表看出,曾經風靡一時的臉書遊戲Tetris Battle,會在KO數相同時比較總消行數,但Tetr只考慮誰先取得足夠勝場,前期消行慢,仔細思考布置也是一種遊戲風格,帶來更大的自由性,不會因前期劣勢滾雪球,導致不可挽回的敗北。</p>]]></content>
<categories>
<category> Diary </category>
</categories>
</entry>
<entry>
<title>(心得)不幸買到七進七出子龍機是什麼體驗</title>
<link href="/(%E5%BF%83%E5%BE%97)%E4%B8%8D%E5%B9%B8%E8%B2%B7%E5%88%B0%E4%B8%83%E9%80%B2%E4%B8%83%E5%87%BA%E5%AD%90%E9%BE%8D%E6%A9%9F%E6%98%AF%E4%BB%80%E9%BA%BC%E9%AB%94%E9%A9%97/"/>
<url>/(%E5%BF%83%E5%BE%97)%E4%B8%8D%E5%B9%B8%E8%B2%B7%E5%88%B0%E4%B8%83%E9%80%B2%E4%B8%83%E5%87%BA%E5%AD%90%E9%BE%8D%E6%A9%9F%E6%98%AF%E4%BB%80%E9%BA%BC%E9%AB%94%E9%A9%97/</url>
<content type="html"><![CDATA[<div class="note info no-icon flat"><p>在台灣購買桌電有很多管道,但建議盡量到實體通路,購買有保障、評價好的品牌機,價格稍高,但可以省下大把時間,<br>不需搬著幾公斤的鐵塊到處解被動觸發的子龍任務。</p></div><p>這台電腦在 2020 年初購入,當時的想法很簡單,上課報告寫作業,i5 的舊筆電綽綽有餘,當時對買電腦完全沒概念,只知道 CPU 好就夠了(這不全然正確,想想看在小金龜上裝法拉利的引擎),興致勃勃地上網,在某網購平台看到,<code>電競水冷機 RTX-2060+i7-9700K</code>,竟然只要 3 萬出頭,不管三七二十一就火速下單,送到家剛開機時,七彩奪目的 RGB 燈,半透明側板,未來龐克設計的水冷系統,讓我興奮地整晚睡不著覺。</p><p>當時沉浸在<code>刺客教條</code>帶給我的 3A 絕佳體驗,毫無意識到 40%爆擊的背刺正攻向我,那是一個美好的清晨,奇怪,開機怎麼發出 bbb 蜂鳴器的刺耳叫聲,卡在 <a href="https://zh.wikipedia.org/zh-tw/BIOS">bios</a>,其實是<a href="https://zh.wikipedia.org/zh-tw/%E7%B5%B1%E4%B8%80%E5%8F%AF%E5%BB%B6%E4%BC%B8%E9%9F%8C%E9%AB%94%E4%BB%8B%E9%9D%A2">UEFI</a>,而且讀不到硬碟?花了幾天瞎搞當然是無疾而終,沒備用零件、沒電壓表,如何交叉測試,花了 400 多塊請了個年紀跟我差不多的大學生幫我看,但他拿著無線鍵盤鼓搗了 3 小時只得出可能是主機板的問題的結論,廢話,那我花錢請你來幹嘛,無奈,車馬費還是得付。</p><p>撥通原廠電話(不是平台,是負責出貨的廠商),對方態度並不是很好,一副跟他無關的樣子,當時也只能憋著一肚子氣,畢竟這台新機才剛到貨 2 個月,過了一個禮拜接到對方公司的電話,理由十分荒謬,bios 設定有問題,那邊測都沒有問題,得到這樣的答覆我並不意外,畢竟如果承認並被客人錄音,可能會導致公司的商譽損失,但不斷推卸責任並且拒絕認錯的態度真的讓人觀感非常差。</p><p>摸摸鼻子就認了,能用這種價格享受”電競級”桌電,已經很划算,當年底,再次壞去,這次是不斷開機、斷電的無限輪迴,黑貓物流很快就載回去原廠,猜猜這次給的理由是甚麼? “完全沒有問題!這邊測都可以正常開機”,氣到直接笑出來,反問要不要把秀斗的影片傳給他看,毫不意外的客服持續跳針,像留聲機一樣,重複應著荒謬又諷刺的”官方說法”。</p><div class="note danger no-icon flat"><p>到這裡已經對這家公司不抱任何期待,先不說他們修完電腦還忘記幫我安裝作業系統,又噴了一筆微軟授權費,就這樣風平浪靜地度過了一年,還記得那是個炎熱的下午,此起彼落的蜂鳴聲呼應著窗外的蟬鳴,又來,有完沒完,也知道結局跟理由是甚麼了,唯一不同的是被另外收了 1000 元的”檢測費”,到目前為止維修這台電腦的成本已經可以購買上一個檔次的電腦了,只希望不要再出問題。<br>玩遊戲到一半畫面卡住,上網查可能是記憶體接觸不良,自己隨便弄重裝好了就不理了,繼續用,昨天,跑程式有點卡頓,記憶體只剩一條在運作,Windows 大量的背景程式讓 Ram 飆到 80、90%,拆開主機滿滿的灰塵彷彿濃霧散出,決定花錢消災,請人幫我清潔、上油,又能動了。</p></div><p>低於市場行情的 3C 設備真的要慎選,平板、電腦、手機有所謂福利品,電腦零件同樣也有,價格甚至不到正常品的一半,惡劣一點的拿伺服器拆下來的垃圾重組,外行人也看不出來,整包算下來真的不划算,羊毛出在羊身上,價格便宜是犧牲品質、使用者體驗、賣家商譽換出來的,題外話,就算大品牌的筆電故障率不見得比較低,例如台灣的 A 開頭品牌,滔滔不絕的皇家子龍任務災情慘重,奇怪,美國 A 開頭有水果在上面的故障率就很低。</p>]]></content>
<categories>
<category> Diary </category>
</categories>
</entry>
<entry>
<title>(心得)我的第一台Lubuntu筆電</title>
<link href="/(%E5%BF%83%E5%BE%97)%E6%88%91%E7%9A%84%E7%AC%AC%E4%B8%80%E5%8F%B0Lubuntu%E7%AD%86%E9%9B%BB/"/>
<url>/(%E5%BF%83%E5%BE%97)%E6%88%91%E7%9A%84%E7%AC%AC%E4%B8%80%E5%8F%B0Lubuntu%E7%AD%86%E9%9B%BB/</url>
<content type="html"><![CDATA[<h2 id="前言"><a href="#前言" class="headerlink" title="前言"></a>前言</h2><p>以前就想要安裝Linux作業系統,長期習慣Windows介面的我遲未行動,一部分是因為許多Steam遊戲不支援,<br>舊筆電(使用5年)出現花屏,可能是顯示卡、螢幕問題,拿去修理效益比實在不大,但又有外出攜帶需求,結合價格、使用<br>頻率、開發需求、硬體規格等多方要素,2021年購入這台不到一萬的迷你筆電。</p><h2 id="規格"><a href="#規格" class="headerlink" title="規格"></a>規格</h2><ul><li>處理器:IntelR Celeron N4020 Processor 1.1 GHz (4M Cache, up to 2.8 GHz)</li><li>記憶體(內建/最大):4GB DDR4</li><li>硬碟:64G EMMC</li></ul><p>大小跟平板差不多(11.6”HD霧面寬螢幕),重量1.05KG,適合外出,預設安裝Windows10 S模式(只允許 Microsoft Store 上提供的應用程式),整體來說開機相當快速,能上網、文書處理、前後端開發、跑資料庫,不過有時會黑屏閃退,這台小筆電開太多Chrome分頁,CPU就會飆到80、90%,所以桌機就漸漸取代它,直到最近整理時,打算安裝輕量級的Ubuntu版本,使其起死回生。</p><h2 id="Lubuntu"><a href="#Lubuntu" class="headerlink" title="Lubuntu"></a>Lubuntu</h2><p>Linux有許多版本,適合桌面使用的Ubuntu,常用於伺服器和商業環境,許多其他Linux上游的Debian,CentOS等。<br>Ubuntu又有許多分支,UbuntuKylin、Kubuntu、Xubuntu、Edubuntu、Mythbuntu,本機選用的Lubuntu輕量、快速,適合老舊機型、規格低下的筆電。</p><h2 id="映像檔"><a href="#映像檔" class="headerlink" title="映像檔"></a>映像檔</h2><p>先到官方網站下載映像檔,<img src="/images/lubuntu/jammy-fish.jpg"></p><h2 id="燒錄開機碟"><a href="#燒錄開機碟" class="headerlink" title="燒錄開機碟"></a>燒錄開機碟</h2><p><img src="/images/lubuntu/rufus.jpg"><br>使用rufus製作開機碟<br>1.裝置,選擇外接硬碟(USB)<br>2.開機模式,選擇剛剛下載的Lubuntu映像檔<br>3.資料分割方式,依照UEFI、BIOS選擇</p><h2 id="UEFI-統一可擴充韌體接口-開機"><a href="#UEFI-統一可擴充韌體接口-開機" class="headerlink" title="UEFI(統一可擴充韌體接口)開機"></a>UEFI(統一可擴充韌體接口)開機</h2><p>Asus筆電開機時長按F2,進入UEFI,開機順序更改為USB開機<br><img src="/images/lubuntu/uefi.jpg"></p><h2 id="啟動安裝"><a href="#啟動安裝" class="headerlink" title="啟動安裝"></a>啟動安裝</h2><p>grub 啟動畫面。<br>1.安裝,選擇Try 或 Install Lubuntu。<br>2.顯卡問題,比如較新的 nvidia 卡,選擇safe graphics。<br>3.測試ram,選擇Test memory。<br><img src="/images/lubuntu/install-1.jpg"></p><h2 id="實時預覽"><a href="#實時預覽" class="headerlink" title="實時預覽"></a>實時預覽</h2><p>啟動後,探索 Lubuntu 並確保所有硬體都能正常工作。準備好後,雙擊桌面左上角的圖標<br><img src="/images/lubuntu/install-2.jpg"></p><h2 id="設定"><a href="#設定" class="headerlink" title="設定"></a>設定</h2><p><img src="/images/lubuntu/install-3.jpg"></p><h2 id="位置"><a href="#位置" class="headerlink" title="位置"></a>位置</h2><p><img src="/images/lubuntu/install-4.jpg"></p><h2 id="鍵盤"><a href="#鍵盤" class="headerlink" title="鍵盤"></a>鍵盤</h2><p><img src="/images/lubuntu/install-5.jpg"></p><h2 id="切割硬碟"><a href="#切割硬碟" class="headerlink" title="切割硬碟"></a>切割硬碟</h2><p><img src="/images/lubuntu/install-6.jpg"><br>刪除磁盤。格式化磁盤,請備份所有重要資料。</p><h2 id="密碼配置"><a href="#密碼配置" class="headerlink" title="密碼配置"></a>密碼配置</h2><p><img src="/images/lubuntu/install-7.jpg"></p><h2 id="最後配置檢查"><a href="#最後配置檢查" class="headerlink" title="最後配置檢查"></a>最後配置檢查</h2><p><img src="/images/lubuntu/install-8.jpg"></p><p>重新啟動,大功告成</p><h2 id="參考資料-amp-圖片"><a href="#參考資料-amp-圖片" class="headerlink" title="參考資料&圖片"></a>參考資料&圖片</h2><p><a href="https://manual.lubuntu.me/stable/1/Installing_lubuntu.html">lubuntu手冊</a></p>]]></content>
<categories>
<category> Linux </category>
</categories>
<tags>
<tag> Linux </tag>
<tag> Lubuntu </tag>
</tags>
</entry>
<entry>
<title>(技術)大型關係管理Monica</title>
<link href="/(%E6%8A%80%E8%A1%93)%E5%A4%A7%E5%9E%8B%E9%97%9C%E4%BF%82%E7%AE%A1%E7%90%86Monica/"/>
<url>/(%E6%8A%80%E8%A1%93)%E5%A4%A7%E5%9E%8B%E9%97%9C%E4%BF%82%E7%AE%A1%E7%90%86Monica/</url>
<content type="html"><![CDATA[<p>Monica 是一個開源專案,用於組織和記錄與親人的互動。又稱 PRM,個人關係管理。可將其視為您朋友或家人的 CRM,本文會介紹感興趣的功能,API、數據導出、OAuth、以及 issue。</p><blockquote><p>Monica’s vision is to help people have more meaningful relationships.<br>幫助人們建立有意義的關係</p></blockquote><p>主打”關係管理”,相較市面成熟的社交產品(如 Facebook),其定位特別,替人脈建立一個管理後台,還記得大學時參加幹訓、社團迎新,認識各社團幹部,常忘記小細節,此產品便能很好地解決這個問題,基於興趣,我也作為翻譯貢獻者,協助 monica 文件繁體中文的在地化,具體參考<a href="https://github.com/chienniman/monica">chienniman/monica</a>。<br>本文會介紹API授權(個人使用、開放授權),數據導出、社群討論issue,也會同時附上以上功能的原始碼分析,深入淺出的介紹設計模式在本專案的應用。</p><h2 id="執行-amp-部署"><a href="#執行-amp-部署" class="headerlink" title="執行&部署"></a>執行&部署</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br></pre></td><td class="code"><pre><span class="line">PHP 8.1+</span><br><span class="line">HTTP server with PHP support (eg: Apache, Nginx, Caddy)</span><br><span class="line">Composer</span><br><span class="line">MySQL</span><br></pre></td></tr></table></figure><figure class="highlight plaintext"><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">Platform.sh</span><br><span class="line">Heroku</span><br></pre></td></tr></table></figure><div class="note warning no-icon flat"><p>官方文件提到,構建專案程式需要 1.5GB RAM 以上,在 GCP 開便宜的 n1-standard-1,每月最少也要 600 台幣</p></div><h2 id="Authentication"><a href="#Authentication" class="headerlink" title="Authentication"></a>Authentication</h2><p>在 Monica 中,OAuth 2.0 與個人訪問令牌是兩種不同的身份驗證機制,但它們都用於授權 API 訪問。<br>OAuth 2.0 是一種標準的開放授權協議,允許用戶在 Monica 上授權第三方應用程序訪問數據,不需要將用戶名和密碼提供給該應用程序。當用戶通過 OAuth 2.0 授權授權應用程序時,該應用程序會收到一個訪問令牌,以便它可以代表用戶訪問 Monica API。<br>個人訪問令牌則是一種基於 Monica 賬戶的令牌,允許應用程序代表用戶訪問 Monica API。這意味著,當用戶提供他們的個人訪問令牌給應用程序時,該應用程序就可以代表該用戶訪問 API,就像它擁有 OAuth 2.0 訪問令牌一樣。<br>雖然這兩種令牌都可以用於授權 API 訪問,但它們的使用方式略有不同。 OAuth 2.0 是一種標準的開放授權協議,允許用戶授權第三方應用程序訪問其數據。個人訪問令牌則是一種在 Monica 內部生成的令牌,只能由用戶本人使用。在大多數情況下,建議使用 OAuth 2.0,因為它是更安全和更靈活的身份驗證協議。</p><h2 id="個人驗證授權"><a href="#個人驗證授權" class="headerlink" title="個人驗證授權"></a>個人驗證授權</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">curl -H "Authorization: Bearer Personal access token" https://app.monicahq.com/api</span><br></pre></td></tr></table></figure><h2 id="個人驗證令牌-personal-access-token"><a href="#個人驗證令牌-personal-access-token" class="headerlink" title="個人驗證令牌(personal-access-token)"></a>個人驗證令牌(personal-access-token)</h2><p><img src="/images/monica/personal-access-token.jpg"><br>將 token 放在 postmon 的 Authorization </p><h2 id="postman測試"><a href="#postman測試" class="headerlink" title="postman測試"></a>postman測試</h2><p><img src="/images/monica/postman-test.jpg"></p><h2 id="開放授權-OAuth"><a href="#開放授權-OAuth" class="headerlink" title="開放授權(OAuth)"></a>開放授權(OAuth)</h2><p>monica 也提供 OAuth 方式驗證 API,向伺服器發起驗證請求,跳出授權允許視窗,取得 Access Token,之後請求夾帶令牌訪問保護資源</p><h2 id="流程"><a href="#流程" class="headerlink" title="流程"></a>流程</h2><p><img src="/images/monica/oauth-process.jpg"></p><h2 id="Postmon"><a href="#Postmon" class="headerlink" title="Postmon"></a>Postmon</h2><p><img src="/images/monica/postmon-oauth.jpg"><br>配置 postmon 參數,將 Callback URL 填入 monica 後台 API,Token name、Client ID、Client Secret 填入 postmon</p><h2 id="授權請求"><a href="#授權請求" class="headerlink" title="授權請求"></a>授權請求</h2><p><img src="/images/monica/postmon-oauth-popup.jpg"><br>postmon 會跳出授權請求,允許後核發 Access Token、Refresh Token,點擊使用後自動帶入 Authorization Token 欄位</p><h2 id="測試請求"><a href="#測試請求" class="headerlink" title="測試請求"></a>測試請求</h2><p><img src="/images/monica/postmon-oauth-success.jpg"><br><a href="https://datatracker.ietf.org/doc/html/rfc6750">The OAuth 2.0 Authorization Framework: Bearer Token Usage</a><br><a href="https://www.monicahq.com/api">monica-api 文件</a></p><h2 id="第三方登入"><a href="#第三方登入" class="headerlink" title="第三方登入"></a>第三方登入</h2><p>官方託管 monica 支持 OAuth API,卻不支持 Facebook、Google 第三方登入,主流的平台為提升用戶體驗,通常會支持,疑惑地查找社群討論發現<br><img src="/images/monica/issue-558.jpg"><br>degan6 提出 OAuth 登入的 pull request,但被主要開發者拒絕了<br><img src="/images/monica/deny-issue.jpg"><br>1.不想要支持有疑慮的第三方登入(Facebook 疑似洩漏個資事件)<br> 2.官方託管已經移除大多數的追蹤程式碼</p><h2 id="數據導出"><a href="#數據導出" class="headerlink" title="數據導出"></a>數據導出</h2><p>monica 能輸出聯絡人vCard,使用者Sql、Json 等,相當便利,數據輸出需較長時間處理,隊列任務被存儲在數據庫,在多個請求之間共享任務。當任務被添加到隊列,被插入到表中,等待被執行。Laravel會跟蹤任務的狀態,未處理、處理中、已處理、失敗。<br>Laravel預設使用同步隊列(sync),保證實時、穩定性,方便進行開發與測試,但對於大量、耗時任務,同步處理會阻塞主線程,因此不適合高併發場景。</p><h2 id="vCard"><a href="#vCard" class="headerlink" title="vCard"></a>vCard</h2><p><img src="/images/monica/vcard.jpg"><br>vCard 是電子名片的文件格式標準。它一般附加在電子郵件之後,但也可以用於其它場合(如在網際網路上相互交換)。vCard 可包含的信息有:姓名、地址資訊、電話號碼、URL,logo,相片等。</p><h2 id="Routes"><a href="#Routes" class="headerlink" title="Routes"></a>Routes</h2><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// monica/routes/web.php </span></span><br><span class="line"><span class="title class_">Route</span>::<span class="title function_ invoke__">get</span>(<span class="string">'/people/{contact}/vcard'</span>, <span class="string">'ContactsController@vcard'</span>)-><span class="title function_ invoke__">name</span>(<span class="string">'vcard'</span>);</span><br></pre></td></tr></table></figure><h2 id="ContactsController"><a href="#ContactsController" class="headerlink" title="ContactsController"></a>ContactsController</h2><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// monica/app/Http/Controllers/ContactsController.php</span></span><br><span class="line"><span class="comment">// 依賴注入:Contact、ExportVCard、Str和LocaleHelper通過依賴注入。</span></span><br><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">vCard</span>(<span class="params">Contact <span class="variable">$contact</span></span>)</span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="comment">// 禁用 Debugbar 避免在下載 vCard 時,偵錯列(debugbar)出現在輸出中</span></span><br><span class="line"> <span class="keyword">if</span> (<span class="title function_ invoke__">config</span>(<span class="string">'app.debug'</span>) && <span class="title function_ invoke__">class_exists</span>(<span class="string">'\Barryvdh\Debugbar\Facade'</span>)) {</span><br><span class="line"> <span class="title class_">Debugbar</span>::<span class="title function_ invoke__">disable</span>();</span><br><span class="line"> }</span><br><span class="line"> <span class="comment">// Laravel 中的全域輔助函數,用於從應用程式服務容器中取回特定的服務實例</span></span><br><span class="line"> <span class="variable">$vcard</span> = <span class="title function_ invoke__">app</span>(<span class="title class_">ExportVCard</span>::<span class="variable language_">class</span>)-><span class="title function_ invoke__">execute</span>([</span><br><span class="line"> <span class="string">'account_id'</span> => <span class="title function_ invoke__">auth</span>()-><span class="title function_ invoke__">user</span>()->account_id,</span><br><span class="line"> <span class="string">'contact_id'</span> => <span class="variable">$contact</span>->id,</span><br><span class="line"> ]);</span><br><span class="line"><span class="comment">// response 函數將 $vcard 序列化後的 VCard 字符串作為內容,設置 'Content-type' 標頭為 'text/x-vcard'</span></span><br><span class="line"><span class="comment">// 表示傳輸的內容是 VCard 格式。同時,設置 'Content-Disposition' 標頭為 'attachment; </span></span><br><span class="line"><span class="comment">// filename='.Str::slug($contact->name, '-', LocaleHelper::getLang()).'.vcf'</span></span><br><span class="line"><span class="comment">// 表示將其作為下載文件附件發送給用戶端,並將文件名設置為聯絡人的名稱轉換為 slug 格式後加上 .vcf 的檔名</span></span><br><span class="line"> <span class="keyword">return</span> <span class="title function_ invoke__">response</span>(<span class="variable">$vcard</span>-><span class="title function_ invoke__">serialize</span>())</span><br><span class="line"> -><span class="title function_ invoke__">header</span>(<span class="string">'Content-type'</span>, <span class="string">'text/x-vcard'</span>)</span><br><span class="line"> -><span class="title function_ invoke__">header</span>(<span class="string">'Content-Disposition'</span>, <span class="string">'attachment; filename='</span>.<span class="title class_">Str</span>::<span class="title function_ invoke__">slug</span>(<span class="variable">$contact</span>->name, <span class="string">'-'</span>, <span class="title class_">LocaleHelper</span>::<span class="title function_ invoke__">getLang</span>()).<span class="string">'.vcf'</span>);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="Sql-amp-Json導出"><a href="#Sql-amp-Json導出" class="headerlink" title="Sql & Json導出"></a>Sql & Json導出</h2><p><img src="/images/export-data.jpg"></p><h2 id="Routes-1"><a href="#Routes-1" class="headerlink" title="Routes"></a>Routes</h2><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// monica/routes/web.php </span></span><br><span class="line"><span class="title class_">Route</span>::<span class="title function_ invoke__">post</span>(<span class="string">'/settings/exportToSql'</span>, <span class="string">'Settings\\ExportController@storeSQL'</span>)-><span class="title function_ invoke__">name</span>(<span class="string">'export.store.sql'</span>);</span><br><span class="line"><span class="title class_">Route</span>::<span class="title function_ invoke__">post</span>(<span class="string">'/settings/exportToJson'</span>, <span class="string">'Settings\\ExportController@storeJson'</span>)-><span class="title function_ invoke__">name</span>(<span class="string">'export.store.json'</span>);</span><br></pre></td></tr></table></figure><h2 id="ExportJob"><a href="#ExportJob" class="headerlink" title="ExportJob"></a>ExportJob</h2><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><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></pre></td><td class="code"><pre><span class="line"><span class="comment">// monica/app/Models/Account/ExportJob.php </span></span><br><span class="line"><span class="keyword">namespace</span> <span class="title class_">App</span>\<span class="title class_">Models</span>\<span class="title class_">Account</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">use</span> <span class="title">App</span>\<span class="title">Traits</span>\<span class="title">HasUuid</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">App</span>\<span class="title">Models</span>\<span class="title">User</span>\<span class="title">User</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">Illuminate</span>\<span class="title">Database</span>\<span class="title">Eloquent</span>\<span class="title">Model</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">App</span>\<span class="title">Notifications</span>\<span class="title">ExportAccountDone</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">Illuminate</span>\<span class="title">Database</span>\<span class="title">Eloquent</span>\<span class="title">Relations</span>\<span class="title">BelongsTo</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">Illuminate</span>\<span class="title">Database</span>\<span class="title">Eloquent</span>\<span class="title">Factories</span>\<span class="title">HasFactory</span>;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">ExportJob</span> <span class="keyword">extends</span> <span class="title">Model</span></span></span><br><span class="line"><span class="class"></span>{</span><br><span class="line"> <span class="keyword">use</span> <span class="title">HasUuid</span>, <span class="title">HasFactory</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">const</span> <span class="variable constant_">EXPORT_TODO</span> = <span class="string">'todo'</span>;</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">const</span> <span class="variable constant_">EXPORT_DOING</span> = <span class="string">'doing'</span>;</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">const</span> <span class="variable constant_">EXPORT_DONE</span> = <span class="string">'done'</span>;</span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">const</span> <span class="variable constant_">EXPORT_FAILED</span> = <span class="string">'failed'</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">const</span> <span class="variable constant_">SQL</span> = <span class="string">'sql'</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="keyword">const</span> <span class="variable constant_">JSON</span> = <span class="string">'json'</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">protected</span> <span class="variable">$fillable</span> = [</span><br><span class="line"> <span class="string">'uuid'</span>,</span><br><span class="line"> <span class="string">'account_id'</span>,</span><br><span class="line"> <span class="string">'user_id'</span>,</span><br><span class="line"> <span class="string">'type'</span>,</span><br><span class="line"> <span class="string">'status'</span>,</span><br><span class="line"> <span class="string">'filesystem'</span>,</span><br><span class="line"> <span class="string">'filename'</span>,</span><br><span class="line"> <span class="string">'started_at'</span>,</span><br><span class="line"> <span class="string">'ended_at'</span>,</span><br><span class="line"> ];</span><br><span class="line"></span><br><span class="line"> <span class="keyword">protected</span> <span class="variable">$guarded</span> = [<span class="string">'id'</span>];</span><br><span class="line"></span><br><span class="line"> <span class="keyword">protected</span> <span class="variable">$dates</span> = [</span><br><span class="line"> <span class="string">'started_at'</span>,</span><br><span class="line"> <span class="string">'ended_at'</span>,</span><br><span class="line"> ];</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">account</span>(<span class="params"></span>)</span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="variable language_">$this</span>-><span class="title function_ invoke__">belongsTo</span>(<span class="title class_">Account</span>::<span class="variable language_">class</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">user</span>(<span class="params"></span>)</span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="variable language_">$this</span>-><span class="title function_ invoke__">belongsTo</span>(<span class="title class_">User</span>::<span class="variable language_">class</span>);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">start</span>(<span class="params"></span>): <span class="title">void</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="variable language_">$this</span>->status = <span class="built_in">self</span>::<span class="variable constant_">EXPORT_DOING</span>;</span><br><span class="line"> <span class="variable language_">$this</span>->started_at = <span class="title function_ invoke__">now</span>();</span><br><span class="line"> <span class="variable language_">$this</span>-><span class="title function_ invoke__">save</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="function"><span class="keyword">function</span> <span class="title">end</span>(<span class="params"></span>): <span class="title">void</span></span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="variable language_">$this</span>->status = <span class="built_in">self</span>::<span class="variable constant_">EXPORT_DONE</span>;</span><br><span class="line"> <span class="variable language_">$this</span>->ended_at = <span class="title function_ invoke__">now</span>();</span><br><span class="line"> <span class="variable language_">$this</span>-><span class="title function_ invoke__">save</span>();</span><br><span class="line"> </span><br><span class="line"> <span class="variable language_">$this</span>->user-><span class="title function_ invoke__">notify</span>(<span class="keyword">new</span> <span class="title class_">ExportAccountDone</span>(<span class="variable">$this</span>));</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="ExportController"><a href="#ExportController" class="headerlink" title="ExportController"></a>ExportController</h2><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// monica/app/Http/Controllers/Settings/ExportController.php</span></span><br><span class="line"><span class="keyword">private</span> <span class="function"><span class="keyword">function</span> <span class="title">newExport</span>(<span class="params"><span class="keyword">string</span> <span class="variable">$type</span></span>): <span class="title">ExportJob</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="variable">$exports</span> = <span class="title class_">ExportJob</span>::<span class="title function_ invoke__">where</span>([</span><br><span class="line"> <span class="string">'account_id'</span> => <span class="title function_ invoke__">auth</span>()-><span class="title function_ invoke__">user</span>()->account_id,</span><br><span class="line"> <span class="string">'user_id'</span> => <span class="title function_ invoke__">auth</span>()-><span class="title function_ invoke__">user</span>()->id,</span><br><span class="line"> ])</span><br><span class="line"> -><span class="title function_ invoke__">orderBy</span>(<span class="string">'created_at'</span>)</span><br><span class="line"> -><span class="title function_ invoke__">get</span>();</span><br><span class="line"> <span class="comment">// 輸出任務總量超過最大配置,刪除最舊的任務</span></span><br><span class="line"> <span class="keyword">if</span> (<span class="variable">$exports</span>-><span class="title function_ invoke__">count</span>() >= <span class="title function_ invoke__">config</span>(<span class="string">'monica.export_size'</span>)) {</span><br><span class="line"> <span class="variable">$job</span> = <span class="variable">$exports</span>-><span class="title function_ invoke__">first</span>();</span><br><span class="line"> <span class="keyword">try</span> {</span><br><span class="line"> <span class="keyword">if</span> (<span class="variable">$job</span>->filename !== <span class="literal">null</span>) {</span><br><span class="line"> <span class="title class_">StorageHelper</span>::<span class="title function_ invoke__">disk</span>(<span class="variable">$job</span>->location)</span><br><span class="line"> -><span class="title function_ invoke__">delete</span>(<span class="variable">$job</span>->filename);</span><br><span class="line"> }</span><br><span class="line"> } <span class="keyword">finally</span> {</span><br><span class="line"> <span class="comment">// 確保釋放資源,避免內存洩漏、資源浪費</span></span><br><span class="line"> <span class="variable">$job</span>-><span class="title function_ invoke__">delete</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">return</span> <span class="title class_">ExportJob</span>::<span class="title function_ invoke__">create</span>([</span><br><span class="line"> <span class="string">'account_id'</span> => <span class="title function_ invoke__">auth</span>()-><span class="title function_ invoke__">user</span>()->account_id,</span><br><span class="line"> <span class="string">'user_id'</span> => <span class="title function_ invoke__">auth</span>()-><span class="title function_ invoke__">user</span>()->id,</span><br><span class="line"> <span class="string">'type'</span> => <span class="variable">$type</span>,</span><br><span class="line"> ]);</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">storeSql</span>(<span class="params"></span>)</span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="variable">$job</span> = <span class="variable language_">$this</span>-><span class="title function_ invoke__">newExport</span>(<span class="title class_">ExportJob</span>::<span class="variable constant_">SQL</span>);</span><br><span class="line"> <span class="title class_">ExportAccount</span>::<span class="title function_ invoke__">dispatch</span>(<span class="variable">$job</span>);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> <span class="title function_ invoke__">redirect</span>()-><span class="title function_ invoke__">route</span>(<span class="string">'settings.export.index'</span>)</span><br><span class="line"> -><span class="title function_ invoke__">withStatus</span>(<span class="title function_ invoke__">trans</span>(<span class="string">'settings.export_submitted'</span>));</span><br><span class="line">}</span><br><span class="line"></span><br><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">storeJson</span>(<span class="params"></span>)</span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="variable">$job</span> = <span class="variable language_">$this</span>-><span class="title function_ invoke__">newExport</span>(<span class="title class_">ExportJob</span>::<span class="variable constant_">JSON</span>);</span><br><span class="line"> <span class="title class_">ExportAccount</span>::<span class="title function_ invoke__">dispatch</span>(<span class="variable">$job</span>);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> <span class="title function_ invoke__">redirect</span>()-><span class="title function_ invoke__">route</span>(<span class="string">'settings.export.index'</span>)</span><br><span class="line"> -><span class="title function_ invoke__">withStatus</span>(<span class="title function_ invoke__">trans</span>(<span class="string">'settings.export_submitted'</span>));</span><br><span class="line"></span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="Dispatch"><a href="#Dispatch" class="headerlink" title="Dispatch"></a>Dispatch</h2><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// framework/src/Illuminate/Foundation/Bus/Dispatchable.php </span></span><br><span class="line"><span class="keyword">public</span> <span class="built_in">static</span> <span class="function"><span class="keyword">function</span> <span class="title">dispatch</span>(<span class="params">...<span class="variable">$arguments</span></span>)</span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="keyword">return</span> <span class="keyword">new</span> <span class="title class_">PendingDispatch</span>(<span class="keyword">new</span> <span class="built_in">static</span>(...<span class="variable">$arguments</span>));</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="PendingDispatch"><a href="#PendingDispatch" class="headerlink" title="PendingDispatch"></a>PendingDispatch</h2><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><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></pre></td><td class="code"><pre><span class="line"><span class="comment">// framework/src/Illuminate/Foundation/Bus/PendingDispatch.php </span></span><br><span class="line"><span class="comment">// 提供了一個額外的介面,讓使用者可以更方便地調用 Job 物件的方法。同時,在物件的銷毀時刻,</span></span><br><span class="line"><span class="comment">// PendingDispatch 會根據 $this->afterResponse 屬性來決定要如何分派 $this->job。</span></span><br><span class="line"><span class="keyword">namespace</span> <span class="title class_">Illuminate</span>\<span class="title class_">Foundation</span>\<span class="title class_">Bus</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">UniqueLock</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">Illuminate</span>\<span class="title">Container</span>\<span class="title">Container</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">Illuminate</span>\<span class="title">Contracts</span>\<span class="title">Bus</span>\<span class="title">Dispatcher</span>;</span><br><span class="line"><span class="keyword">use</span> <span class="title">Illuminate</span>\<span class="title">Contracts</span>\<span class="title">Cache</span>\<span class="title">Repository</span> <span class="keyword">as</span> <span class="title">Cache</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">ShouldBeUnique</span>;</span><br><span class="line"></span><br><span class="line"><span class="class"><span class="keyword">class</span> <span class="title">PendingDispatch</span></span></span><br><span class="line"><span class="class"></span>{</span><br><span class="line"> <span class="keyword">protected</span> <span class="variable">$job</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">protected</span> <span class="variable">$afterResponse</span> = <span class="literal">false</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__construct</span>(<span class="params"><span class="variable">$job</span></span>)</span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="variable language_">$this</span>->job = <span class="variable">$job</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">onConnection</span>(<span class="params"><span class="variable">$connection</span></span>)</span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="variable language_">$this</span>->job-><span class="title function_ invoke__">onConnection</span>(<span class="variable">$connection</span>);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> <span class="variable language_">$this</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">onQueue</span>(<span class="params"><span class="variable">$queue</span></span>)</span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="variable language_">$this</span>->job-><span class="title function_ invoke__">onQueue</span>(<span class="variable">$queue</span>);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> <span class="variable language_">$this</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">allOnConnection</span>(<span class="params"><span class="variable">$connection</span></span>)</span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="variable language_">$this</span>->job-><span class="title function_ invoke__">allOnConnection</span>(<span class="variable">$connection</span>);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> <span class="variable language_">$this</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">allOnQueue</span>(<span class="params"><span class="variable">$queue</span></span>)</span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="variable language_">$this</span>->job-><span class="title function_ invoke__">allOnQueue</span>(<span class="variable">$queue</span>);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> <span class="variable language_">$this</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">delay</span>(<span class="params"><span class="variable">$delay</span></span>)</span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="variable language_">$this</span>->job-><span class="title function_ invoke__">delay</span>(<span class="variable">$delay</span>);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> <span class="variable language_">$this</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">afterCommit</span>(<span class="params"></span>)</span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="variable language_">$this</span>->job-><span class="title function_ invoke__">afterCommit</span>();</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> <span class="variable language_">$this</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">beforeCommit</span>(<span class="params"></span>)</span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="variable language_">$this</span>->job-><span class="title function_ invoke__">beforeCommit</span>();</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> <span class="variable language_">$this</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">chain</span>(<span class="params"><span class="variable">$chain</span></span>)</span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="variable language_">$this</span>->job-><span class="title function_ invoke__">chain</span>(<span class="variable">$chain</span>);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> <span class="variable language_">$this</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">afterResponse</span>(<span class="params"></span>)</span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="variable language_">$this</span>->afterResponse = <span class="literal">true</span>;</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> <span class="variable language_">$this</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 實現對任務調度執行的控制,確保同一個唯一的任務在同一時間只會被調度執行一次。</span></span><br><span class="line"> <span class="comment">// 返回true,則表示當前任務可以被調度執行,否則返回false,表示該任務已經被另一個進程或線程佔用了</span></span><br><span class="line"> <span class="keyword">protected</span> <span class="function"><span class="keyword">function</span> <span class="title">shouldDispatch</span>(<span class="params"></span>)</span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="keyword">if</span> (! <span class="variable language_">$this</span>->job <span class="keyword">instanceof</span> ShouldBeUnique) {</span><br><span class="line"> <span class="keyword">return</span> <span class="literal">true</span>;</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> (<span class="keyword">new</span> <span class="title class_">UniqueLock</span>(<span class="title class_">Container</span>::<span class="title function_ invoke__">getInstance</span>()-><span class="title function_ invoke__">make</span>(<span class="title class_">Cache</span>::<span class="variable language_">class</span>)))</span><br><span class="line"> -><span class="title function_ invoke__">acquire</span>(<span class="variable">$this</span>->job);</span><br><span class="line"> }</span><br><span class="line"></span><br><span class="line"> <span class="comment">// $pendingDispatch 可以透過 __call 方法動態調用 $job 實例上的任何方法</span></span><br><span class="line"> <span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">__call</span>(<span class="params"><span class="variable">$method</span>, <span class="variable">$parameters</span></span>)</span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="variable language_">$this</span>->job->{<span class="variable">$method</span>}(...<span class="variable">$parameters</span>);</span><br><span class="line"></span><br><span class="line"> <span class="keyword">return</span> <span class="variable language_">$this</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> <span class="function"><span class="keyword">function</span> <span class="title">__destruct</span>(<span class="params"></span>)</span></span><br><span class="line"><span class="function"> </span>{</span><br><span class="line"> <span class="keyword">if</span> (! <span class="variable language_">$this</span>-><span class="title function_ invoke__">shouldDispatch</span>()) {</span><br><span class="line"> <span class="keyword">return</span>;</span><br><span class="line"> } <span class="keyword">elseif</span> (<span class="variable language_">$this</span>->afterResponse) {</span><br><span class="line"> <span class="title function_ invoke__">app</span>(<span class="title class_">Dispatcher</span>::<span class="variable language_">class</span>)-><span class="title function_ invoke__">dispatchAfterResponse</span>(<span class="variable">$this</span>->job);</span><br><span class="line"> } <span class="keyword">else</span> {</span><br><span class="line"> <span class="title function_ invoke__">app</span>(<span class="title class_">Dispatcher</span>::<span class="variable language_">class</span>)-><span class="title function_ invoke__">dispatch</span>(<span class="variable">$this</span>->job);</span><br><span class="line"> }</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="成功通知"><a href="#成功通知" class="headerlink" title="成功通知"></a>成功通知</h2><p><img src="/images/monica/export-email.jpg"></p><h2 id="發信notify"><a href="#發信notify" class="headerlink" title="發信notify"></a>發信notify</h2><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// monica/app/Models/Account/ExportJob.php </span></span><br><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">end</span>(<span class="params"></span>): <span class="title">void</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="variable language_">$this</span>->status = <span class="built_in">self</span>::<span class="variable constant_">EXPORT_DONE</span>;</span><br><span class="line"> <span class="variable language_">$this</span>->ended_at = <span class="title function_ invoke__">now</span>();</span><br><span class="line"> <span class="variable language_">$this</span>-><span class="title function_ invoke__">save</span>();</span><br><span class="line"></span><br><span class="line"> <span class="variable language_">$this</span>->user-><span class="title function_ invoke__">notify</span>(<span class="keyword">new</span> <span class="title class_">ExportAccountDone</span>(<span class="variable">$this</span>));</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="ExportAccountDone"><a href="#ExportAccountDone" class="headerlink" title="ExportAccountDone"></a>ExportAccountDone</h2><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// monica/app/Notifications/ExportAccountDone.php </span></span><br><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">toMail</span>(<span class="params">User <span class="variable">$user</span></span>): <span class="title">MailMessage</span></span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="variable">$date</span> = <span class="title class_">Carbon</span>::<span class="title function_ invoke__">parse</span>(<span class="variable">$this</span>->exportJob->created_at)</span><br><span class="line"> -><span class="title function_ invoke__">setTimezone</span>(<span class="variable">$user</span>->timezone);</span><br><span class="line"> <span class="comment">// 成功、主題、歡迎詞、描述、下載連結</span></span><br><span class="line"> <span class="keyword">return</span> (<span class="keyword">new</span> <span class="title class_">MailMessage</span>)</span><br><span class="line"> -><span class="title function_ invoke__">success</span>()</span><br><span class="line"> -><span class="title function_ invoke__">subject</span>(<span class="title function_ invoke__">trans</span>(<span class="string">'mail.export_title'</span>))</span><br><span class="line"> -><span class="title function_ invoke__">greeting</span>(<span class="title function_ invoke__">trans</span>(<span class="string">'mail.greetings'</span>, [<span class="string">'username'</span> => <span class="variable">$user</span>->first_name]))</span><br><span class="line"> -><span class="title function_ invoke__">line</span>(<span class="title function_ invoke__">trans</span>(<span class="string">'mail.export_description'</span>, [<span class="string">'date'</span> => <span class="title class_">DateHelper</span>::<span class="title function_ invoke__">getShortDate</span>(<span class="variable">$date</span>)]))</span><br><span class="line"> -><span class="title function_ invoke__">action</span>(<span class="title function_ invoke__">trans</span>(<span class="string">'mail.export_download'</span>), <span class="title function_ invoke__">route</span>(<span class="string">'settings.export.index'</span>));</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="下載資源"><a href="#下載資源" class="headerlink" title="下載資源"></a>下載資源</h2><figure class="highlight php"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br></pre></td><td class="code"><pre><span class="line"><span class="comment">// monica/app/Http/Controllers/Settings/ExportController.php </span></span><br><span class="line"><span class="keyword">public</span> <span class="function"><span class="keyword">function</span> <span class="title">download</span>(<span class="params">Request <span class="variable">$request</span>, <span class="keyword">string</span> <span class="variable">$uuid</span></span>)</span></span><br><span class="line"><span class="function"></span>{</span><br><span class="line"> <span class="comment">// 查詢第一筆紀錄</span></span><br><span class="line"> <span class="variable">$job</span> = <span class="title class_">ExportJob</span>::<span class="title function_ invoke__">where</span>([</span><br><span class="line"> <span class="string">'account_id'</span> => <span class="title function_ invoke__">auth</span>()-><span class="title function_ invoke__">user</span>()->account_id,</span><br><span class="line"> <span class="string">'user_id'</span> => <span class="title function_ invoke__">auth</span>()-><span class="title function_ invoke__">user</span>()->id,</span><br><span class="line"> <span class="string">'uuid'</span> => <span class="variable">$uuid</span>,</span><br><span class="line"> ])-><span class="title function_ invoke__">firstOrFail</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> (<span class="variable">$job</span>->status !== <span class="title class_">ExportJob</span>::<span class="variable constant_">EXPORT_DONE</span>) {</span><br><span class="line"> <span class="keyword">return</span> <span class="title function_ invoke__">redirect</span>()-><span class="title function_ invoke__">route</span>(<span class="string">'settings.export.index'</span>)</span><br><span class="line"> -><span class="title function_ invoke__">withErrors</span>(<span class="title function_ invoke__">trans</span>(<span class="string">'settings.export_not_done'</span>));</span><br><span class="line"> }</span><br><span class="line"> <span class="variable">$disk</span> = <span class="title class_">StorageHelper</span>::<span class="title function_ invoke__">disk</span>(<span class="variable">$job</span>->location);</span><br><span class="line"></span><br><span class="line"> <span class="comment">// 返回請求資料</span></span><br><span class="line"> <span class="keyword">return</span> <span class="variable">$disk</span>-><span class="title function_ invoke__">response</span>(<span class="variable">$job</span>->filename,</span><br><span class="line"> <span class="string">"monica.<span class="subst">{$job->type}</span>"</span>,</span><br><span class="line"> [</span><br><span class="line"> <span class="string">'Content-Type'</span> => <span class="string">"application/<span class="subst">{$job->type}</span>; charset=utf-8"</span>,</span><br><span class="line"> <span class="string">'Content-Disposition'</span> => <span class="string">"attachment; filename=monica.<span class="subst">{$job->type}</span>"</span>,</span><br><span class="line"> ]</span><br><span class="line"> );</span><br><span class="line">}</span><br></pre></td></tr></table></figure>]]></content>
<categories>
<category> Backend </category>
</categories>
<tags>
<tag> Backend </tag>
<tag> Authentication </tag>
<tag> Authorization </tag>
<tag> Monica </tag>
<tag> Laravel </tag>
<tag> OAuth </tag>
</tags>
</entry>
<entry>
<title>(技術)網頁打包壓縮的好用工具Parcel</title>
<link href="/(%E6%8A%80%E8%A1%93)%E7%B6%B2%E9%A0%81%E6%89%93%E5%8C%85%E5%A3%93%E7%B8%AE%E7%9A%84%E5%A5%BD%E7%94%A8%E5%B7%A5%E5%85%B7Parcel/"/>
<url>/(%E6%8A%80%E8%A1%93)%E7%B6%B2%E9%A0%81%E6%89%93%E5%8C%85%E5%A3%93%E7%B8%AE%E7%9A%84%E5%A5%BD%E7%94%A8%E5%B7%A5%E5%85%B7Parcel/</url>
<content type="html"><![CDATA[<div class="note info no-icon flat"><p>說到打包工具,多數人的第一直覺就是Webpack,我也不例外,今天就要介紹一個簡單快速的打包工具Parcel,適用於小型專案的開發。</p></div><h2 id="為何壓縮"><a href="#為何壓縮" class="headerlink" title="為何壓縮"></a>為何壓縮</h2><p>伺服器中,會使用壓縮來減少頻寬和傳輸時間,從而提高網站性能和用戶體驗。通常壓縮的是返回給客戶端的HTML、CSS、JavaScript、圖像等靜態資源文件。透過減少文件大小。</p><p>網頁伺服器會使用一些壓縮算法,例如gzip和deflate,將靜態資源文件壓縮成壓縮包,然後在將壓縮包傳輸給客戶端。客戶端接收到壓縮包後,會解壓縮文件並顯示頁面。</p><p>壓縮技術可以提高網站性能,但壓縮也可能增加服務器的負擔和處理時間。此外,某些瀏覽器不支持特定的壓縮算法,因此需要在服務器端進行相應的配置和優化。</p><h2 id="原生性能"><a href="#原生性能" class="headerlink" title="原生性能"></a>原生性能</h2><blockquote><p>Parcel’s JavaScript compiler, CSS transformer, and source maps implementation are written in Rust for maximum performance. It’s 10-20x faster than other JavaScript-based tools!<br>Parcel’s JavaScript compiler is built on SWC, which handles transpiling JavaScript, JSX, and TypeScript. On top of SWC, Parcel implements dependency collection, bundling, scope hoisting, tree shaking, Node emulation, hot reloading, and more.<br>Parcel’s CSS transformer and minifier is built in Rust on top of the browser-grade CSS parser used in Firefox. It’s over 100x faster than other JavaScript-based transformers and minifiers.</p></blockquote><p>JavaScript 編譯器、CSS 轉換器和源映射實現是用Rust編寫的,以實現最佳性能。它比其他基於 JavaScript 的工具快 10-20 倍!<br>Parcel 的 JavaScript 編譯器建立在SWC之上,它處理轉譯 JavaScript、JSX 和 TypeScript。在 SWC 之上,Parcel 實現了依賴收集、捆綁、範圍提升、tree shaking、Node 仿真、熱重載等。<br>Parcel 的 CSS 轉換器和縮小器是在 Firefox 中使用的瀏覽器級 CSS 解析器之上的 Rust 中構建的。比其他JavaScript 的轉換器和壓縮器快 100 倍以上。</p><h2 id="快取"><a href="#快取" class="headerlink" title="快取"></a>快取</h2><blockquote><p>Everything Parcel does is cached – transformation, dependency resolution, bundling, optimizing, and everything in between. This means the dev server restarts instantly, and the same code is never built twice.<br>Parcel automatically tracks all of the files, configuration, plugins, and dev dependencies that are involved in your build, and granularly invalidates the cache when something changes. It integrates with low-level operating system APIs to determine what files have changed in milliseconds, no matter the project size.</p></blockquote><p>Parcel 所做的一切都被緩存——轉換、依賴解析、捆綁、優化,以及介於兩者之間的一切。這意味著開發伺服器會立即重新啟動,並且永遠不會構建相同的代碼兩次。<br>自動追蹤構建中所有文件、配置、插件和依賴項,並在變化時使緩存失效。與低階操作系統 API 整合,無論項目大小如何,都可以在幾毫秒內確定哪些文件發生了變化。</p><h2 id="安裝"><a href="#安裝" class="headerlink" title="安裝"></a>安裝</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install --save-dev parcel</span><br></pre></td></tr></table></figure><h2 id="配置"><a href="#配置" class="headerlink" title="配置"></a>配置</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br></pre></td><td class="code"><pre><span class="line">{</span><br><span class="line"> "name": "my-project",</span><br><span class="line"> "source": "src/index.html",</span><br><span class="line"> "scripts": {</span><br><span class="line"> "start": "parcel",</span><br><span class="line"> "build": "parcel build"</span><br><span class="line"> },</span><br><span class="line"> "devDependencies": {</span><br><span class="line"> "parcel": "latest"</span><br><span class="line"> }</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="資料夾"><a href="#資料夾" class="headerlink" title="資料夾"></a>資料夾</h2><figure class="highlight plaintext"><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">my-app/</span><br><span class="line"> |- dist/ # 編譯後代碼</span><br><span class="line"> | |- index.html # 打包後的 HTML </span><br><span class="line"> | |- main.js # 打包後的 JavaScript </span><br><span class="line"> |- node_modules/ # 第三方庫</span><br><span class="line"> |- src/ # 源碼</span><br><span class="line"> | |- index.html # HTML 入口</span><br><span class="line"> | |- main.js # JavaScript 入口</span><br><span class="line"> |- package.json # 配置</span><br><span class="line"> |-.parcel-cache # 打包緩存</span><br></pre></td></tr></table></figure><p><a href="https://parceljs.org/features/development/">開發環境</a><br><a href="https://parceljs.org/features/production/">生產環境</a></p><h2 id="JavaScript"><a href="#JavaScript" class="headerlink" title="JavaScript"></a>JavaScript</h2><p>介紹Parcel中js的配置前,先了解ES modules跟 CommonJS 的差異。</p><h2 id="載入"><a href="#載入" class="headerlink" title="載入"></a>載入</h2><p>ES modules 使用 import 載入模組,而 CommonJS 使用 require 載入模組。ES modules 在運行時進行靜態解析,而 CommonJS 在運行時動態載入。</p><h2 id="編譯"><a href="#編譯" class="headerlink" title="編譯"></a>編譯</h2><p>ES modules 在編譯時會進行預解析和標記,使得編譯器能夠在編譯時知道哪些模組需要載入,而 CommonJS 則是在運行時動態載入,因此需要進行動態解析和加載,相對於 ES modules 更耗費運行時的資源。</p><h2 id="輸出"><a href="#輸出" class="headerlink" title="輸出"></a>輸出</h2><p>ES modules 使用 export 輸出模組,而 CommonJS 使用 module.exports 輸出模組。ES modules 可以直接將對象、函數等直接作為輸出,而 CommonJS 必須透過 module.exports 將需要輸出的對象或函數包裝成對象再進行輸出。</p><h2 id="結論"><a href="#結論" class="headerlink" title="結論"></a>結論</h2><p>總之,ES modules 是一種新的模組化,比起CommonJS,有更好的靜態解析能力,支持標記和預解析,並且可以在編譯時優化。然而,目前在瀏覽器中 ES modules 的支援度還不夠完善,需要透過轉譯或者 polyfill 來實現,而 CommonJS 則是在 Node.js 等環境中得到了廣泛的使用。</p><h2 id="ES-modules"><a href="#ES-modules" class="headerlink" title="ES modules"></a>ES modules</h2><p>add.js</p><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">export</span> <span class="keyword">function</span> <span class="title function_">add</span>(<span class="params">a, b</span>) {</span><br><span class="line"> <span class="keyword">return</span> a + b;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>sum.js</p><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">import</span> {add} <span class="keyword">from</span> <span class="string">'./add.js'</span>;</span><br><span class="line"></span><br><span class="line"><span class="keyword">export</span> <span class="keyword">function</span> <span class="title function_">sum</span>(<span class="params">x,y</span>) {</span><br><span class="line"> <span class="keyword">return</span> <span class="title function_">add</span>(x, y);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="CommonJS"><a href="#CommonJS" class="headerlink" title="CommonJS"></a>CommonJS</h2><p>add.js</p><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></pre></td><td class="code"><pre><span class="line"><span class="built_in">exports</span>.<span class="property">add</span>=<span class="keyword">function</span>(<span class="params">a, b</span>) {</span><br><span class="line"> <span class="keyword">return</span> a + b;</span><br><span class="line">}</span><br></pre></td></tr></table></figure><p>sum.js</p><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></pre></td><td class="code"><pre><span class="line"><span class="keyword">const</span> add=<span class="built_in">require</span>(<span class="string">'./add.js'</span>);</span><br><span class="line"></span><br><span class="line"><span class="built_in">exports</span>.<span class="property">sum</span>=<span class="keyword">function</span>(<span class="params">x,y</span>) {</span><br><span class="line"> <span class="keyword">return</span> <span class="title function_">add</span>(x, y);</span><br><span class="line">}</span><br></pre></td></tr></table></figure><h2 id="總結"><a href="#總結" class="headerlink" title="總結"></a>總結</h2><p>與Webpack相比,Parcel的生態和功能有限,較難進行進階的設置。因此,在選擇使用Webpack還是Parcel時,需要根據具體需求和技術做出選擇。如果是在簡單項目中快速構建和開發,Parcel可能是一個不錯的選擇;如果需要更高度的客製化和擴展性,Webpack可能更符合需求。</p><h2 id="參考資料"><a href="#參考資料" class="headerlink" title="參考資料"></a>參考資料</h2><p><a href="https://parceljs.org/">Parcel</a></p>]]></content>
<categories>
<category> Frontend </category>
</categories>
<tags>
<tag> Frontend </tag>
<tag> Parcel </tag>
</tags>
</entry>
<entry>
<title>(技術)30秒解決Dcard彈跳視窗</title>
<link href="/(%E6%8A%80%E8%A1%93)30%E7%A7%92%E8%A7%A3%E6%B1%BADcard%E5%BD%88%E8%B7%B3%E8%A6%96%E7%AA%97/"/>
<url>/(%E6%8A%80%E8%A1%93)30%E7%A7%92%E8%A7%A3%E6%B1%BADcard%E5%BD%88%E8%B7%B3%E8%A6%96%E7%AA%97/</url>
<content type="html"><![CDATA[<h2 id="可以不要一直叫我登入嗎"><a href="#可以不要一直叫我登入嗎" class="headerlink" title="可以不要一直叫我登入嗎"></a>可以不要一直叫我登入嗎</h2><p>有時在網路上看到有趣的 Dcard 文章,好奇點進去,看留言時卻跳出討厭的登入視窗,這篇文章會示範如何用開發者工具在 30 秒內關閉</p><ol><li><p>點擊 F12,開發者工具<br><img src="/images/dcard/page.jpg"></p></li><li><p>找到彈跳視窗根元素(最外層,屬性 tabindex=”0”),點滑鼠右鍵,刪除元素,這時候就可以看到乾淨漂亮的頁面了~但是還是不能滾動<br><img src="/images/dcard/root-element.jpg"></p></li><li><p>往上滑找到 body 元素,element 屬性加上 overflow:scroll<br><img src="/images/scroll.jpg"></p></li><li><p>大功告成,不需要打帳密了</p></li></ol><h2 id="全自動執行"><a href="#全自動執行" class="headerlink" title="全自動執行"></a>全自動執行</h2><p>做成 Chrome Extension,這裡提供思路,封裝實作可以參考<a href="https://ithelp.ithome.com.tw/articles/10186017">這篇文章</a></p><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></pre></td><td class="code"><pre><span class="line"><span class="variable language_">window</span>.<span class="title function_">addEventListener</span>(<span class="string">'load'</span>, <span class="keyword">function</span>(<span class="params"></span>) {</span><br><span class="line"> <span class="keyword">const</span> popup = <span class="variable language_">document</span>.<span class="title function_">getElementById</span>({modal--id});</span><br><span class="line"> <span class="keyword">if</span> (popup) {</span><br><span class="line"> popup.<span class="title function_">remove</span>();</span><br><span class="line"> <span class="variable language_">document</span>.<span class="property">body</span>.<span class="property">style</span>.<span class="property">overflow</span> = <span class="string">'scroll'</span>;</span><br><span class="line"> }</span><br><span class="line">});</span><br></pre></td></tr></table></figure><h2 id="免責聲明"><a href="#免責聲明" class="headerlink" title="免責聲明"></a>免責聲明</h2><p>本文僅為客戶端提供教學示範之用,請勿用於任何影響網頁正常運作的技術,否則將自行承擔相應法律責任。</p>]]></content>
<categories>
<category> Frontend </category>
</categories>
<tags>
<tag> Frontend </tag>
</tags>
</entry>
<entry>
<title>(技術)製作自動排程的YoubikeLineBot</title>
<link href="/(%E6%8A%80%E8%A1%93)%E8%A3%BD%E4%BD%9C%E8%87%AA%E5%8B%95%E6%8E%92%E7%A8%8B%E7%9A%84YoubikeLineBot/"/>
<url>/(%E6%8A%80%E8%A1%93)%E8%A3%BD%E4%BD%9C%E8%87%AA%E5%8B%95%E6%8E%92%E7%A8%8B%E7%9A%84YoubikeLineBot/</url>
<content type="html"><![CDATA[<h2 id="關於騎腳踏車上班"><a href="#關於騎腳踏車上班" class="headerlink" title="關於騎腳踏車上班"></a>關於騎腳踏車上班</h2><p>Youbike 通勤上下班,趕到公司樓下卻發現沒有空位,只能花費雙倍路程時間步行到上一站,搜尋可行的解決方案,別人製作的 <a href="https://www.youbike.com.tw/region/main/stations/">站點地圖</a>是不錯的解決方案,但對壓線出門的懶人不是最佳解,<strong>重複的查詢、比較、紀錄</strong>相當多餘,真正能解決痛點的是<strong>固定時間、主動通知、快速查詢</strong>工具。<br>以 Node.js開發的 bot,邏輯在<a href="https://github.com/chienniman/YouBikeNotify-Bot/blob/main/index.js">index.js</a>,<a href="https://github.com/chienniman/YouBikeNotify-Bot">完整原始碼</a>。</p><h2 id="特點"><a href="#特點" class="headerlink" title="特點"></a>特點</h2><ul><li><code>自動化查詢</code></li><li><code>部署Render雲服務</code></li><li><code>排程每日通知</code></li></ul><p><img src="/images/youbikeLinebot/ubike-robot-result.webp"></p><h2 id="SDK"><a href="#SDK" class="headerlink" title="SDK"></a>SDK</h2><p>其他語言參考<a href="https://developers.line.biz/en/docs/downloads/">Official SDKs</a>,官方提供</p><ul><li>Java</li><li>PHP</li><li>Go</li><li>Perl</li><li>Ruby</li><li>Python</li><li>Node.js</li></ul><h2 id="本地"><a href="#本地" class="headerlink" title="本地"></a>本地</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">git clone https://github.com/chienniman/YouBikeNotify-Bot.git</span><br></pre></td></tr></table></figure><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install</span><br></pre></td></tr></table></figure><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">mkdir .env</span><br></pre></td></tr></table></figure><p><strong>環境變數&金鑰</strong><br><img src="/images/youbikeLinebot/config.jpg"></p><h2 id="Cron"><a href="#Cron" class="headerlink" title="Cron"></a>Cron</h2><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">npm install --save node-cron</span><br></pre></td></tr></table></figure><p><img src="/images/youbikeLinebot/cron.jpg"></p><h2 id="臺中交通資訊-API"><a href="#臺中交通資訊-API" class="headerlink" title="臺中交通資訊 API"></a>臺中交通資訊 API</h2><p>上網搜了一下發現臺中交通資訊 API 整合的相當不錯,Swagger 的文件架構清晰,井然有序,這邊給個讚,<del>台中路面狀況如果也可以就謝天謝地了</del>。<br><a href="https://motoretag.taichung.gov.tw/DataAPI/swagger/ui/index#/YoubikeAPI">臺中交通資訊 API</a><br><img src="/images/youbikeLinebot/youbike-api.jpg"><br><img src="/images/youbikeLinebot/query-ubike.jpg"></p><h3 id="LINE-Developers"><a href="#LINE-Developers" class="headerlink" title="LINE Developers"></a>LINE Developers</h3><p>首先要先創建一個 LINE Developers 帳號<br><a href="https://developers.line.biz/en/">註冊網址</a></p><h3 id="LINE-Bot-channel"><a href="#LINE-Bot-channel" class="headerlink" title="LINE Bot channel"></a>LINE Bot channel</h3><p>登入後點選 Create new channel 創建新的 LINE Bot 頻道,並且填寫頻道相關資訊(例如:頻道名稱、頻道圖片、類型等等)。<br><img src="/images/youbikeLinebot/channel.jpg"></p><h2 id="ngrok"><a href="#ngrok" class="headerlink" title="ngrok"></a>ngrok</h2><blockquote><p>ngrok 做為一個轉發的伺服器,他可以把外界的請求轉發到你指定的 Port,使用的背景原理是連接到 ngrok 雲端伺服器,將你本機指定的地址公開,再將由 ngrok 一串公開的網址來存取內容。他的優點是快速而且還提供了 https 的服務讓你使用上更安全,甚至你還可以設置密碼保護。</p></blockquote><p><a href="https://ithelp.ithome.com.tw/articles/10197345">ref-[Day-37] 使用 ngrok 讓外網連接你的 API</a></p><h3 id="安裝"><a href="#安裝" class="headerlink" title="安裝"></a>安裝</h3><p><a href="https://ngrok.com/">ngrok</a></p><h3 id="執行"><a href="#執行" class="headerlink" title="執行"></a>執行</h3><p><code>windows,雙擊 exe</code></p><p><code>linux, cd ngrok</code></p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">ngrok.exe http {port}</span><br></pre></td></tr></table></figure><h3 id="映射"><a href="#映射" class="headerlink" title="映射"></a>映射</h3><figure class="highlight plaintext"><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">Forwarding https://xxxxxx.ngrok.io -> localhost:{port}</span><br></pre></td></tr></table></figure><h3 id="資安"><a href="#資安" class="headerlink" title="資安"></a>資安</h3><p>沒有正確地設定 ngrok,防火牆、密碼,可能導致安全風險,使用完記得<code>ctrl+c</code>退出</p><h3 id="驗證失敗"><a href="#驗證失敗" class="headerlink" title="驗證失敗"></a>驗證失敗</h3><p>ngrok 運行 500,terminal 顯示 404,因為 token 沒設定好<br><img src="/images/youbikeLinebot/500.jpg"></p><p><img src="/images/youbikeLinebot/404.jpg"></p><h2 id="部署雲端"><a href="#部署雲端" class="headerlink" title="部署雲端"></a>部署雲端</h2><blockquote><p>官方文件<a href="https://github.com/haojiwu/line-bot-nodejs-on-render">nodejs-on-rende</a></p></blockquote><p>1.設定<a href="https://github.com/chienniman/YouBikeNotify-Bot/blob/main/render.yaml">render.yaml</a><br>2.新增 Web Service<br>3.Public Git repository<br>4.設定姓名、環境、區域<br>5.編譯部屬成功<br><img src="https://user-images.githubusercontent.com/97031067/223740969-e16e8586-e53b-491b-9caf-0eee42233eaa.jpg" alt="deploy-success"></p><h2 id="免費限制"><a href="#免費限制" class="headerlink" title="免費限制"></a>免費限制</h2><blockquote><p>Free instance types are not available for Private Services, Background Workers, or Cron Jobs.<br><br>Web Services on the free instance type are automatically spun down after 15 minutes of inactivity. When a new request for a free service comes in, Render spins it up again so it can process the request.<br>This can cause a response delay of up to 30 seconds for the first request that comes in after a period of inactivity.<br></p></blockquote><div class="note warning no-icon flat"><ul><li>本地伺服器可自動排程,但 render 雲的免費計畫不支援 </li><li>超過 15 分鐘沒有活動,伺服器會自動停止,直到新的請求,造成延遲響應。</li></ul></div><h2 id="心得"><a href="#心得" class="headerlink" title="心得"></a>心得</h2><p>youbike 地圖相當方便,但是查詢、紀錄、比較等重複性工作仍可優化,都說科技始終來自惰性,有了排程查詢機器人後只需要被動等待通知,但缺點也是相當明顯,不穩定的響應(1 秒~6 分鐘),注定讓免費計畫只能作為實驗用途,很少使用者能接受超過 5 秒的等待,會不會升級成付費版本目前還在觀察中。</p>]]></content>
<categories>
<category> Line API </category>
</categories>
<tags>
<tag> Backend </tag>
<tag> LineBot </tag>
<tag> Line API </tag>
<tag> Youbike API </tag>
<tag> render </tag>
</tags>
</entry>
<entry>
<title>(技術)淺談伺服器的授權、驗證</title>
<link href="/(%E6%8A%80%E8%A1%93)%E6%B7%BA%E8%AB%87%E4%BC%BA%E6%9C%8D%E5%99%A8%E7%9A%84%E6%8E%88%E6%AC%8A%E3%80%81%E9%A9%97%E8%AD%89/"/>
<url>/(%E6%8A%80%E8%A1%93)%E6%B7%BA%E8%AB%87%E4%BC%BA%E6%9C%8D%E5%99%A8%E7%9A%84%E6%8E%88%E6%AC%8A%E3%80%81%E9%A9%97%E8%AD%89/</url>
<content type="html"><![CDATA[<h2 id="Authentication"><a href="#Authentication" class="headerlink" title="Authentication"></a>Authentication</h2><p><code>驗證</code>,告訴伺服器登入者是其所聲稱的使用者,以遊戲登入舉例</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line">+------------------------+ </span><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">+-----------v------------+ </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">+-----------v------------+ </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">+-----------v------------+ </span><br><span class="line">| 排隊進入遊戲 | </span><br><span class="line">+------------------------+ </span><br><span class="line"></span><br></pre></td></tr></table></figure><h2 id="Authorization"><a href="#Authorization" class="headerlink" title="Authorization"></a>Authorization</h2><p>當玩家通過<code>驗證</code>進入遊戲伺服器後,伺服器會根據玩家的帳戶資料進行<code>授權</code>,假設想要2023的年槍,紫炫流光,就得向伺服器獲得<code>授權</code>,買解碼器、黑市,才能解鎖新武器。</p><p>簡單舉例</p><figure class="highlight plaintext"><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><br></pre></td></tr></table></figure><p>每個玩家客戶端都有全部種類的武器,來自於每次的更新檔,是為了提升遊戲體驗,總不能撿到新槍再下載吧,因此<code>授權</code>只是向伺服器請求,解鎖不能使用的武器。</p><h2 id="Https-Authentication-Basic"><a href="#Https-Authentication-Basic" class="headerlink" title="Https Authentication(Basic)"></a>Https Authentication(Basic)</h2><p>一種<a href="https://learn.microsoft.com/zh-tw/dotnet/framework/wcf/feature-details/understanding-http-authentication">HTTP驗證機制</a>,Base64將用戶名和密碼進行編碼,然後在HTTP請求中以Authorization標頭的形式傳送。簡單來說,當使用者輸入用戶名和密碼時,這些數據將被編碼並包含在HTTP請求中,伺服器收到請求後會解碼這些數據並進行身份驗證。</p><p><img src="/images/serverAuth/basic-auth.jpg"></p><h2 id="jigsaw-demo"><a href="#jigsaw-demo" class="headerlink" title="jigsaw demo"></a>jigsaw demo</h2><p><a href="https://jigsaw.w3.org/HTTP/">jigsaw.w3.org測試網址</a></p><p><img src="/images/serverAuth/auth-login.jpg"></p><figure class="highlight plaintext"><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">ac:guest</span><br><span class="line">pw:guest</span><br></pre></td></tr></table></figure><ul><li>伺服器檢查在<code>Header</code>裡的<code>Authorization</code>欄位,規格應為 <code>Authorization: Basic <value></code></li><li>此時因為沒有<code>Authorization</code>並沒有資料,server按照約定會回傳<code>401</code> status code並在Header上加上 <code>WWW-Authenticate: Basic realm="<value>"</code></li><li>client當發現得到以上的回應後,會出現一個給予使用者輸入用戶名稱及密碼的地方</li><li>client將用戶名稱跟密碼做成<code>base64(username:password)</code></li><li>client將資料放到<code>Header</code>: <code>Authorization: base64(username:password)</code></li></ul><p><a href="https://ithelp.ithome.com.tw/articles/10304135">先生你誰?-身分驗證Authentication (Basic, token, JWT)</a><br><img src="/images/serverAuth/auth-success.jpg"></p><p>把header的authentication取出base64解碼可以看到正好是輸入的帳密</p><figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">base64(username:password)</span><br></pre></td></tr></table></figure><p><img src="/images/serverAuth/base64.jpg"></p><h2 id="Digest:"><a href="#Digest:" class="headerlink" title="Digest:"></a>Digest:</h2><blockquote><p>摘要訪問認證是一種協議規定的Web伺服器用來同網頁瀏覽器進行認證信息協商的方法。它在密碼發出前,先對其應用哈希函數,相對於HTTP基本認證發送明文而言,更安全。<br><a href="HTTP%E6%91%98%E8%A6%81%E8%AA%8D%E8%AD%89">https://zh.wikipedia.org/zh-tw/HTTP%E6%91%98%E8%A6%81%E8%AE%A4%E8%AF%81</a></p></blockquote><ul><li>客戶端向服務器發送請求。</li><li>服務器回復401和WWW-Authenticate,nonce(服務器生成的隨機字符串,防止重放攻擊)。<figure class="highlight plaintext"><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">www-authenticate: </span><br><span class="line">Digest realm="test", </span><br><span class="line">domain="/HTTP/Digest", </span><br><span class="line">nonce="e67010901fb034b2e0e0c9e0c1f451d8"</span><br></pre></td></tr></table></figure></li><li>客戶端使用用戶名、領域和密碼計算出HA1值,使用請求方式和請求URI計算出HA2值。</li><li>客戶端使用HA1、nonce和HA2計算出響應值,加到“Authorization”的header。<figure class="highlight plaintext"><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">HA1 = MD5(username:realm:password)</span><br><span class="line">HA2 = MD5(method:digestURI)</span><br><span class="line">response = MD5(HA1:nonce:HA2)</span><br></pre></td></tr></table></figure></li><li>服務器使用相同的計算方式驗證。如果正確,服務器會返回請求的資源,否則,返回401未授權或其他錯誤狀態碼,客戶端必須重新進行身份驗證。</li></ul>]]></content>
<categories>
<category> Backend </category>
</categories>
<tags>
<tag> Backend </tag>
<tag> Authentication </tag>
<tag> Authorization </tag>
</tags>
</entry>
<entry>
<title>(心得)考取AZ-900心得分享</title>
<link href="/(%E5%BF%83%E5%BE%97)%E8%80%83%E5%8F%96AZ-900%E5%BF%83%E5%BE%97%E5%88%86%E4%BA%AB/"/>
<url>/(%E5%BF%83%E5%BE%97)%E8%80%83%E5%8F%96AZ-900%E5%BF%83%E5%BE%97%E5%88%86%E4%BA%AB/</url>
<content type="html"><![CDATA[<div class="note info no-icon flat"><p>筆者於2022/10/29通過<a href="https://learn.microsoft.com/zh-tw/certifications/exams/az-900/">AZ900</a>,在此分享,先前在FB看到大推Azure廣告,本身雖以軟體開發為主,但對雲端也深感興趣。</p></div><h2 id="流程"><a href="#流程" class="headerlink" title="流程"></a>流程</h2><p>1.聽完線上講座免費拿考試卷 / 自費購買($75美元,印象中)<br>2.報名線上/實體,自己是去聯成電腦考試<br>3.考試前要先拍證件照<br>4.被帶進小房間考試,全程後面有考官盯著<br>5.印象中寫了30分鐘就交了,當場就知道分數</p><h2 id="如何準備"><a href="#如何準備" class="headerlink" title="如何準備"></a>如何準備</h2><p>1.寫考古題再去背概念(畫心智圖)<br>2.youtube/微軟 Doc 掃一次<br>3.英文準備</p><h2 id="範例"><a href="#範例" class="headerlink" title="範例"></a>範例</h2><p>考題幾乎都是一個概念的比較,例如混合雲、公共雲、私有雲差別應用,很快就能判斷,但是<br>中英文翻譯落差,第一眼看到題目可能會愣住,因此建議讀文件&考古都使用英文</p><h2 id="選擇題-官方例題"><a href="#選擇題-官方例題" class="headerlink" title="選擇題-官方例題"></a>選擇題-官方例題</h2><p>組織會使用哪一種雲端方法來充分利用內部部署技術投資,並在兩個環境之間共用資料和應用程式?</p><p>A. 公用雲端<br>B. 私人雲端<br>C. 混合式雲端<br>D. 內部部署資料中心</p><h3 id="混合雲:"><a href="#混合雲:" class="headerlink" title="混合雲:"></a>混合雲:</h3><p>控制——您的組織可以為需要低延遲的敏感資產或工作負載維護私有基礎架構。<br>靈活性——您可以在需要時利用公共雲中的額外資源。<br>成本效益——通過擴展到公共雲的能力,您只需在需要時為額外的計算能力付費。<br>輕鬆— 過渡到云不必費力,因為您可以逐步遷移 — 隨著時間的推移逐步分階段遷移工</p><h3 id="公共雲"><a href="#公共雲" class="headerlink" title="公共雲"></a>公共雲</h3><p>公共雲是最常見的雲計算部署類型。雲資源(如服務器和存儲)由第三方雲服務提供商擁有和運營,並通過互聯網交付。使用公共雲,所有硬件、軟件和其他支持基礎設施都由雲提供商擁有和管理。Microsoft Azure 是公共雲的一個示例。</p><p>在公共雲中,您與其他組織或云“租戶”共享相同的硬件、存儲和網絡設備,並使用 Web 瀏覽器訪問服務和管理您的帳戶。公共雲部署經常用於提供基於 Web 的電子郵件、在線辦公應用程序、存儲以及測試和開發環境。</p><p>優勢:<br>降低成本——無需購買硬件或軟件,您只需為使用的服務付費。<br>無需維護——您的服務提供商提供維護。<br>近乎無限的可擴展性——按需資源可滿足您的業務需求。<br>高可靠性——龐大的服務器網絡確保不會出現故障。</p><p>私有云由一個企業或組織專門使用的雲計算資源組成。私有云可以物理地位於您組織的現場數據中心,也可以由第三方服務提供商託管。但在私有云中,服務和基礎設施始終在私有網絡上維護,硬件和軟件專門用於您的組織。</p><p>通過這種方式,私有云可以讓組織更輕鬆地自定義其資源以滿足特定的 IT 要求。私有云通常被政府機構、金融機構和任何其他具有關鍵業務運營的中大型組織所使用,這些組織尋求增強對環境的控制。</p><h3 id="私有雲:"><a href="#私有雲:" class="headerlink" title="私有雲:"></a>私有雲:</h3><p>更大的靈活性——您的組織可以自定義其云環境以滿足特定的業務需求。<br>更多控制——資源不與他人共享,因此可以實現更高級別的控制和隱私。<br>更高的可擴展性——與本地基礎設施相比,私有云通常提供更高的可擴展性。</p><h3 id="解答"><a href="#解答" class="headerlink" title="解答"></a>解答</h3><p>答案是 C. 混合式雲端。</p><h3 id="推薦資源"><a href="#推薦資源" class="headerlink" title="推薦資源"></a>推薦資源</h3><p><a href="https://www.examtopics.com/exams/microsoft/az-900/?utm_source=adwords&utm_medium=search&utm_campaign=search&gclid=Cj0KCQiArsefBhCbARIsAP98hXRP5CThqFMLKuvuH759u4ZnOgALUdZS6nWdn6bWJ2HoT6ru0GlFY1QaAtL1EALw_wcB">Microsoft AZ-900 Exam免費考古題</a></p><h2 id="總結"><a href="#總結" class="headerlink" title="總結"></a>總結</h2><p>AZ-900都是以簡單快速記憶為主,不需要深度記憶與推理,廣度大於深度,快速掃過的效益比才是最高的,時間不夠可以直接刷考古題,不建議找太舊的。</p><p>可參考當次的<a href="https://query.prod.cms.rt.microsoft.com/cms/api/am/binary/RE3VwUY">考試指南</a>,這樣比較有方向,網路考古題有些答案是錯的,而且分歧極大,遇到這種題目都建議直接找官方文檔。</p><p>不過要是像我一樣前天晚上才準備了話建議是直接pass,還記得走出考場的時候只花了一半時間,壓線通過,監考官還疑惑地問說今天怎麼這麼多人都來考,完成後必須在登記表上<br>簽退,掃了一下當天大概有4個來考,並不是每一位都通過。</p><p><a href="https://azure.microsoft.com/en-gb/resources/cloud-computing-dictionary/what-is-iaas/#faq">https://azure.microsoft.com/en-gb/resources/cloud-computing-dictionary/what-is-iaas/#faq</a></p>]]></content>
<categories>
<category> Diary </category>
</categories>
<tags>
<tag> AZ-900 </tag>
</tags>
</entry>
</search>