- 現代PHP, 新的特點及良好習慣
- Modern PHP: New Features and Good Practices
2022年6月12日 星期日
PHP開發筆記 - 書:現代PHP, 新的特點及良好習慣(Modern PHP: New Features and Good Practices)
2022年6月10日 星期五
PHP 開發筆記 - 使用 PHP-CS-FIXER 維護團隊的 Coding Style
% mkdir -p tools/php-cs-fixer% php tools/composer.phar require --working-dir=tools/php-cs-fixer friendsofphp/php-cs-fixer
% cd src% ../tools/php-cs-fixer/vendor/bin/php-cs-fixer fix --dry-run --diff .
% cd src% ../tools/php-cs-fixer/vendor/bin/php-cs-fixer fix .
% cd src% cat composer.json | jq '.scripts'{"test": "phpunit","cs-diff": "../tools/php-cs-fixer/vendor/bin/php-cs-fixer fix --dry-run --diff .","cs": "../tools/php-cs-fixer/vendor/bin/php-cs-fixer fix ."}
% ../tools/composer.phar run-script cs-diff> ../tools/php-cs-fixer/vendor/bin/php-cs-fixer fix --dry-run --diff .Loaded config default.Using cache file ".php-cs-fixer.cache".Checked all files in 0.032 seconds, 12.000 MB memory used
% ../tools/composer.phar run-script cs> ../tools/php-cs-fixer/vendor/bin/php-cs-fixer fix .Loaded config default.Using cache file ".php-cs-fixer.cache".Fixed all files in 0.006 seconds, 12.000 MB memory used
% cat test.php<?php$x = "hello world";$y = "123";% ../tools/php-cs-fixer/vendor/bin/php-cs-fixer fix --dry-run --using-cache=no --rules=@PSR12 -vvv test.phpPHP CS Fixer 3.8.0 BerSzcz against war! by Fabien Potencier and Dariusz Ruminski.PHP runtime: 7.4.29Loaded config default.. 1 / 1 (100%)Legend: ?-unknown, I-invalid file syntax (file ignored), S-skipped (cached or empty file), .-no changes, F-fixed, E-errorChecked all files in 0.005 seconds, 12.000 MB memory used
% ../tools/php-cs-fixer/vendor/bin/php-cs-fixer fix --dry-run --diff --using-cache=no --rules=@PSR12,@Symfony -vvv test.phpPHP CS Fixer 3.8.0 BerSzcz against war! by Fabien Potencier and Dariusz Ruminski.PHP runtime: 7.4.29Loaded config default.F 1 / 1 (100%)Legend: ?-unknown, I-invalid file syntax (file ignored), S-skipped (cached or empty file), .-no changes, F-fixed, E-error1) web/test.php (single_quote, binary_operator_spaces)---------- begin diff ------------- /Volumes/Data/project/src/test.php+++ /Volumes/Data/project/src/test.php@@ -1,5 +1,5 @@<?php- $x = "hello world";+ $x = 'hello world';- $y = "123";+ $y = '123';----------- end diff -----------Checked all files in 0.011 seconds, 12.000 MB memory used
% ../tools/php-cs-fixer/vendor/bin/php-cs-fixer fix --using-cache=no --rules=@PSR12,@Symfony test.phpLoaded config default.1) web/test.phpFixed all files in 0.011 seconds, 12.000 MB memory used% cat test.php<?php$x = 'hello world';$y = '123';
2022年6月8日 星期三
樊登說書
約莫 2021 春天起入坑,接著靠運動時期清書,應該沒八個月規律地刷完一遍,不到四百本書,正在進行複習第二遍,未來就進入每週聽一本書,然後沒啥 podcast 想聽時,繼續挑有興趣的來複習。
從樊登說書的熱門書籍清起,可以很清楚地看到 TA 已經是親子學習為主、商業工具書為輔,但無論如何,都仍是人性議題,帶團隊跟養小孩都還是相互呼應的,稱不上衝突。例如如何鼓勵員工往前邁進,等同於鼓勵小孩如何進步一樣。
我以前也覺得網路上有很多文料,舉凡工作技術文、親子、科普等,認為不需要翻書了,直到被大學室友提醒:片段的文章,跟從頭到尾的書籍,還是有很大的不一樣。現代人的習性也慢慢被切割成只能閱讀零碎的片段。
樊登說書其實厲害的就樊登一人,自己打通任督二脈,以論語中庸當內力,在吸取中內外的書籍,的確如他所言,這個事業搞起來後,自己受益最大,也開始慢跑健身少吃麵食,也持續享受著看書、講書的興趣,推掉不必要聚會,並精實的呼應著讓人一年讀 52本書,另外,也朝向不吃光用戶眼光跟時間,吸收完知識後,關掉 app 去做正經事。其實看一個人功力強不強,就像看廚師炒飯一樣,一本經典書籍內容那麼充沛,有幾位網紅可以好好用 30 分鐘介紹一本書?又有幾位網紅可以串起各類書籍,並且前後呼應而不是自相矛盾?
回顧起 2021 年接觸的 app ,應當就這 app 受益最大。從商務工具書,提醒自己溝通時要著重事實的呈述而非情緒,親子相處時,要多留點時間給小孩,不只陪伴,還包括等待小孩成長。我想,我還是會繼續複習完成二刷吧
樊登說書 熱門書籍 Top 100 清單(說書時間、書名):
2017-03-18 正面管教
2016-07-30 非暴力沟通
2017-04-08 亲密关系
2018-04-28 终身成长
2019-03-30 逆商
2018-12-15 父母的语言
2016-11-19 刻意练习
2015-10-24 关键对话
2017-12-09 可复制的领导力
2017-10-07 高效能人士的七个习惯
2017-01-07 如何让你爱的人爱上你
2018-06-09 即兴演讲
2017-05-20 自卑与超越
2016-01-01 如何培养孩子的社会能力
2019-03-02 应对焦虑
2018-10-27 活好
2013-12-03 你就是孩子最好的玩具
2019-06-01 不管教的勇气
2019-07-20 掌控习惯
2016-12-10 不吼不叫
2016-07-16 如何说孩子才会听,怎么听孩子才肯说
2019-01-12 感受爱
2015-09-18 幸福的婚姻
2018-11-03 认知天性
2020-04-18 陪孩子终身成长
2016-10-15 销售就是要玩转情商
2019-10-12 不妥协的谈判
2019-03-16 列奥纳多·达·芬奇传
2020-01-04 我们都曾受过伤,却有了更好的人生
2019-04-06 能力陷阱
2021-07-10 人生只有一件事
2019-06-15 自尊
2019-08-03 事实
2019-11-09 被忽视的孩子
2018-03-03 他人的力量
2019-04-27 低风险创业
2019-06-08 高效休息法
2020-02-29 思维的囚徒
2019-02-16 用事实说话
2019-05-04 坚毅
2020-09-19 自驱型成长
2020-09-26 活出心花怒放的人生
2018-12-08 思辨与立场
2013-11-25 幸福的方法
2016-02-04 我的情绪为何总被他人左右
2020-09-12 洞见
2018-01-06 反脆弱
2019-05-11 原生家庭
2018-07-07 活法
2019-08-31 解码青春期
2014-01-04 第3选择
2020-02-08 爱、金钱和孩子
2020-04-11 意志力
2018-10-13 掌控谈话
2018-10-06 运动改造大脑
2019-08-17 顾客为什么购买
2021-09-11 心态
2019-11-23 孔子传
2017-11-18 思考,快与慢
2019-04-20 世界观
2020-05-23 斯坦福高效睡眠法
2016-03-26 干法
2016-06-25 你要如何衡量你的人生
2018-08-11 热锅上的家庭
2015-07-03 次第花开
2021-05-22 解惑:心智模式决定你的一生
2018-09-22 一平方米的静心
2020-08-08 陌生人效应
2019-07-13 学会吃饭
2020-09-05 曾国藩的正面与侧面
2019-08-10 身为职场女性
2020-06-20 与内心的恐惧对话
2017-08-05 少有人走的路
2019-12-14 幸福的陷阱
2019-03-23 欲罢不能
2016-12-03 销售洗脑
2019-07-27 道德经说什么
2018-12-01 苏东坡传
2019-03-09 你要的是幸福,还是对错
2019-04-13 掌控
2021-04-17 你好,小孩
2020-11-28 内在动机:自主掌控人生的力量
2018-11-10 扫除道
2015-02-06 叛逆不是孩子的错
2021-05-15 考试脑科学
2018-01-27 深度工作
2018-03-24 心流
2021-04-24 如何克服社交焦虑
2019-02-23 高能量姿势
2019-09-07 分手后,成为更好的自己
2014-03-14 管理十诫
2021-03-20 幸福关系的7段旅程
2016-05-06 养育女孩
2020-07-25 学习的格局
2015-12-12 瞬变
2019-11-16 你为什么不道歉
2017-12-02 恰如其分的自尊
2017-01-21 王阳明哲学
2020-03-28 弹性
2019-05-18 有限与无限的游戏
2022年5月30日 星期一
Go 開發筆記 - 使用 Regular Expression / Regex / Re
- 有兩種 Regular Expression 實現方式 ,其中有 POSIX 關鍵字是 POSIX ERE (egrep) 語法跟效果。
- 初始化有 Compile 跟 MustCompile (對應的是 CompilePOSIX 和 MustCompilePOSIX) ,其中有 Must 字眼是驗證語法錯誤時,會進入 panics 狀態
% cat main.gopackage main// https://pkg.go.dev/regexp// https://pkg.go.dev/regexp/syntaximport ("fmt""regexp")func main() {input := `<html><head><title>study golang</title></head><body><ul><li>changyy.org</li><li>1234567890</li><li>abcdefg</li><li>abcdefgABCDEFG</li><li>abcdef1234567890gABCDEFG</li></ul></body></html>`// Style 1: regexp.Match{matched, err := regexp.Match(`<[A-Za-z]+>(.*?)</[A-Za-z]+>`, []byte(input))if err != nil {fmt.Println("Style 1 - regexp.Match error:", err)} else {fmt.Println("Style 1 - regexp.Match: ", matched)}}// Style 2: regexp.Compile + obj.MatchString// https://pkg.go.dev/regexp#Regexp.MatchString{obj, err := regexp.Compile(`<[A-Za-z]+>(.*?)</[A-Za-z]+>`)if err != nil {fmt.Println("regexp.Compile error:", err)} else {fmt.Println("Style 2 - case 1: ", obj.MatchString(`<title>Hello World</title>`))fmt.Println("Style 2 - case 2: ", obj.MatchString(input))}}// Style 3: regexp.MustCompile + obj.MatchString// https://pkg.go.dev/regexp#Regexp.MatchString{pattern := `<[A-Za-z]+>(.*?)</[A-Za-z]+>`obj := regexp.MustCompile(pattern)fmt.Println("Style 3 - case 1: ", obj.MatchString(`<title>Hello World</title>`))fmt.Println("Style 3 - case 2: ", obj.MatchString(input))}// Style 4: obj.FindString// https://pkg.go.dev/regexp#Regexp.FindString{pattern := `<[A-Za-z]+>(.*?)</[A-Za-z]+>`obj := regexp.MustCompile(pattern)fmt.Println("Style 4 - case 1: ", obj.FindString(`<title>Hello World</title>`))fmt.Println("Style 4 - case 2: ", obj.FindString(input))}// Style 5: obj.FindAllString , obj.FindAllStringIndex// https://pkg.go.dev/regexp#Regexp.FindAllString// https://pkg.go.dev/regexp#Regexp.FindAllStringIndex{pattern := `<[A-Za-z]+>(.*?)</[A-Za-z]+>`obj := regexp.MustCompile(pattern)fmt.Println("Style 5 - case 1: ", obj.FindAllString(`<title>Hello World</title>`, -1))fmt.Println("Style 5 - case 2: ", obj.FindAllString(input, -1))fmt.Println("Style 5 - case 3: ", obj.FindAllStringIndex(`<title>Hello World</title>`, -1))fmt.Println("Style 5 - case 4: ", obj.FindAllStringIndex(input, -1))}// Style 6: obj.FindStringSubmatch , obj.FindStringSubmatchIndex// https://pkg.go.dev/regexp#Regexp.FindStringSubmatch// https://pkg.go.dev/regexp#Regexp.FindStringSubmatchIndex{pattern := `<[A-Za-z]+>(.*?)</[A-Za-z]+>`obj := regexp.MustCompile(pattern)fmt.Println("Style 6 - case 1: ", obj.FindStringSubmatch(`<title>Hello World</title>`))fmt.Println("Style 6 - case 2: ", obj.FindStringSubmatch(input))fmt.Println("Style 6 - case 3: ", obj.FindStringSubmatchIndex(`<title>Hello World</title>`))fmt.Println("Style 6 - case 4: ", obj.FindStringSubmatchIndex(input))}// Style 7: obj.ReplaceAllString// https://pkg.go.dev/regexp#Regexp.ReplaceAllString{pattern := `<[A-Za-z]+>(.*?)</[A-Za-z]+>`obj := regexp.MustCompile(pattern)fmt.Println("Style 7 - case 1: ", obj.ReplaceAllString(`<title>Hello World</title>`, "A"))fmt.Println("Style 7 - case 2: ", obj.ReplaceAllString(input, "B"))}// Style 8: obj.Split// https://pkg.go.dev/regexp#Regexp.Split{pattern := `<[A-Za-z]+>(.*?)</[A-Za-z]+>`obj := regexp.MustCompile(pattern)fmt.Println("Style 8 - case 1: ", len(obj.Split(`<title>Hello World</title>`, -1)))fmt.Println("Style 8 - case 2: ", len(obj.Split(input, -1)))}// Style 9: obj.Longest()// https://pkg.go.dev/regexp#Regexp.FindString// https://pkg.go.dev/regexp#Regexp.Longest{pattern := `a(|b)`obj := regexp.MustCompile(pattern)fmt.Println("Style 9 - case 1: ", obj.FindString(`abb`))obj.Longest()fmt.Println("Style 9 - case 2: ", obj.FindString(`abb`))}}% go run main.goStyle 1 - regexp.Match: trueStyle 2 - case 1: trueStyle 2 - case 2: trueStyle 3 - case 1: trueStyle 3 - case 2: trueStyle 4 - case 1: <title>Hello World</title>Style 4 - case 2: <title>study golang</title>Style 5 - case 1: [<title>Hello World</title>]Style 5 - case 2: [<title>study golang</title> <li>changyy.org</li> <li>1234567890</li> <li>abcdefg</li> <li>abcdefgABCDEFG</li> <li>abcdef1234567890gABCDEFG</li>]Style 5 - case 3: [[0 26]]Style 5 - case 4: [[27 54] [103 123] [136 155] [168 184] [197 220] [233 266]]Style 6 - case 1: [<title>Hello World</title> Hello World]Style 6 - case 2: [<title>study golang</title> study golang]Style 6 - case 3: [0 26 7 18]Style 6 - case 4: [27 54 34 46]Style 7 - case 1: AStyle 7 - case 2:<html><head>B</head><body><ul>BBBBB</ul></body></html>Style 8 - case 1: 2Style 8 - case 2: 7Style 9 - case 1: aStyle 9 - case 2: ab
2022年5月26日 星期四
Go 開發筆記 - 使用 database/sql 通用介面存取資料庫,以 SQLite3 為例
package mainimport ("log""database/sql"_ "github.com/mattn/go-sqlite3")func main() {db, err := sql.Open("sqlite3", "/tmp/sqlite3.db")if err != nil {log.Fatalln(err)}defer db.Close()//// http://go-database-sql.org/modifying.html//// via db.Exec with checking the error message onlyif _, err := db.Exec(`CREATE TABLE IF NOT EXISTS account (uid INTEGER PRIMARY KEY AUTOINCREMENT,username VARCHAR(64) NULL);`); err != nil {log.Println(err)}// Insert via db.Prepareif stmt, err := db.Prepare("INSERT INTO account(username) VALUES(?)"); err == nil {if res, err := stmt.Exec("changyy.org"); err != nil {log.Println("Insert Exec Error:", err)} else if lastId, err := res.LastInsertId() ; err != nil {log.Println("Get LastInsertId Error:", err)} else if rowCount, err := res.RowsAffected() ; err != nil {log.Println("Get RowsAffected Error:", err)} else {log.Println("Insert Done, Last Insert Id:", lastId, ", RowsAffected: ", rowCount)// Update via db.Prepareif stmt, err := db.Prepare("UPDATE account SET username = ? WHERE uid = ?"); err != nil {log.Println("Update Prepqre Error:", err)} else if res, err := stmt.Exec("blog.changyy.org", lastId); err != nil {log.Println("Update Exec Error:", err)} else if rowCount, err := res.RowsAffected() ; err != nil {log.Println("Get RowsAffected Error:", err)} else {log.Println("Update RowsAffected: ", rowCount)}}} else {log.Println("Prepqre Insert Error:", err)}//// http://go-database-sql.org/retrieving.html// https://pkg.go.dev/database/sql#DB.Query//// via db.Query with sql.Rows and error mesasgerows, err := db.Query("SELECT * FROM account")if err != nil {log.Println(err)} else {defer rows.Close()log.Println("Result:")for rows.Next() {var id intvar username stringif err := rows.Scan(&id, &username) ; err == nil {log.Println(id, username)} else {log.Println(err)}}if err := rows.Err() ; err != nil {log.Println(err)}}}
% go run main.go2022/05/25 20:44:26 Insert Done, Last Insert Id: 1 , RowsAffected: 12022/05/25 20:44:26 Update RowsAffected: 12022/05/25 20:44:26 Result:2022/05/25 20:44:26 1 blog.changyy.org% file /tmp/sqlite3.db/tmp/sqlite3.db: SQLite 3.x database, last written using SQLite version 3038005, file counter 3, database pages 3, cookie 0x1, schema 4, UTF-8, version-valid-for 3% sqlite3 /tmp/sqlite3.db .schemaCREATE TABLE account (uid INTEGER PRIMARY KEY AUTOINCREMENT,username VARCHAR(64) NULL);CREATE TABLE sqlite_sequence(name,seq);


