Useful Unit Test
先不說要交出去的
這篇探討的是"怎麼用Unit Test"幫到自己
因此什麼理論什麼合理性,什麼覆蓋率請直接丟掉,至少對成品沒有直接幫助
以下以phpunit vs php開發為基準,java可能另有狀況,請勿直接當同一種
<請點選連結查看全文>
[轉貼推薦]請不要以為版權費就是智慧財產權全部了
http://world.yam.com/post.php?id=2988
"你有用到我的東西,所以你要直接付錢給我"
"你有看到了任何我的東西,所以你也要直接付錢給我"
"你引用了我太多的東西,所以你還是要繼續付錢給我"
版權,智慧財產權最近都旨在保護代理商就算了,整天聽他們說使用者付費實在煩
市場你創出來的嗎?,是否你也得付費給那整群幫你打廣告的源頭
而不是自己有東西被使用,被閱覽,就能不分青紅皂白地要求別人付費?
整天嚷著使用者付費原則,"如果這東西要我付費我也不會拒絕"的這些人,不妨先看看這篇文章
內容造假和內容有不當行為麻煩選一邊可以嗎?
內容造假,代表我認為這內容有問題,裡面完全不可信
這狀況不應該再繼續評論任何東西,因為都是假的
內容有不當行為,代表這內容是真的,我以這個內容是事實為基底
根據各種疑點質疑這內容敘述的事情已經造成哪些問題
沒人把兩件完全矛盾的事情湊在一起瞎扯淡自以為攻擊力變兩倍好嗎?
如果你智商低於100,可能需要往下看
內容造假代表裡面不當行為可能是假的,也可能是真的
你拿這種模稜量可的東西來討論真相?是否太過膚淺?
對,或許不是全部都假的,但你如果能準確地指出哪些是造假,還能順便指出那些內容真正描述不當
那麼你自己才是造假那個人吧...
一分鐘懂MockObject
function 外部Class A 裡面有function FA()可以拿到對應值
function 外部Class B 裡面有function FB()可以拿到對應值
我寫的class:
class Example(){
function getA(){
return new A->FA();
}
function getB(){
return new B->FB();
}
function mixData(){
$dataA = getA();
$dataB = getB();
return $dataA + $dataB
}
}
好了,假設這些ClassA ClassB是外部函數,也就是其他人開發的
那我們該怎測試才能確保自己的unit有正常運作呢?
class test_Example(){
funciton test_mixData(){
$mock = $this->getMock('Example');
$mock->method('getA')->willReturn('1');
$mock->method('getB')->willReturn('2');
$this->assertEquals(3, $mock->mixData());
}
}
一分鐘了,應該看懂在寫什麼了吧
看懂以後再看下面
在這樣的具體個案中,如果要確認Unit有沒有"正常運作"
最該care的是取得資料以後, "+ 有沒有執行,有沒有return"
而不該是"AB資料取得的值是否正確"
因此"對這個unit而言",我們不應該做類似以下事情:
"FA可能沒取到值,我們應該assert確認一下"
"FA是否是字串根本不能相加,我們要確定一下是否為浮點數"
這裡要鄭重說明一下,我們的目的終究是要確認這個unit有沒有正常運作
所以,如果你做了外來資料的過度判斷,而到時候又真的出錯了自己不在現場
如果是外來資料有問題,結果unit test檢測被其他人看到,恩經判斷期望結果不符
非常有可能會以為這是你的程式出了問題,結果查好久才查到原來根本是外部程式導致
這會造成大家的麻煩,請務必別做這樣的事情
再來,為什麼這種函數都很少去用各種condition來assert結果
因為:出問題你很難判斷是外在資料錯誤,還是你計算錯(原因可以無限上綱,不要懷疑)[註1]
與其花費大量時間寫各種判斷式來嘗試抓冰山一角
更好的方式就是不要在unit test幹這種事情(不是不測,而是別在這階段做)
(假使要做這件事情,除非程式本身就帶Exception,那我們可以做另一個測試時,帶入不合法的值來確認是否真的會觸發Exception)
Mock Object的作用就是在此,我們應該準確地確認這個unit是否真的有運作
不應該被其他外在函數的特例狀況影響到
這也是單元測試好用的地方,我們即使程式還沒完成或上線前接不到資料
也可以假設某函數資料正確來直接測試,這是Unit Test Framework最強的地方
這樣也不需要在主程式改一些測試專用Code,然後可能上線前還忘記砍掉之類
老話一句,如果想用unit test,
請絕對不要迎合unit test去多做一堆沒用判斷,然後說什麼這樣可能很難測試,我要為了unit test方便而忍痛改變現有架構之類的蠢事
請去用他對你來說真正受益,可以減少程式錯誤,增進開發效率的地方,這樣才能發揮價值
註1:
因為用少數結果絕對無法檢驗程式邏輯有沒有錯
要舉一些極端例子的話,
1.如果你assert 3應該回傳5,我程式如果為了測試,最後一行真的是寫return 5,assert下去絕對有過,但這樣的結果明顯只是鬼打牆(而且這個實際真的有人發生,因為為了寫unit test最後的return還真的忘了拿掉)
2.如果你做了兩個,assert 3應該回傳5 assert 4應該回傳 6 是否裡面剛好程式搞砸了,最後變成 input+2 ,結果assert還是有過
3.然後開始上綱,你的unit判斷式寫太複雜其實有藏了幾個BUG,結果要測目標程式測不到
分析自己的判斷能力
http://www.neo.com.tw/archives/1072
這不是引用,也不是轉貼,單純是素材...
當你看的出來哪些是消毒文的時候
恭喜你,你的判斷能力有及格
不過,有些抗性和理解真相的能力
常常是要自己被坑一次才會了解...
PHP的個人整合應用分享
感覺抱怨文發有點多,發一篇來洗掉(雖然沒什麼意義)
以下請勿沒看狀況照搬,也請自己先弄懂並確認運作流程
假設有狀況需要執行A方針的流程1和流程2,但其他狀況需要執行B方針的流程1和C方針的流程2
神奇的PHP可以把他整理得很乾淨
class A{
function magic(){
doSomethingA;
}
function magic2(){
doSomethingB;
}
}
class B{
function magic(){
doSomethingC;
}
}
class C{
function magic2(){
doSomethingD;
}
}
$dynamicClass = new A();
$dynamicClass->magic();
$dynamicClass->magic2();
} else {
$dynamicClass = new B();
$dynamicClass->magic();
$dynamicClass2 = new C();
$dynamicClass2->magic2();
}
但是其實可以整理成這樣
$dynamicClass = new A();
$dynamicClass2 = $dynamicClass;
} else {
$dynamicClass = new B();
$dynamicClass2 = new C();
}
$dynamicClass->magic();
$dynamicClass2->magic2();
好處的話,當流程不只兩個,而是十幾二十個的時候,差在哪顯而易見
但是這也考驗著,有沒有辦法整合自己架構,釐清整體流程
因為在這裡雖然很明確的寫出magic和magic2作為方便理解,在現實狀況卻不一定是能很輕鬆分出來的
使役理論幫助自己,別白癡的去當理論的奴隸
我實在不懂為什麼有人會說
"雖然我不懂,但我還是覺得人家有這種理論,必定有一些神奇且深奧的地方"
"我覺得XX理論就是YYYYY,所以我們做這件事情,依照這理論,我們應該ZZZ"
拜託一下,用一下你的腦子好嗎?
這理論到底帶給你什麼好處,如果在寫程式,應該深有所感
TMD不要寫到綁手綁腳,寫到吐,然後回頭被問
"阿你這樣寫到底實際上拿到什麼收益,效率快在哪,維護方便在哪"
結果?拿不出來,而且還用一些自表理由
"(重複)因為這理論就是YYYYY,所以我依照這理論,我們可能要ZZZ,然後或許因為有點限制,還要ZZZZ"
"我雖然說不出來有什麼好處,但未來總有可能有幫助的"
可以停止欺騙自己了嗎?
有些人很確切的了解到自己幹這件事情雖然綁手綁腳,但逐漸為自己理想邁進,這樣的犧牲是有價值的
但是有些人不然,看到一些小地方為了展現自己知識,就硬是要大作文章,說我覺得這樣做比較好,你們遇到這件事情也都倒跟我效法
老實說,這樣算小事
但是,遇到方向性理論呢?
有些人自以為可以見葉知秋,以為我把這邊做好,考量別人可能會出狀況的BCD,恩我的系統超好超完美,你看,以後怎麼發生狀況我都不怕了啦
然後,才出一個狀況就倒了是怎樣
這絕非運氣不好,我用一個非常具體的程式例子來講
"單元測試"
為什麼單元測試不做邏輯測試,不做整合測試,甚至資料假的都可以測試
"因為他本來就不是給你測這些鬼東西的"
有些人自以為聰明,想說"測試總是要有點實際意義",然後就寫了落落長的"可以順便驗證資料真實性,可以確定邏輯和突發狀況的"單元測試程式,雖然說測試程式比原本程式碼多有時候是正常的,但也多太多了吧?雖然問題遠比這嚴重
你的目標是"如果發生了我預想的ABCD狀況,根據我的測試,我可以準確的防禦並抓到問題"
但是,程式根本不怕預想錯誤,就TMD怕例外,所以才有Exception,才有assert
你拿這些預想內狀況來測試,是在考驗自己,測試自己的智商水平會不會哪天手殘改壞沒注意到還上線被客戶使用結果爆出來了嗎?
在某次單元測試中的對話:
"你看,為了測試我這個程式運作沒有異常,我直接抓這必要的回傳陣列第一個值判斷是否有設值,就可以完美的讓這測試有更深遠的意義"
"異議,回傳是空字串同樣算是有設值"
"那麼就在檢驗字串長度好了"
"還是有異議,回傳是錯誤資訊也還是有設值"
"那再多個判斷是否回傳的是錯誤資訊"
"一筆資料也不能確定沒有異常吧"
"那我帶十筆測試,這樣可信度更高了吧"
"資料庫被影響怎麼辦"
"哦,那我們要自己建立專門用來測試的資料庫,確保測試期間所有程式只有我的程式在運行,所有影響都可掌控,然後每次測試完畢以後都要刪光資料表,確保上一個測試沒有影響到下一個測試,接著還有還有還有還有.........."
...TMD我到底聽到什麼神奇的對話...當場傻眼
(如果讀者認為上述的很有道理,代表客官您還不是很懂單元測試在做什麼的,建議去Google或我先前的文章有非常詳細的說明)
然後?沒有然後了,因為單元測試目的在檢驗"程式跑得動"
但有人一直在檢驗"運作完全按照自己預期,資料沒有出錯"
所以才會發生死胡同
"沒有設值,恩空字串也算有設值,不對即使意外從其他資料庫拿到錯誤的資訊還是有設值,更進一步,你中途不小心手殘去設了值...這測試程式怎麼這麼難寫!"
"我預設其他人都不會傳錯資料,只會用我預期的方式發生預想中錯誤,這樣我就可以用我的理論發揚光大,展現我程式的彈性"
抱歉,這種東西,完全是妄想
程式是要預留調整的彈性,而不是自己預想將來會發生啥狀況然後擅自認定以後把這些應對寫好
一定有人會白癡問說:"阿將來發生怎麼辦,你要負責嗎?"
我可以順你的意,按你理論,我可以多寫一百多條判斷,你不准撤,因為將來只要出錯,你撤了任何一條判斷,你就要負責
為什麼這樣說
因為這只是單純的把自己的白痴思維套用到別人身上
你擅自認定了以後可能資料庫會按照自己預想的方式修改,而且哪天手殘會不小心改到程式碼的特定某個區段,此時我寫的防禦機制,將將,漂亮的防禦了一次攻擊!
....姑且不說約有99.999%是"預想外狀況"
我可以很明確的說,如果到時候發生了你所說的狀況
"百分之百是你幹的"
你正在做這件極度自婊的事情,不過你好像沒有這個自覺
為什麼這能牽扯到理論的奴隸
這非常簡單,非常直覺,因為會幹出這種事情,不外乎自己已經被一些自己擅自認定"這東西超強"的理論框架綁架,擅自認為這東西效率最高,最好,出錯一定都別人寫錯或不會用
自己捫心自問一下,真正效益在哪,犧牲在哪
不是TMD理論的白癡講解方法,而是運行呼叫次數少了多少,維護預設遍歷少了多少,記憶體少了多少
這點我一直想說,有些人被問問題,馬上很搞笑地去GOOGLE找測試數據,找別人怎支持這理論
雖然一直藏著沒講,在這邊講一下好了,反正沒幾個人看的到
"你TMD這麼有自信,不會寫測試丟自己程式身上證明一下嗎?
有些人確實這樣幹,我非常佩服,但這些人因為自己有測過,說話都會比較保守,因為如果有正確且充分的測試,都會了解到自己現在寫的都不是最好,最萬能的
為什麼?因為常常
換個環境測數據就變了
隨便換個攻擊手段你所謂的防禦機制就崩潰了
隨便換個架構修改法你預想並擅自寫好的擴充函數根本無用結果導致得全部砍掉重做
同一個演算法無法完美套用所有運算
同一架構無法完美套用於所有狀況
同一個預防機制無法因應所有意外
這是基本常識,我們因為有腦子,所以我們懂得變通
所以絕對沒有什麼"照這樣理論就對了,絕對是最有效率,最完美的"這種蠢事
但是有些人展現100%的自信,被正面婊後還死不認錯繼續轉移焦點找理由,然後再把那些已經被打臉的又重新搬回來講一次理論
沒有經過正確消化的理論,即使講第二次也沒有更大的說服力,不如說根本是反效果
因為即使這理論真的很好用,你也沒有正確使用到,才會有這樣的表現
這種,就是百分之百的,理論奴隸
常常覺得自己很忙,做苦工,結果到頭來只是屈服於好像很好用的理論之下
我真的不知道該說什麼,因為根本不知道從何吐槽起
最崇高的設計理念,架構,永遠只是夢想
因為他本來就套不進現實狀況,硬要用只會被正面婊慘後各種拘束最後在嚴重拖慢效率
夢想是目標,但從來都不是寫程式的標準
因為照著走只有死路一條,且遇到狀況就牽就所謂的夢想,只會把事情搞複雜
這叫自殘,絕非變通
沒有能力去駕馭強大理論,就放下身段,懂多少就去用多少,這才叫踏實
因為你可以明確知道自己正在幹什麼事情,犧牲多少,得到多少
"所有能用的都要全用上,讓狀況變得非常完美"
抱歉,請在夢裡面講就好,尤其奉勸某些人找到一些看起來很強大,就自以為可以完全掌握,而實際上非常生疏,是第一次接觸的技術
請三思而後行
這裡並不是說什麼,故步自封,有新技術也不學什麼的
而是指,你學了多少,掌握多少,就用這些拿來幫助自己就好
沒有必要打腫臉充胖子,以為自己沒掌握的地方也會按自己預想的狀況下進行
這非常危險,也常常讓很多人直接走進死路
但終究還是給自己一個警惕
永遠不要擅自去認定環境該怎麼改變而擅自預先做了一堆自以為是的防禦機制
因為,預想內的基本處理是"本來就該做的事情",還去做一堆事情"預防"根本叫做"搞不清楚狀況"
要預防的是什麼?
該預防的是預想外狀況(例外)好嗎!?
本日最無言
http://www.ettoday.net/news/20141109/423806.htm#ixzz3IZQKV4Bk
在民主社會,人民選你,是因為你的決定會是人民心聲,因為你的決策會等於人民的決策
不能讓人民有決策權到底是啥鬼?
本篇禁止comment
歷史紀錄
有雷,點之前請先有心理準備
如作者對本BLOG轉貼有反對意見請提出,將直接移除(注意必須是作者)
http://homu.komica.org/38/src/1415525945549.jpg
http://www.stormmediagroup.com/opencms/news/detail/70d0ec64-c6bf-11e3-896c-ef2804cba5a1/?uuid=70d0ec64-c6bf-11e3-896c-ef2804cba5a1
https://tw.news.yahoo.com/%E5%8D%8A%E7%89%88%E5%BB%A3%E5%91%8A%E6%94%BB%E6%93%8A-%E4%B8%81%E5%AE%88%E4%B8%AD%E7%97%9B%E6%89%B9%E9%80%A3%E6%8A%B9%E9%BB%91-221033029.html
https://www.ptt.cc/bbs/PublicIssue/M.1413021545.A.785.html
請把OOP的精神發揚光大,而不是只把他的封裝幹徹底
死迴圈,一堆人有這種本末倒置的觀念
寫到最後,通常會用這種理由來解釋自己的程式比別人品質更高
"你看,我這邊判斷得多麼精準,沒用到的就是不會執行到,多麼完美"
"你看,如果你想加額外的處理項目,直接在這底下開函數就可以了"
"你看,你完全不用管我這邊怎運作的,只要使用就行了,該出的例外訊息都會丟出來"
我要反問了
"現在不是額外的處理項目了,我們資料庫要換,處理方法要換,你能馬上改出來嗎?"
"現在合作架構有點異動,很多欄位(數量)都改變了哦"
最重要的
"現在XX功能出問題了,你打算怎麼讓別人知道該怎去追這麼BUG"
"你要怎麼讓別人知道你程式運作的方式以及調整架構的方式"
然後死盲點
"你真的以為用這一大堆判斷式確認沒有額外函數執行效率會比較高嗎?"
合作開發這種事情,一個人是幹不起來的
要讀別人的程式碼是必然,因為要合作,在來有BUG,即使你說你負責處理,退個一萬步總得讓對方知道怎把這條BUG報給你吧
有些人會問我,怎麼你說你的程式是OOP的架構,GET/SET怎這麼少,函數好像也沒開很多
我倒要反問一下這些東西跟OOP到底有啥關係了
大家常常看到的 Vehicle new Car new Bike覺得很完美對不對?
可是你有沒有想過那只是大準則,你真的一new就天下太平了嗎?,別妄想了
程式,最基本最重要的東西就叫做"流程(Step)"
所有東西都依賴於他,即便你是個OOP架構,你最終還是要給我個"使用順序"來完成事情
當你確定流程以後,才有資格說我按照使用狀況去封裝必要的程式碼
為什麼?因為這樣做才能讓合作對象最容易了解你在做什麼
怎樣算是一個成功的OOP,就看需求有變動(注意不是項目,多個欄位你就顯示不出來,請不要來亂)程式能跟著變化到什麼程度
最基本的,處理流程,順序,不同資料銜接的方式,在怎麼說都是需要靈活應變的
總不能說我的資料只能完美的給A情況使用,換成B,阿不好意思我要大幅度改寫...
你再怎麼解釋你程式高效能,最終就是被貼一個標籤,應用方式太狹隘,思考太侷限
那怎樣算是一個失敗的OOP,近期看到一個例子,來分享一下
這個OOP相當省記憶體,因為只要沒有做到的他就絕對不會初始化,這點已資源考量方面是相當完善的
然而,他是怎麼運行的呢?
當我new 一個A類別,我就會執行一些B函數,但執行到一半為了處理事情我要用執行階段的部分內容呼叫C函數處理,然後執行完後我要直接拿這個結果呼叫D函數...
(後來想想,應該有人會看不懂,那白話一點,這個狀況就是:
你執行A類別,B函數以後,剩下的CDEFGHIJKL你除非去追原始CODE不然都不知道她怎幫你處理資料的)
問題來了:
這些所謂的function都是丟在該類別裡面,當有人問你
"請跟我說一下這程式處理資料的流程,我覺得好像有個地方執行怪怪的"
下場,很簡單,你要從頭到尾解釋一次程式給他聽,而且恐怕第一次解釋還聽不懂
因為function不管你怎麼整理,為了高效化就是有許多各自的細緻處理,最終的下場就是
"執行順序消失了"
這是相當嚴重的事實,我有正常跑我的類別,可是執行順序我都需要反查一下才知道跑到哪了
先不考慮過多判斷是否早已掩蓋掉原本直接執行的效率
剛才是不是有提一件事情
"現在,我的處理資料流程要變動了哦,稍微變動個執行流程,因為中間我們要加個驗證了"
然後好死不死,原作者不在現場
快,告訴我,哪個傢伙趕快神解一下這個類別到底該加在哪個位置
物件導向,是將事情正確的拆開封裝,以"方便溝通",與"方便維護",和"方便調整"
但這個模式同時隱含著你必須處理好運作流程,否則該封裝沒有意義
我一直不懂為什麼有些人會用效率去解釋他的OOP做得多好
你們TMD為什麼沒想過原本直接下一條指令就能搞定的東西,被你包了這麼多層
怎麼看都不可能比原本的效率還好OK? 你沒把最重要的流程,架構,溝通做好
還反過來說你看我這樣封裝,沒執行到的都被我精確排除了
抱歉,我只說一句,你正在拿最沒有效率的手段說你正在提高效率
請絕對不要做這種搞笑事情
以此觀點來說,沒錯,我也要講另一件事情
那些看起來很強的perfect coding,我就真的當它是都市傳說
因為那常常是特定狀況下才有辦法這樣幹,又或者是自身已經對資料架構摸到熟到不能再熟,且資料架構也沒啥大問題的狀況下,才有可能完美呈現的CODE
很抱歉這個需求我就是要動到5個資料表,你要我用處理單一資料表的水準把程式跑出來
這就是不可能的事情,請不要對著這支程式說
"你看人家對(單一)資料表都處理的那麼完美,怎麼你的處理方式有點雜亂"
當你正在想這件事情的時候,請自己寫一下真正會變怎樣
如果全部都能照你所想的正確呈現出來,那你真的可以去讓對方信服
反之,雖然處理漂亮了但判斷變超複雜,STEP變超複雜,你TMD還是來亂的
因為根本就不可能這樣改寫
有些理論只存在理想,如果你覺得他可以實際用出來
請拿實際能辦到且自己正在應用的事情來說服別人(不是拿其他人的程式碼哦,這有天地般的巨大差距),而非只是宣傳一下好像很強的理論
就以為自己也辦的到,且這很完美,怎麼別人都不聽你的
理想與現實,一直都是兩回事,身為一個程式設計師,請務必先釐清這件事實
合作寫程式,開發階段的基本概念
1.流程麻煩清楚
2.讓別人一看就知道你在幹什麼
3.初期程式請勿封裝過頭
4.初期程式請勿封裝過頭
5.初期程式請勿封裝過頭
有件事情說了三次,為什麼,很重要
開發階段為什麼叫開發階段,就是因為我們可能還會按照需求調整
可能還會中途插入一些預想外的資料需要處理,也可能其中有一半要全部打掉因為不用了
你把程式全部像OOP概念一樣封起來,就程式精神沒錯,但就合作開發角度你TMD根本在搗亂
首先這種東西沒有辦法很快讀懂,浪費所有人初期確認你程式運行的方式,撰寫架構等等
再來,如果真的慘劇發生,"這一大半現在說不需要了,我們另一半資料應該用另一個資料庫,處理方法也要變更"
封裝過頭的下場就是你會抱怨怎麼這樣我超不方便改我程式的
因為近乎,不對,是整個要重寫
其次,遇到封裝無法處理(例如需要多考慮一個參數),結果又要說是程式限制導致,結果其他人要配合你解決嗎?
不可能的,你還是得大費周章調整自己已經封裝好的程式,因為這是你的問題
且還要額外多測試很多東西,因為你不能保證我只調整這邊,其他一律不會出錯
你當然也是可以不測試,但往後如果出錯就是被裱到更慘,因為通常已經是很多人開始使用,然後你也說這程式沒有問題的狀況
最後,最現實的
"我現在東西參照到你的,東西也完全符合格式,但就是出錯了"
結果一查,一開始沒有全面考量就封起來,結果要改掉這個例外狀況,我還是要拆掉重新寫在重新封裝
你覺得這樣回應有用嗎?
"這是這個函數的限制,你要呼叫這個函數,要自己避免我程式不支援的地方"
拜託,不用想就知道會引起公憤的行為,請三思而後行
補充一個更慘的事情,那就是因為別人看你的程式看不太懂,以為你封起來的東西並不支援需求,所以又另外寫一個,結果到時候還要解釋說
"如果你當初有多花幾小時研讀我程式的話,就會發現我寫的東西已經滿足你需求了,所以你這些並不需要寫"
即使你寫的東西再完美,都會讓很多人不爽,因為你寫的程式很難溝通
然而,OOP概念沒用嗎?封裝沒用嗎?考慮最佳效率沒用嗎?
錯,當然有用,非常有用
但是這種東西有用是,大家合作的部分都已經確定,整體架構趨於穩定,需求也穩定近期不會改版,或基本要封測上線
那我們就可以考慮哪邊可以開始整合,優化,提高效率
這時候當你提出,"我覺得這地方要進一步整合封裝起來,可以提高效率"
那,大家也可以快速地確認有沒有影響到自己的部分,有也可以馬上提出來
再者,你這時間點想幹這種事情,除非提案荒唐,否則獲得雙手贊成的機率應該非常高
因為你是針對穩定下來的東西想進一步優化他,沒有反對的理由
因為你接下來要封裝的東西,別人同樣呼叫你寫的程式,方法必定更簡單,或者根本沒有必要改呼叫方法
總而言之
重構,整合,封裝,絕非在最早的開發階段應該做到徹底完美的事情
因為你做了就等同在找合作夥伴麻煩,以及找自己麻煩
請先有初版程式,讓大家看懂你整體流程到底在幹什麼(當然還是要整理,只是別過頭,詳見文尾說明)
開發階段是討論程式架構與合作方式,分工方式的時間
而不是爭論哪種寫法效能比較高的時間
隨著需求改變,你所謂正確率最高的寫法有可能在當下直接變拖油瓶
最簡單的狀況就是因為絕對不會錯又大量狂跑一堆寫過頭的防錯機制
又或者你是為了因應未來"自己認定的可能修改方式"而特化了部分封裝,然而這永遠沒發生
結果發生的都是"自己認定以外的修改需求",結果感覺別人都在整自己,然而這不是從一開始想法就本末倒置了嗎?
所以,請務必清楚團隊合作開發一開始該做什麼
以上
說明:
1.文中所提及之基本易懂流程絕非單一函數CALL到底叫易懂,絕非SQL WHERE JOIN JOIN WHERE SELECT到底就叫易讀,這種也並非效能問題,而是會"直接死的問題"
2.效能問題大概像是"雙引號還是單引號效率高一點","我先用function整理起來,呼叫時間可以縮短0.01ms,記憶體可能減少1bit"的問題
是自作聰明,還是沒事找事做?
主管:請給我1+1的計算
恩...怎麼看都是echo 1+1 應該就OK了
等等,以後可能會改成2+1...好吧,那麼用傳入值的方式
var p = 1
var q = 1
echo p + q
嗯!完美!
不行不行,到時後說要突然把加換成乘怎麼辦
var p = 1
var q = 1
var op = "+"
function amazingPerfectFunction(p, q){
if (op == "+")then
echo p + q
}
call function amazingPerfectFunction(p, q)
等下,不行哦,搞不好有人p會亂改,或中途不小心改到
順便念一下好了
var p = 1
var q = 1
function amazingPerfectFunction(p, q){
try{
if (op == "+")then
echo p + q
}catch(notnumberexception e){
echo "你腦殘喔輸入什麼非數字!";
}
}
call function amazingPerfectFunction(p, q)
初版完美程式完成了:)
[轉貼]當我們還有思考能力,就很難被誤導,但現實似乎...
如果你的26同學在酸你們台灣人在頂泰豐尿尿在小籠包上面,
如果有689拿這個事件在說嘴,酸台灣人的素質其實沒比"內地人"好上多少,
請您基於實事求是,追根究底並且導正視聽的精神,
把到底發生了什麼事情說給他聽。
https://www.ptt.cc/bbs/Gossiping/M.1413888793.A.6B0.html
https://www.ptt.cc/bbs/Gossiping/M.1413901860.A.05B.html
[轉貼]個資安全請特別注意
目前看到最慘的例子如下:
http://www.cna.com.tw/news/aopl/201410130399-1.aspx
phpstorm 運行 phpunit的小問題
實際上在setting 做好直接引用的path to phpunit.phar即可直接使用
但是,這邊會遭遇到一個小意外:
如果你是按照PHPUnit的官網來做的話
https://phpunit.de/getting-started.html
最後的名稱是"phpunit"
因為PHPStorm只吃"phpunit.phar"這個特定名稱,所以載入會失敗
直接複製一個改名成phpunit.phar就可以直接載入
VirtualBox 共用資料夾 權限設定
參考自:
http://www.arthurtoday.com/2012/09/virtualbox-shared-folder-permission-denied-invalid-argument.html#.VCzomvmSz1Y
一般來說如果直接按一按設定做好環境,其實就可以直接用了
可是,只能用root
但是ubuntu環境本身就不是能用使用者root來操作的底
所以如果想要能直接點media/設定資料夾 就顯示的話
必須要sudo usermod -G vboxsf -a [使用者名稱]
Linux SSH Key遷移
確認是兩組相對應的key
如果key檔案不在~/.ssh/ 下就ssh-add,重開機就會不見,需要重新ssh-add
因此建議把key檔案放到~/.ssh/底下,開機後就會自動載入
[轉貼]當你還能思考的時候,請不要自己放棄他
https://www.ptt.cc/bbs/Gossiping/M.1411750202.A.16A.html
有多少人一出生就沒有辦法思考,這數字遠比你我想像中大的多
仔細想想這是多麼殘酷的事情
我每次看到放棄思考的人就各種火大,根本在糟蹋得來不易的人生
人類很早就開始有藝術品,因為他們不只求生存,他們開始思考怎樣製作作品流傳後世
有些根本在文明社會的人,他們也會反駁,"我光是生存就盡全力了,因為..."
我只能說,當你還能說這些話的時候,代表你為了生存以外還是有空間營造自己的作品的
人生如果只為了延續生命,根本沒有必要這麼麻煩幹這麼多事情,這毫無效率好嗎?
就是因為"我有其他想要完成的事情",所以"我才需要繼續生存"
可以不用事事都拚上老命,但總不能當個只會呼吸的肉塊吧,嗯?
-------------
幫高調
https://www.ptt.cc/bbs/Gossiping/M.1411915695.A.293.html
推薦閱讀的基本
"為什麼推薦,因為___"
"我看過以後發現___非常棒,你也一定要看看"
推薦閱讀就是因為自己讀過發現某些特定片段深有感觸,所以才想別人也一起看看
請絕對不要拿書名或作者或標題或"我認為XXX很重要"根本沒讀過就砸過去了,這非常沒有禮貌
磚塊這種東西,常常寫了一堆廢文在灌水,更常常只有一兩頁值得參考
如果做這種事情,代表
"我覺得XXX很重要,看看磚塊的標題,恩差不多啦,全部讀完應該會有不少體會"
相信我,對方正在想的是
"你X的自己都沒讀過,怎這麼神知道這本書能讓我讀完有不少體會,連重點都點不出來"
ubuntu的設定網路別直接改interface檔
如題
猜測程式會覺得你寫的跟他預設的格式有點不同就判成別的版本
然後interface檔和系統設定值裡面的網路會雙雙掛掉....
當然可能只是個案
(我的狀況是interface和控制台的網路裡面的檔案都被ubuntu砍掉了)
總之紀錄一下這個狀況
[轉貼]Mysql Prepared Statement
有些人以為這種東西就是給PDO帶參數防inject用的,實在有點無言...
實際上這東西用途相當廣,也很適合應用於撰寫資料庫批次維護...
推薦你一定要看一下在mysql環境下怎麼直接做prepared statement
http://www.codedata.com.tw/database/mysql-tutorial-12-prepared-statement/
[轉貼] SQL Describe改(查comment 權限的表)
SHOW FULL FIELDS FROM database.table
SHOW FULL FIELDS FROM table FROM database
(如果已經USE過,直接FROM table就可以了)
資料來源:http://liaosankai.pixnet.net/blog/post/18480448
[轉貼]你以為一生光明磊落,事事對得起自己良心就沒事了嗎?
https://www.ptt.cc/bbs/Gossiping/M.1410696376.A.E92.html
共勉之
我們可能不能防止別人的抹黑,這是無可奈何的
但如果輕易的隨著抹黑沒查證只是跟著輿論起舞,這就相當的愚蠢了
本篇並沒有指任何人,請不要自己對號入座,謝謝。
單元測試的真正意義(10/7更新)
就是Unit Test,結束,嗯?(不對阿,就真的是字面上的意思哦?)
不過確實,有很多人以為這東西是寫所有程序都應遵循的絕對準則,或者甚至以為Unit Test就是PHPUnit,JUnit,最嚴重的是還以為要涵蓋測試所有function,就是要確認我的資料處理完全正確...
(點選標題閱讀全文)
舊版fuelphp vs redis 衝突筆記
裝正規redis.so的前提,還用舊版FuelPHP須注意
舊版的FuelPHP,redis路徑在Fuel/Core/Redis
如果事先use過或變過namespace,可以直接new Redis
但是裝了redis.so以後,同樣可以new Redis來使用,這裡會產生衝突,造成運作異常(例如出exception)
新版的FuelPHP,redis路徑在Fuel/Core/Redis/db.php,class名稱變成redis_db,所以是new Redis_Db,所以不會起衝突
利用FuelPHP Migration拿建立資料庫的function
前言:
Migration實際上原本是要自己寫的,且這個遷移實際上跟字面上的語意差很多
Migration的作用是結構控管,也就是現在的資料庫使用的結構如果是共同協作,那麼如果我需要升級一個版本,那我統一丟一組migration給你就好了,你升級以後就能使用新寫出來的某某系統,大概是這樣的概念
(點選標題閱讀全文)
FuelPHP Migration小研究
簡單來說呢,migrate是一個架構改變機制
up和down設定好以後,up通常就是升級版本以後資料庫應該要怎樣
也就是我想要在新版的A資料表的B欄位名稱應該改成C
那up就是A.B 改成A.C down就是A.C改成A.B
由於是可逆的,因此up和down必須完全是相反操作,這樣就能符合結構的版本控制
如果中間有發現什麼問題,也可以直接退版本來解決以後,再重新進到比較新的版本當中
官網沒有說很清楚,其實那個檔案XXX_filename的XXX就是版本名稱
因此如果打入php oil r migrate --version=23
就是從目前執行的版本一直執行up裡面的函式直到23號的檔案
然後如果又要退到15號,打入php oil r migrate --version=15,他就是不斷執行down的函式直到版本是15
因此這裡的架構的PHP SQL Code可逆性有嚴格要求(尤其做什麼rename 然後還有搬東西或修改架構而非創建之類的,就要特別注意)
最後,這些東西都跟資料無關,注意migration只針對資料庫架構進行調整,是不管裡面資料內容的
所以你可以看到up 裡面create一堆,down 就直接drop了(或相反)
中間不負責救資料,因此需要留意
ubuntu rename的真正用法
天殺的不懂為什麼範例少到一個 ...
假設想把該資料夾所有php檔名裡面的abc改成xyz
rename 's/abc/xyz/' *.php
FuelPHP的short tag
不存在,不要懷疑
這是為什麼他如果想用short tag還需要掛smarty的原因
這點code igniter就好很多,不過code igniter是暫存還是每次編譯就沒有去看了
smarty是會先編一次放在暫存資料夾下面,實際上沒有運作問題(除了第一次執行,但這並非大量使用的重點考量)
ubuntu apache預設編碼
/etc/apache2/conf-available裡面
有個註解狀態的AddDefaultCharset UTF-8
取消註解後重開即可
有些環境可能不一樣,反正找到含有這行且有作用的檔案改就對了
apache多server基本設定
雖然每次都能解決,不過要一直try自己做的對不對很煩,紀錄一下
<VirtualHost *:80>
DocumentRoot /var/www/
ServerName ayu.local
</VirtualHost>
<VirtualHost *:80>
DocumentRoot /var/www/test1/test2/test3
ServerName ayu
</VirtualHost>
然後,網域註冊或host
此時
ayu/index.php即 /var/www/test1/test2/test3/index.php
ayu.local/index2.php即 /var/www/index2.php
此時ip/index2.php 可以正常連,不過ip/index.php會找不到
小記錄,不喜勿點
沒放TAG,內容單純提醒我以後不要蠢到犯同樣錯誤
內容可能讓你不舒服,但絕非色情連結
https://www.ptt.cc/bbs/Gossiping/M.1407151986.A.AD8.html
http://tw01.org/profiles/blogs/xiao-yuan-zui-da-ba-ling-ji
http://blog.kaishao.idv.tw/?p=2899
http://imgur.com/oDHqa9V
http://imgur.com/a/mXkig
資料來源
https://www.facebook.com/nagee.tw
---------
http://ma92pa.blogspot.tw/2014/04/blog-post_13.html
Mysql show function list
....喵的明明有create function,drop function
可是根本沒說清楚怎麼查阿!
找了N久才看到可以
select * from mysql.func;
PHP測試小技巧
不能直接echo值怎麼辦?
試試echo "<script>console.log( '".$YourValueWantToDisplay."' )</script>"
註:僅供開發測試用,上線請避免使用這種寫法
更進階的用法參考 http://stackoverflow.com/questions/4323411/how-can-i-write-to-console-in-php
cli 和apache2
這是不同的環境設定
前面是指打cmdline的時候所引用的設定
以xdebug為例,我們灌好要新增這個功能的時候,必須要在php.ini裡面設定
zend_extension=xdebug.so
不過你如果locate,就會發現實際上有兩個php.ini
$ locate php.ini
/etc/php5/apache2/php.ini
/etc/php5/cli/php.ini
Ubuntu 14 的GuestAddition 與字型
VM必用到的無痕模式
其實不一定用到,但是可以隨意縮放視窗是賣點
...
但是14.04有部分特定版本(或者說,更新)讀光碟會異常(會告訴你檔案iso格式不符
阿google下去那就是光碟的標準格式阿....為什麼會讀不到.....orz
現在的最新版,嗯,老實說不太穩定,問題也比之前難解(畢竟才出沒多久
所以要做這類更新之前自己照個VM快照吧
------------
注意:這是"部分版本"對光碟格式判斷錯誤,不是"全部版本"
所以這邊才建議更新前照快照,如果內容有更動,第一次重新開機無痕模式仍然會失效
但是這個時候插入光碟並不會有錯誤訊息(如果不相容的版本,插光碟就會告訴你I/O錯誤,如果這個狀態再更新會不會解決就不清楚)
此時重新安裝Guest Addition
------------
原本以為只能忍耐用心細明體了,沒想到發現一篇
http://scar.simcz.tw/article/2014/04/22/fix-ubuntu-14-04-lts-zh-font-selector/
phpmyadmin 提示缺少mcrypt
php.ini裡面
Dynamic Extensions中
extension=mcrypt.so <=注意自己locate一下可能不同路徑 名字之類
還有一個做連結的方法
不過網路上的方法製造出來的可能跟旁邊的預設設定不一樣,同樣自行參照一下修正
理論上做一個就可以了....
php 資料庫編碼問題
$conn = mysql_connect(ConnectionProperty::getHost(), ConnectionProperty::getUser(), ConnectionProperty::getPassword());
mysql_select_db(ConnectionProperty::getDatabase());
mysql_query("set names utf8");
if(!$conn){
throw new Exception('could not connect to database');
}
在選擇db以後設定編碼
其他的做法莫名其妙的沒用...
phpunit+gearman產生的矛盾
嗯,經過各種接近極限整人的測試以後,發現以下幾點,有誤請指正
指正是拿具體例子或明顯可執行/實作的例子來反駁,如果舉不出可行的簡單例子,請勿來亂,謝謝。
------------------------
先說結論
phpunit沒有辦法正確顯示coverage的原因是沒有直接call,然而這個應該是gearman的必然現象
判斷的結果,既然是單元測試,那麼必然是我直接call他可以得到期望的回傳(即使中間有邏輯),好死不死gearman的運作機制並不是這類型的
首先是worker部分必然是脫離phpunit獨立執行,因為開worker那部份一定要無窮回圈來listen(不然用gearman就失去意義了)
phpunit比起coverage實際上assert才是重要的檢證機制(畢竟他不只可以用來assert true,assert false,或是assert 特定的value,還可以使用regexp來檢查return,是相當有效的防修改掛掉的test
然後listen的client部分為什麼沒有cover呢? 很簡單,即使用了class,即使require,我們也不會去直接執行那條function
因為在沒有job的狀態下,去執行那條function毫無意義,然而如果是發出去的worker需求,會變成這樣:
"我們(傳資料)給已經註冊的job server function,由他幫你處理註冊好先前設定的工作"
所以中間的code都是我們一開始註冊的無窮迴圈狀態的worker在執行的,既然是別人在執行,那就不會cover了
FuelPHP 模組/HMVC筆記
FuelPHP對HMVC敘述不明不白,附帶一提那個V還是有問題的(後來新版架構已改成presenter)
app/config裡面的'module_paths' 項目要做好路徑設定,不過不是設自己的名稱
而是內定的APPPATH.'modules'.DS,
module裡面最底限要有類似fuelphp的架構
因為module和package的差距就是module"可以路由"
也就是說,如果執行netpath/mymodule/moduleincontroller/index之類的路徑
我們是可以像自己本身專案的PHP一樣使用的
然後實際上用的方式,可以用HMVC直接請求回傳結果,拿來給原本的主程式使用
首先我們模組裡面的控制器使用以下程式:
namespace hellomodule;
Class Controller_Hellomodule extends \Controller{
public function action_index(){
echo Model_mymodel::hellol();
if( ! \Request::is_hmvc()){
echo 'Normal request!';
}
else{
echo 'HMVC request!';
}
}
}
模組裡面的模型(註:module裡面的model)使用以下的程式:
namespace hellomodule;
class Model_mymodel extends \Model{
public static function hellol(){
return 'I already hate hello world!<br/>';
}
}
此時我們直接連線到hellomodule/hellomodule/index
將得到:
I already hate hello world!
Normal request!
但是如果我們在原本的控制器用一個HMVC式的請求
$temptext = Request::forge('hellomodule/hellomodule/index',false)->execute();
此時$temptext 裡面的回傳內容如果被echo出來,將會是:
I already hate hello world!
HMVC request!
FuelPHP 套件筆記
最低限度設置:
app/config裡面的 'packages' 項目要做好路徑設定
'filename'=>PKGPATH.'filename/'大概這樣的形式
packages裡面最低限度要有classes資料夾,裡面放一個自己要用的class
然後底下要有bootstrap.php
Autoloader::add_core_namespace('套件名稱',true);
Autoloader::add_classes(array(
'NAMESPACE\\CLASSNAME' => __DIR__.'/PATH/filename.php',
));
注意
1.classname和filename可以不同
2.package裡面的檔案要有namespace,不然會redlare error
全部都做好以後,就可以直接使用package裡面的class,可以呼叫裡面的靜態function,不需要再加任何namespace
Example:
'packages' => array(
'ayu'=>PKGPATH.'ayu/',
),
測試設置: ayu/classes/ayu.php 以及ayu/bootstrap.php
ayu.php內容如下(為了確認class名稱與檔名是分開設定,這邊我們弄成不同的名稱
而namespace太容易辨識了就不再做額外處理)
<?php
namespace ayu;
class Tsukimiya{
public static function holyworld(){
echo 'Holy Package Loading and Working Success<br/>';
}
}
bootstrap.php內容如下:
<?php
Autoloader::add_core_namespace('ayu',true);
Autoloader::add_classes(array(
'ayu\\Tsukimiya' => __DIR__.'/classes/ayu.php', //即NAMESPACE\\CLASSNAME' => __DIR__.'/PATH/filename.php',
));
任意一個Controller裡面置入以下測試內容:
Tsukimiya::holyworld();
就可以得到正確的輸出
Holy Package Loading and Working Success
FuelPHP 擴充實作篇
學官網在classes下面直接加入 class MyConfig extends Config,然後隨便呼叫一個已經設定的設定值
echo "MyConfig::get('config_key1') = ".MyConfig::get('config_key1');
得到MyConfig::get('config_key1') = config_value1
隨便裡面加個函數並echo "MyConfig::test() = ".MyConfig::test();
public static function test(){
return 7;
}
得到MyConfig::test() = 7
因此隨便副寫個get
public static function get($item, $default = NULL){
return 1;
}
結果MyConfig::get('config_key1')輸出1,代表可以簡單用自訂函數去override
但是如果一定要使用官方的核心指令,那就必須要用同名class 同名函數去override
另外也必須正確把這個同名class在bootstrap當中預先add class,才能生效
實際上,FuelPHP有擴充限制,具體限制那些在官網可以看到
http://fueldocs.ycnets.com/general/extending_core.html
example 複寫log
class Log extends Fuel\Core\log{
public static function info($msg, $method = null){
return static::write(\Fuel::L_INFO, 'troll my info method ver2'.$msg, $method);
}
}
Autoloader::add_classes(array(
'Log'=>APPPATH.'classes/log.php',
));
如此,以後紀錄的info訊息都會加上一些自訂文字在裡面
FuelPHP 擴充詳解
基本上老話題一下
官網只要你沒實作出來,文件都看不懂,因為他的Example給的通常都很詭異
那他到底在寫啥呢?
擴充但不取代核心類別
也就是你用任何自己的自訂名稱去extend核心類別的項目
例如我可以用Mylog去extend Log ,我可以用MycOnFiG去extend Config
但是同名不行,不是掛掉就是沒效果
擴充且取代核心類別
這意思其實是說,我不管怎樣,下核心指令都想要用自己的
也就是例如,我view東西就是要自己的方法,log就是要有自己處理過的
這時候就去用同樣的名稱去extend,並且在bootstrap去add classes
然後最大的問題其實在
FuelPHP只有這兩種方法可以擴充,那些什麼很曖昧的作法是不存在的
所有曖昧或不合理的用法只有報錯,不執行或直接掛掉這三種狀況
(不要懷疑真的可能掛掉,例如你add class裡面丟config,又真的有那檔案,執行下去就死給你看)
例如我能不能偷偷用一個同名extend一下但不取代
或者能不能用自己方法去實作最後再回來假裝表面銜接後add class一下
因此,若當你已經知道那機制的內容,回去重看文件
恩,他寫的沒什麼大問題啊?
但是你交給一個還不懂狀況的:
fking shxt,那官網到底在寫O小朋友.....
php var_dump 突然無法顯示全部
如果有看到什麼 ...more element啥的
一定是不小心裝到什麼xdebug
以ubuntu為例,來到/etc/php5/mods-avaliable/xdebug.ini裡面(或php.ini,自行嘗試)
加入xdebug.var_display_max_children=512 (預設是128,沒幾條就會超過了)
然後重開apache2
不放心的話去phpinfo看設定
如果發現層數明顯沒有引完
則是去設定xdebug.var_display_max_depth
可能是預防太多層螢幕顯示不好看吧,要設幾層自己衡量了
FuelPHP的ViewModel 還真的消失了
一開始就在想說 這個實際上不算MVC的V(連一半都不到)
且還是optional(沒有必要實作)
新版的1.7.2已經變成Presenter Class
https://github.com/fuel/core/wiki/Changelog-v1.7.2
實際上,使用HMVC就會發現,即使請求回來頂多也就是"修正view的需求"
幾乎不會在HMVC裡面直接連過去(會這樣做的話,你應該會考慮直接讓這項目升級成主架構)
舊版本如果真的有用ViewModel意味著有小改寫的必要,不過幅度應該不大XD
補充一提,FuelPHP的V即使在HMVC也仍然能用
同樣的\Response::forge(\view::forge('PATHLINK')); 是會正確生效的
但是MVC架構卻不放在一起,只能說FuelPHP認為他本來就不是同一個層級的東西吧
FuelPHP各種try
https://drive.google.com/file/d/0Bz9IvLZNUkriUkdXc1l5OHZ4Y00/edit?usp=sharing
改自訂環境,CSRF,路由應用的小try
SSL基本理解
SSL 產生憑證參考網站1 http://note.tc.edu.tw/662.html
SSL 產生憑證參考網站2 http://wiki.centos.org/zh-tw/HowTos/Https
SSL 產生憑證參考網站3 http://twpug.net/x/modules/newbb/viewtopic.php?viewmode=compact&order=ASC&topic_id=2893&forum=22
基本上照著跑就可以
由於沒有真的上線需求,就先不去做真的認證了
產生的三個檔案分別放在
/etc/testssl/certs/ca.crt
/etc/testssl/private/ca.csr
/etc/testssl/private/ca.key
接下來應該是ubuntu需求(上面的連結是centOS設法,有些微不同)
首先先到/etc/apache2/sites-avaliable/default-ssl做基本設定
SSLCertificateFile /etc/testssl/certs/ca.crt
SSLCertificateKeyFile /etc/testssl/private/ca.key
然後啟動 ssl module
啟用 ssl 模組
a2enmod ssl
啟用 ssl 虛擬站台
a2ensite default-ssl
安裝 ssl 套件
apt-get install openssl ssl-cert
重啟 apache
/etc/init.d/apache2 restart
然後直接把檔案改https,應該就可以連上了
不過這時候會發現一件事情,那就是我們的route設定不見了
由於各個linux版本不同,以現在自己手上的ubuntu為例子,要到/etc/apache2/sites-avaliable/default-ssl裡面
往下看到DocumentRoot做相關設定,這樣就會正常了
FuelPHP每次連線必warning的修正
WARNING - 2014-07-08 14:06:43 --> Fuel\Core\Fuel::init - The configured locale en_US is not installed on your system.
基本上每次連都會在log留下一次紀錄
然後假使這不是單機測試而是大量使用...那就GG了
註:自己安裝哪個語言可以在linux環境以下用echo $LANG來查看
找到APPPATH/config.php
然後把locale設定弄成空字串,再來訊息就不會再出現了
Linux基本理解
https://drive.google.com/file/d/0Bz9IvLZNUkriLXBqVUJmNFkzeUU/edit?usp=sharing
htacess
不爽,so我偏要先弄出來
以下適用ubuntu 和apt-get的基本架構環境,其他自行調整
1.先phpinfo() 看apache2handler的mod_rewrite有沒有開 沒開就a2enmod rewrite一下
2.ubuntu為例,httpd.conf不存在,這東西只在site avalible裡面的default
default裡面 AllowOverride None 要改掉,怕All會出問題就用Auth
Auth怎運作自行看鳥哥說明
3. .htacess如果已經正確執行,不要在裡面再AllowOverride一次不然會直接ISE
4.真的ISE的話(不一定是3的問題)去看log,會告訴你htacess究竟噴了哪種錯誤,再試圖修正
4-1.一般來說雙向確認方法就是把rewrite功能關掉看是否網頁又正常
5.補充一題,14版ubuntu 的aptget下來的套件的apache2.conf
已經自帶htacess解析 ErrorLog路徑 沒事不要再多寫一次
6.環境不同,網路上查的mods-enabled 以我ubuntu為例,是以分散檔案的方式
存在mods-enabled裡面來設定的,而可設定內容在avalible,並非全部以list方式呈現
註:a2enmod 叫做 apache2 enable module
所以如果要關閉特定模組 就是a2dismod (apache2 disable module)
FuelPHP Note02
官網那個Model寫法是
模組本身
namespace Model;
class xxx extends \Model {
使用時
use \Model\xxx;
呼叫時 xxx::function(etc
不use的呼叫時為\Model\xxx::function(etc
但是遇到extends Model_Crud的時候就掛了,因為不能多重繼承
這時只好利用路徑_檔名的特性
改寫成:
模組本身
class Model_xxx
使用時
use Model_xxx as xxx;
呼叫時 xxx::function(etc
不use的狀況下呼叫為 Model_xxx::function(etc
FuelPHP Bootstrap 聽說有用到爆的Note
注意,FuelPHP的文件,直到你做出實際可跑的結果之前,你應該都看不懂他在寫什麼
那個Example完全只有設定方向,實際可以怎麼用...你還是得自行測試,根本不算Example
相對這個詭異的文件,Code Igniter提供的教學雖然比較簡單,但你可以馬上知道那個MVC運作到底在做什麼,以文件和example來說是相對比較適當的寫法
FuelPHP
1.FuelPHP的header content footer分隔用法要看 控制器=>樣板(template)
2.沒曖昧的膠水需求直接無視viewmodel,真正的view在apppath/view
3.資料庫真正設定位置在apppath/config/development(除非你去bootstrap改過環境)
註:裡面帳號密碼都是root且有優先複寫,只要沒改掉development或改掉帳密有九成會掛
4. Controller Model View用法直接去看Code Igniter的說法比較容易懂
Bootstrap(FuelPHP裡面的CSS)
Bootstrap網路上非常多用舊格式的example,然而Fuelphp使用的是3.0,直接套絕對沒效果
1.由於舊版說明文本仍然是存在的,但由於做法的不同,在3.0是沒有用的
例如大部分默認以最少套用,舊版的表單直接有預設樣式這點,新版是不存在的
2.文字符號寫法有變更,拿舊版class會直接變方框需處理
3.按鈕如果沒有變立體,是因為沒有引入theme的緣故
Counter
Labels
Archive
-
▼
2014
(58)
-
►
09
(15)
- [轉貼]當你還能思考的時候,請不要自己放棄他
- 推薦閱讀的基本
- ubuntu的設定網路別直接改interface檔
- [轉貼]Mysql Prepared Statement
- [轉貼] SQL Describe改(查comment 權限的表)
- [轉貼]你以為一生光明磊落,事事對得起自己良心就沒事了嗎?
- 單元測試的真正意義(10/7更新)
- 舊版fuelphp vs redis 衝突筆記
- 重構程式的時候不要把自己當作業員
- 利用FuelPHP Migration拿建立資料庫的function
- FuelPHP Migration小研究
- ubuntu rename的真正用法
- FuelPHP的short tag
- ubuntu apache預設編碼
- apache多server基本設定
-
►
09
(15)