🔍 搜尋結果:codeigniter

🔍 搜尋結果:codeigniter

回應網友提問:我是新手前端,公司叫我學一點 php + laravel 串 API,該從哪邊學起呢?

昨天在我們新手寫程式 LINE 群組,有幾個業界工程師&剛轉職的新手在討論: 我是新手前端,公司叫我學一點 php + laravel 串 API,該從哪邊學起呢? https://line.me/ti/g2/nipkjq2WoZPKX5dTn9tE9266aEOt6EOICFGa1g 這主題很好,我決定單獨寫一篇文章討論這件事情 --- 我猜你面臨的情況,老闆不是真的叫你從無到有寫後端,應該是去硬改現成的後端專案 因為是公司馬上需要的,先求速成為主,背後細節就先別管了 就分幾個步驟來做吧 # Step 1 laravel 官網 `Installation` 章節讀一讀,然後看你用什麼作業系統,網路上 laravel 安裝教學找幾份試試看 先想辦法把環境跑起來,讓目前專案可以在電腦上跑 然後找一款有 GUI(圖形化介面)的資料庫管理軟體,在 UI 上點一點,準備好資料庫 # Step 2 `Routing` `Controllers` `Requests` `Responses` 這幾個章節讀一讀 至少稍微看懂,後端是哪些地方在接收參數、回應參數 # Step 3 把 `Eloquent ORM` 章節讀一讀,這個類別提供很多神奇的方法,很輕易就能做到 CRUD 至少稍微看懂,後端是哪些地方在跟資料庫互動,自己有辦法新增資料、更新資料、刪除資料這樣 --- 除此之外,上網找幾份 laravel 的簡易 CRUD 範例教學,不太懂背後原理沒關係,按照指示,做個部落格之類的 然後就去硬改公司現成的後端專案,頂著用,不然短期內也沒辦法真的學精 laravel,就先這樣吧!先能滿足公司需求就好! 其實,以上所說,真的是很混的學習方法:ORM 背後的觀念、資料庫的 SQL 觀念,幾乎都沒學到 長遠來說,如果是真的要學 php + laravel 後端,我都是建議先從「純 php + mysql」開始學起 也就是我鼓勵新手用純 php 寫一個部落格網站,寫純 SQL 去連接資料庫,先搞懂這種最純粹的寫法 然後再開始學 laravel 以及 ORM 等等好用套件工具 不然的話,我知道很多人直接從 laravel 開始寫起,半知半解,工作很久了,卻連哪些功能是 php 提供的,哪些是 laravel 提供的都分不出來 然後在需要換框架 比如 CodeIgniter 或者 Yii 的時候,很多觀念無法融會貫通,長遠來說,根本事半功倍 --- 話說回來,如果老闆不是叫你硬改現成的後端專案,而是叫你從無到有寫後端 那這工作內容實在不太合理,除非你一開始應徵的就是「全端工程師」的職缺&薪資 以上,簡單幾個方向分享,希望對你有點幫助!

Composer 進階原理:PHP命名空間與PSR-0

上次的說明了PHP套件管理的歷史與社群提出的解決之道,本篇文章接著談類別管理的進階議題。 # 當類別名稱一樣... 當專案大了起來,有時候會有類別名稱重複的問題。 假設今天要撰寫一個論壇模組,提供討論區與留言板功能。 你一定很想將討論區的文章與留言板的文章都命名類別為Article: ``` // BoardArticle.php <?php class Article{ //... } ?> // ForumArticle.php <?php class Article{ //... } ?> ``` 當然了,這麼做會得到一個結果: ``` Fatal error: Cannot redeclare class Article ``` 這種問題有一個簡單的解決辦法,就是加上前綴字。 類別分別命名為ForumArticle與BoardArticle就可以了。 *Q1: 等一下!這個解法好陽春!我看到至少4個問題:* 1. 類別名稱容易變得冗長。 2. 有些類別一開始你以為不會跟人重複,結果之後真的重複了。難道永遠替類別加前綴字? 3. 類別名稱寫Article俐落多了!文章就是概念上的文章,不要逼我告訴你是討論區還是留言板!如果專案用到兩種留言板模組,分別由以前的兩個前輩寫好,難道還要逼我把作者名稱寫進去? ``` class TonyBoardArticle{ //... } class JackBoardArticle{ //... } ``` 4. 如果我在打造框架(framework)呢?幾乎會把所有常見名詞用過一次(像是Request、Loader、Response、Controller、Model等類別)!難道前面全部前綴? 看看 Codeigniter 的原始碼,全部用CI_當作前綴。超醜的。 # 命名空間(namespace)登場 於是PHP從5.3版之後支援了命名空間(namespace)。 所以可以用Article替類別定義了: ``` // BoardArticle.php <?php namespace Board; class Article{ //... } ?> // ForumArticle.php <?php namespace Forum; class Article{ //... } ?> ``` 使用類別時只要加上命名空間即可: ``` //index.php <?php include 'BoardArticle.php'; include 'ForumArticle.php'; $article = new Forum\Article(); $post = new Board\Article(); ``` 如果當前的php檔只用到其中一個Article類別,可以指定當前的php檔只用哪個命名空間+類別的組合: ``` <?php include 'BoardArticle.php'; include 'ForumArticle.php'; use Forum\Article; $article = new Article(); $fArticle = new Forum\Article(); $bArticle = new Board\Article(); ``` 如此一來,當php找不到Article類別時,便會去使用use關鍵字宣告的組合。 當然了,就算用use指定過,原本的宣告方式還是可以用的。(如最下方兩行所示) # 當東西多了起來... OK,可以繼續完成我們的論壇模組了! 討論區跟留言板有各自的文章,再來還需要「推文」: ``` <?php namespace Board; class Comment{ // ... } ?> <?php namespace Forum; class Comment{ // ... } ?> ``` 使用剛剛學到的命名空間去載入他們: ``` <?php // index.php include 'BoardArticle.php'; include 'ForumArticle.php'; include 'BoardComment.php'; include 'ForumComment.php'; $article = new Forum\Article(); $comment = new Forum\Comment(); // ... ``` 果然是漂亮的各種命名阿! *Q2: include有好多行!上次提到了Composer可以解決這種問題,當引入命名空間之後,Composer也能發揮作用嗎?* **是的。** # Composer登場 跟上次初學Composer一樣,建立一個composer.json檔: ``` { "autoload": { "files": [ "ForumArticle.php", "ForumComment.php", "BoardArticle.php", "BoardComment.php" ] } } ``` 注意,上次我們用"classmap"指定資料夾、把資料夾內檔案全掃一次,這次我們用"files"分別設定各個檔案。 再來,在terminal輸入 ``` composer install ``` 執行完畢之後,跟上次一樣,只要載入一個檔案: ``` <?php require 'vendor/autoload.php'; $article = new Forum\Article(); $comment = new Forum\Comment(); ``` 就可以使用各個類別囉! *Q3: 等一下!看起來跟沒有命名空間的時候差不多啊!一樣是把php檔自動require進去而已?* 對啊,你最上面的原始寫法,也只是手動載入好幾個檔案,在載入的時候本來就沒有特別之處: ``` <?php // index.php include 'BoardArticle.php'; include 'ForumArticle.php'; include 'BoardComment.php'; include 'ForumComment.php'; $article = new Forum\Article(); $comment = new Forum\Comment(); // ... ``` 載入php檔就只是載入,跟命名空間是兩回事。 *Q4: 還是不太對啊!上次我用classmap一次把好幾個資料夾內容掃過,這次我用files分別指定每個檔案幹嘛?Composer不是厲害在能指定資料夾去自動掃過?* ......你說的沒錯。 開個my_lib資料夾,把4個php檔都丟進去吧。composer.json這樣寫就好了: ``` { "autoload": { "classmap": [ "my_lib" ] } } ``` 再來,在terminal輸入 ``` composer install ``` 這樣就搞定了! 其實我只是想示範,除了用classmap設定資料夾之外,也可以用files直接指定檔案。 *Q5: OK,原諒你。不過,我必須說,我今天什麼都沒學到。最後還是在composer.json寫classmap而已,跟上次一模一樣。* 是的...我剛說了,載入php檔就只是載入,跟命名空間是兩回事。 我今天介紹的namespace功能是PHP本身提供的。而Composer只是協助你載入的工具、當然不可能改變程式語言本身。 Composer只是幫助你少打那一串require而已。 *Q6: ㄟ等等...有個地方我覺得很醜。我們現在的my_lib資料夾裏面有4個檔案,檔名很醜:* ``` "ForumArticle.php" "ForumComment.php" "BoardArticle.php" "BoardComment.php" ``` 類別名稱本身都是俐落的Article跟Comment了,檔案名稱還是有前綴字。但也不可能有兩個Article.php、兩個Comment.php。你有沒有辦法解決這個美感問題? 這個問題簡單,把那個my_lib資料夾刪掉,開一個Forum資料夾、一個Board資料夾。本來的ForumArticle.php改成Article.php丟進Forum資料夾、本來的BoardArticle.php改成Article.php丟進Board資料夾。composer.json改寫成這樣: ``` { "autoload": { "classmap": [ "Board", "Forum" ] } } ``` 再來,在terminal輸入 ``` composer install ``` 這招不錯吧!檔案名稱就是類別名稱,乾淨俐落! 而且資料夾的名字本身就是namespace的名稱! 以後都這樣做啦!一用到命名空間就開個同名資料夾把檔案丟進去! *Q7: 這招我覺得還好耶...。本來檔案都放在my_lib,我在composer.json只要填my_lib一行就好,現在變成要填兩行。要是我這個論壇模組有一大堆類別、用了一大堆命名空間呢?那我classmap底下不就要填入好幾行?那我寧可全部丟進my_lib,只填my_lib一行!* 唔,這樣說也是有道理。那重新建立my_lib資料夾,把Board跟Forum資料夾丟進my_lib資料夾。 composer.json改回這樣寫: ``` { "autoload": { "classmap": [ "my_lib" ] } } ``` 再來,在terminal輸入 ``` composer install ``` classmap不只是告訴Composer去載入哪幾個資料夾內的檔案,還會把資料夾內的資料夾也全部掃過一次。 怎麼樣,Composer夠神吧。 *Q8: 原來classmap底下會遞迴掃描下去...。我決定了,我的Forum跟Board都是在提供線上討論功能,我決定替我這個模組命名為Discussion。我要在my_lib底下開Discussion資料夾,然後把原本的Forum跟Board資料夾都丟進去。你覺得這個想法如何?* 還不錯。一個Discussion資料夾就是你的整個Discussion模組。 提供了討論區、留言板功能的Discussion模組,我喜歡。 *Q9: 好像忘了什麼...。啊,剛剛說命名空間跟檔案結構符合會最漂亮。那我要把那4個檔案的namespace改成這樣:* ``` <?php namespace Dicussion/Forum; class Article{ //... } ``` 剛剛說了,載入檔案就只是載入檔案,跟命名空間無關。 現在檔案結構沒變,所以我應該不用重新輸入composer install。 讓我試試...。 靠!怎麼噴error了!你騙我? ``` Fatal error: Class 'Discussion\Forum\Comment' not found ``` 呃...,我前面的說法確實有點誤導。 PHP自動載入的基本函式長這樣: ``` void __autoload ( string $class ) ``` 如你所見,PHP至少需要Composer提供資訊指出$class該去哪個檔案找。 namespace改變之後,PHP會找不到對應的$class在哪。 所以還是輸入一下composer install吧!Composer會把需要的資訊整理好的。 *Q10: OKOK,我知道了,我駕馭這一切了。我覺得這個Dicsussion模組真的超屌的,不但命名空間漂亮,連檔案結構都漂亮。我要把這個Discussion資料夾整個丟給我朋友,他們公司最近需要論壇模組。* 讓我打電話給他...。 「什麼?你們已經做好半個論壇模組了?你只需要我模組的其中幾個功能?你們的模組也是放在Discussion資料夾?」 糟糕,資料夾名稱重複了!所以我的模組拿給別人還是有不相容的可能,怎麼辦? 沒有錯..還記得你Q1提到的第3個狀況嗎?確實有把作者名稱加進去的必要! 別怕,我教你。你開一個Tony資料夾,把整個Discussion資料夾丟進去。 接著所有檔案namespace改成像這樣: ``` <?php namespace Tony/Dicussion/Forum; class Article{ //... } ``` 要用的時候就這樣喔: ``` <?php require 'vendor/autoload.php'; $article = new Tony\Discussion\Forum\Article(); $comment = new Tony\Discussion\Forum\Comment(); ``` 是變得有點長啦。 但這下搞定了吧!作者名稱再撞到的話,就改個獨特的名稱就是了! # 終於。讓我們談談PSR-0 你一定常聽到PSR-0對吧! PSR-0是PHP跨框架相容性統一標準組織訂出來的自動載入慣例。 來談談PSR-0幾個最重要的要求吧! * 命名空間加上類別名稱一定要長這樣: ``` {vendor name}\{namespace}\{class name} ``` * 前面一定要是作者名稱 * 中間可以有任意層次的命名空間、最後是類別名稱。 * 中間任意層次的命名空間直接對應到檔案結構。 發現了嗎?在剛剛Q1~Q10的過程中,其實你已經把PSR-0學完了,連設計原理都一起搞懂了。 懂這些之後,你也可以做好自己的模組、發佈到 Packagist 給全世界透過composer下載、使用了! 最後,如果遵守psr-0的話,composer.json可以這樣寫: ``` { "autoload": { "psr-0": { "Tony\\Discussion\\": "my_lib/" } } } ``` 注意,雙引號、兩次反斜線並沒有特別意思,只是 json 規定的格式。 跟classmap一樣都可以完成任務。兩者其實是有差別的...,我們下次再談。 # 結語 Composer工具以及PHP-FIG組織的出現,讓一直以來散落各地的PHP社群開始有集中的趨勢。 換句話說,各社群終於能共享彼此的library了。 然而,如你所見,psr-0不但導致檔案結構容易變得深層,還要求檔案結構必須配合程式碼,這也招致了不少批評。 https://r.je/php-psr-0-pretty-shortsighted-really.html 除此之外,composer autoload內的classmap跟psr-0到底如何分工?效能差異又為何?這些問題也都還在爭論與驗證當中。 http://stackoverflow.com/questions/22803419/why-use-a-psr-0-or-psr-4-autoload-in-composer-if-classmap-is-actually-faster 不過,PSR-0在各框架已被廣泛支援,因此建議你還是需要有所瞭解。 # 最後... 現在已經出現psr-0的替代方案,稱為psr-4。 PSR-0從2014-10-21開始被註明為不建議使用。 至於PSR-4..我們下次再談。

MVC是一個巨大誤會

我是web工程師,從剛開始學MVC就深感困惑: - 怎麼每個地方說的MVC都不太一樣? - 有些文章講的MVC,跟我正在用的MVC,怎麼像完全不同的東西? Model、Controller、View三者到底如何互動?真是一個定義不明、含糊不清的名詞。 這讓我研究了很久。最後,發覺它是一個嚴重的誤會。 這個誤會導致了學習和溝通上的代價,請聽我娓娓道來。 # 哪些是MVC? web領域,不論前端(client-side)、後端(server-side)、不論什麼程式語言,幾乎所有framework都自稱、或被認為是「MVC」。 有哪些呢? 前端:Backbone.js、AngularJS、Ember.js… 後端:Ruby on Rails、CodeIgniter、Laravel、Django… 真的是這樣嗎?它們全都是MVC嗎? # MVC是什麼? 該怎麼定義MVC呢? 我們先來看看維基百科怎麼說: > MVC模式(Model-View-Controller)是軟體工程中的一種軟體架構模式,把軟體系統分為三個基本部分:模型(Model)、檢視(View)和控制器(Controller)。 嗯,跟大家說的一樣。我們繼續往下看: > 模型(Model) 用於封裝與應用程式的業務邏輯相關的資料以及對資料的處理方法。「 Model 」有對資料直接存取的權力,例如對資料庫的存取。「Model」不依賴「View」和「Controller」,也就是說, Model 不關心它會被如何顯示或是如何被操作。但是 Model 中資料的變化一般會通過一種重新整理機制被公布。為了實作這種機制,那些用於監視此 Model 的 View 必須事先在此 Model 上註冊,從而,View 可以了解在資料 Model 上發生的改變。(比較:觀察者模式(軟體設計模式)) 看起來有些陌生,整段描述跟你的web開發經驗完全不同,對嗎? 最大的疑問來自這句: > 那些用於監視此 Model 的 View 必須事先在此 Model 上註冊,從而,View 可以了解在資料 Model 上發生的改變。(比較:觀察者模式(軟體設計模式)) 後面直接叫你去看觀察者模式(observer pattern)。 問題來了:你有在view跟model之間實作observer pattern嗎? 也就是說,你的Model在資料改變之後,能主動通知View嗎? 沒有的話,就根本不符合MVC的定義。 # 全都不是MVC? 我們現在發現MVC有observer pattern這個必要條件了。 事情嚴重了起來。 client-side framework或許能夠符合這個條件。 以Backbone.js官網範例來說,我們可以這樣在Model上註冊: ``` book.on({ "change:title": titleView.update, "change:author": authorPane.update, "destroy": bookView.remove }); ``` 它的確實作了observer pattern。 但server-side framework呢? 你的Model如何能在發生改變之後去「主動通知」View? 你平常開發web哪有用到server push的技術? 所有server-side framework,從Ruby的Rails;PHP的CodeIgniter、Laravel;到Python的Django,他們全都不是MVC。 它們實作的,是昇陽電腦在1998年提出的「Model 2」。 # 什麼是Model 2? Model 2名氣不大,在維基百科連中文條目都沒有。我們看看英文條目怎麼講: > Model 2 is a complex design pattern used in the design of Java Web applications which separates the display of content from the logic used to obtain and manipulate the content. > In a Model 2 application, requests from the client browser are passed to the controller. The controller performs any logic necessary to obtain the correct content for display. 它針對web而設計,讓controller進行必要的程序之後,將資料塞進view去呈現。 正是我們server-side框架在做的事情。 也就是說,server-side目前只能實作Model 2;client-side可以實作Model 2,也可以實作MVC。 # 巨大的代價 web工程師最常碰的就是client-side跟server-side框架。結果整個業界把MVC跟Model 2混為一談,都說成MVC。 這帶來了什麼後果呢? MVC變成一個從初學者到業界工程師,永遠說不清楚、下不了定義的名詞。 這件事對於學習和討論,造成了非常巨大的成本。(參考下方的Q1和Q2) # 那該怎麼辦? 下次有初學者詢問「什麼是MVC」的時候,怎麼回答才不會害他回家之後「越查資料越混亂」? [Rails is not MVC](http://andrzejonsoftware.blogspot.tw/2011/09/rails-is-not-mvc.html)的作者提出了三種解決方法: > 第一個方法是聲稱MVC已經從原始意義改變了,Model 2也可以稱為MVC。如此一來,我們可以用「傳統MVC」或「真MVC」來描述原始的MVC。這是現在普遍的作法,但我不認為改變定義是一個好主意。這幾乎是越搞越亂。 > 第二個方法是到處推廣Rails其實是Model 2,MVC就留給…MVC吧。這很困難,但至少能保持定義不變。 > 第三個是直接忽略這些混亂。管它那麼多? 我個人覺得MVC這個詞已經沒救了,不管怎麼解釋都會帶給別人混亂。 當對方同時學習client-side跟server-side時,混亂更強烈。 我選擇這樣回答: 「MVC有分很多種喔!網路上全部沒寫清楚,你一定看不懂。 沒關係,你只要知道View可以抽出來就好。 C跟M先別管,你先隨便瞎搞吧。」 --- # Q&A ## Q1: 怎麼可能各大server-side framework都搞錯? 確實有人腦袋清醒得很,它就是Python的Django。 Django的官方文件內根本沒有「Controller」這個名詞。 看看Django官網的常見問題: > Q: Django似乎是一個MVC框架,但你們把Controller命名為「View」,把View命名為「Template」。你們幹嘛不用標準命名啊? > A: (前略)…如果你真的很想要一個縮寫,你就說Django是一個MTV框架吧。Model、Template、View。這樣分比較有道理些。 Django不想變成搞亂MVC的幫凶,只好委屈地又發明了一個名詞「MTV」。 ## Q2: 那client-side框架有受影響嗎? 有。client-side框架也必須為MVC巨大誤會浪費一堆時間解釋。 看看Backbone.js官網的常見問答: > Backbone跟「傳統MVC」的關聯何在? > …我們來比較一下Backbone跟像是Rails這種server-side MVC框架的差別… Backbone實作了「傳統MVC」,卻被迫用「傳統MVC」來描述server-side的Model 2,然後花一堆篇幅解釋。 ## Q3: 知道Model 2的存在又如何?我現在依然一片混亂! 沒錯,Model 2跟MVC都用到Model、Controller、View三個名詞,所以看起來類似。 但是,我們不應該再把時間花在思考「MVC怎麼如此難懂」。 我們討論的重點,應該是「如何分辨MVC與Model 2」、「在server-side如何實作Model 2才漂亮」、「在client-side實作MVC跟Model 2的優劣分別何在」。 ## Q4: 好,那你現在回答我,「如何分辨MVC與Model 2」? OK,就讓我拋磚引玉一下。 分別談談Model、View、Controller吧: ### View - Model 2: 不具有行為,只是等別人塞資料進去的模板(template)。 - MVC: 具有監視Model的行為,並以此去改變呈現(presentation)。 兩種View有沒有很像?跟張飛、岳飛一樣像。 看看Backbone.js官網的View範例。你server-side的View哪是長這樣? ``` var DocumentRow = Backbone.View.extend({ tagName: "li", className: "document-row", events: { "click .icon": "open", "click .button.edit": "openEditDialog", "click .button.delete": "destroy" }, initialize: function() { this.listenTo(this.model, "change", this.render); }, render: function() { ... } }); ``` ### Controller - Model 2: 接收請求與參數,轉交給Model處理,再把結果(最新的資料)塞進View。 - MVC: 接收請求與參數,轉交給Model處理。沒其他事了。 兩種Controller有沒有很像?跟小狗、熱狗一樣像。 MVC的View跟Model 2的Controller可能還比較像一點。(隨便說說,千萬別這樣類比。) ### Model - Model 2: 接收Controller傳來的參數,回傳結果。 - MVC: 接收Controller傳來的參數,將結果通知View。 Model倒是有些類似。 總之,Model 2跟MVC除了三個部份的名字一樣之外,沒什麼關聯了。 ## Q5: 我決定徹底鑽研MVC跟Model 2的定義了。給我一些延伸閱讀? http://www.ithome.com.tw/node/77330 http://andrzejonsoftware.blogspot.tw/2011/09/rails-is-not-mvc.html https://docs.djangoproject.com/en/1.7/faq/general/#django-appears-to-be-a-mvc-framework-but-you-call-the-controller-the-view-and-the-view-the-template-how-come-you-don-t-use-the-standard-names http://backbonejs.org/#FAQ-mvc https://r.je/views-are-not-templates.html --- ##一些社群的看法(2015-2-28) 附上幾個社群的連結,裡面有許多很棒的討論。 https://www.facebook.com/groups/javascript.tw/permalink/600136880087654/ https://www.facebook.com/groups/199493136812961/permalink/759391387489797/ https://www.facebook.com/groups/pythontw/permalink/10153760201638438/ https://www.facebook.com/mosky.liu/posts/10203964969186383 http://www.ithome.com.tw/voice/94877