joomla常用的留言板套件有:
Phoca Guestbook
TZ Guestbook => 安裝測試後發現firefox留言lightbox 關掉會有跑板問題
JE Guestbook => 線上demo無法新增留言
本篇採用 Phoca Guestbook
安裝:
到 http://www.phoca.cz/download/category/5-phoca-guestbook-component 下載 Phoca Guestbook (Joomla! 3) - com_phocaguestbook_v3.0.2.zip
到後台Extension Manager => Upload Package File 安裝他
安裝好後你的資料庫會多兩張表:
#__phocaguestbook_items
#__phocaguestbook_logging
新增Guestbook ( 必須先做這步,不然menu那邊Select Guestbook沒得選 )
後台Components => Phoca Guestbook => Guestbooks
新增一個Category..
1. 填寫 Title ="留言板" 和Alias = guestbook
2. 讓訪客也能留言 - 點選 permissions tab => 點選左邊的 Guest=> 將 Post items 改成Allowed
3. 保存
新增guestbook連結:
後台 Menu => Main Menu ( 視你要新增在哪個Menu下而異 ) => Add New menu Item
1. 填寫Menu Title = Phocaguestbook 、Alias = phocaguestbook
2. Menu Item Type 選Phoca Guestbook => Guestbook
3. Select Guestbook 選剛剛新增的Guestbook( 留言板 )
4. 保存
這樣前台Menu就會出現Phocaguestbook 連結 => http://localhost/index.php/phocaguestbook
中文化( 必須先在後台Extensions => Language Manager裡安裝中文 ):
在 http://www.phoca.cz/download/category/5-phoca-guestbook-component 下載語言包
簡體中文 -
下載 Chinese J17 (Simplified Chinese) - zh-CN.com_phocaguestbook.j17.zip 後解壓縮複製檔案到你的joomla/administrator/language/zh-CN/ (後台中文化) 和 joomla/language/zh-CN/ (前台中文化) 下
ex.
前台中文化 -
$ cp zh-CN.com_phocaguestbook.ini /your_joomla_path/language/zh-CN/zh-CN.com_phocaguestbook.ini
$ cp zh-CN.com_phocaguestbook.sys.ini /your_joomla_path/language/zh-CN/zh-CN.com_phocaguestbook.sys.ini
後台中文化 -
$ cp zh-CN.com_phocaguestbook.ini /your_joomla_path/administrator/language/zh-CN/zh-CN.com_phocaguestbook.ini
$ cp zh-CN.com_phocaguestbook.sys.ini /your_joomla_path/administrator/language/zh-CN/zh-CN.com_phocaguestbook.sys.ini
繁體中文 -
下載 Chinese J17 (Traditional Chinese) - zh_TW_com_phocaguestbook_j25.zip 之後步驟一樣,解壓縮後複製到相對應的zh-TW 下
安裝記錄:
我把從開新的joomla到安裝完Phoca Guestbook 並中文化的過程記錄在github上..
https://github.com/kalecgos0616/install_joomla_phoca_guestbook_extenstions
參考資料:
http://www.phoca.cz/forum/viewtopic.php?f=2&t=22062
2015年1月31日 星期六
2015年1月30日 星期五
arch 安裝ejabberd
系統:
Arch Linux
ejabberd 14.12-1 #新的版本和舊的設定有所不同,設定檔是 ejabberd.yml
安裝:
# pacman -S ejabberd
手冊:
# ejabberdctl --help
設定檔目錄: /etc/ejabberd
ejabberd設定檔: /etc/ejabberd/ejabberd.yml
ejabberdctl設定檔: /etc/ejabberd/ejabberdctl.cfg
log目錄: /var/log/ejabberd
資料庫目錄: /var/lib/ejabberd
ejabberd node name: ejabberd@localhost
註冊帳號:
# ejabberdctl register bear test.localhost 123456 # 註冊 test.localhost 這個domain的帳號
設定ejabberd.yml(注意:需要兩格空白縮進),把bear在test.localhost帳號以管理者登錄:
重開機後啟動
# ejabberdctl --node bear@test.localhost start #要先啟動這個
# systemctl start ejabberd
查bear@test.localhost這個node有沒有跑:
# ejabberdctl --node bear@test.localhost status
因為ejabberd 資料庫是用Mnesia,而這個系統儲存Erlang node name到備份檔。移除ejabberd後這些資料都還會在,更多erlang mnesiak的操作需另外研究
Arch Linux
ejabberd 14.12-1 #新的版本和舊的設定有所不同,設定檔是 ejabberd.yml
安裝:
# pacman -S ejabberd
手冊:
# ejabberdctl --help
設定檔目錄: /etc/ejabberd
ejabberd設定檔: /etc/ejabberd/ejabberd.yml
ejabberdctl設定檔: /etc/ejabberd/ejabberdctl.cfg
log目錄: /var/log/ejabberd
資料庫目錄: /var/lib/ejabberd
ejabberd node name: ejabberd@localhost
註冊帳號:
# ejabberdctl register bear test.localhost 123456 # 註冊 test.localhost 這個domain的帳號
設定ejabberd.yml(注意:需要兩格空白縮進),把bear在test.localhost帳號以管理者登錄:
88c88,89 - - "localhost" --- + ## - "localhost" + - "test.localhost" 390,393c391,394 - ## admin: - ## user: - ## - "aleksey": "localhost" - ## - "ermine": "example.org" --- + admin: + user: + - "aleksey": "localhost" + - "bear": "test.localhost"
重開機後啟動
# ejabberdctl --node bear@test.localhost start #要先啟動這個
# systemctl start ejabberd
查bear@test.localhost這個node有沒有跑:
# ejabberdctl --node bear@test.localhost status
因為ejabberd 資料庫是用Mnesia,而這個系統儲存Erlang node name到備份檔。移除ejabberd後這些資料都還會在,更多erlang mnesiak的操作需另外研究
2015年1月29日 星期四
git-ftp心得
git-ftp有兩種解法
https://github.com/ezyang/git-ftp ( 可搭配hook,只傳新檔案和移除舊檔案 )
https://github.com/git-ftp/git-ftp ( 傳tracked的檔案 )
https://github.com/git-ftp/git-ftp
安裝:
# apt-get install git-ftp
使用(在 client repository):
$ git ftp init -u username -p password - ftp://your.ftp.domain/htdocs/ #第一次要用init
or
$ git ftp push -u username -p password - ftp://your.ftp.domain/htdocs/
https://github.com/ezyang/git-ftp ( 搭配hooks的 post-receive )
安裝:
# apt-get install python-setuptools ( 如果沒有easy_install,就先裝這個 )
# easy_install gitpython
在remote repository上根目錄建立 ftpdata ( 與config, HEAD同一層 ):
在hooks下建立 post-receive(權限775,直接複製github上的內容):
在hooks下建立 git-ftp.py(權限775,直接複製github上的內容):
略
然後在client repository,git push後 就會更新程式到ftp上去
參考資料:
http://stackoverflow.com/questions/2950107/git-push-into-production-ftp
https://github.com/ezyang/git-ftp ( 可搭配hook,只傳新檔案和移除舊檔案 )
https://github.com/git-ftp/git-ftp ( 傳tracked的檔案 )
https://github.com/git-ftp/git-ftp
安裝:
# apt-get install git-ftp
使用(在 client repository):
$ git ftp init -u username -p password - ftp://your.ftp.domain/htdocs/ #第一次要用init
or
$ git ftp push -u username -p password - ftp://your.ftp.domain/htdocs/
https://github.com/ezyang/git-ftp ( 搭配hooks的 post-receive )
安裝:
# apt-get install python-setuptools ( 如果沒有easy_install,就先裝這個 )
# easy_install gitpython
在remote repository上根目錄建立 ftpdata ( 與config, HEAD同一層 ):
[master] username=ftp_username password=ftp_password hostname=your.ftp.domain remotepath=/htdocs #你的ftp上傳路徑 ssl=no #如果ftp 不支援https ,要改no
在hooks下建立 post-receive(權限775,直接複製github上的內容):
#!/bin/bash # You may install this post-receive hook in your remote git repository # to have automatic file upload when pushing to the repository. while read OLD_COMMIT NEW_COMMIT REFNAME; do BRANCH=${REFNAME#refs/heads/} if [[ `grep "^\[$BRANCH\]$" ftpdata` ]]; then echo "Uploading $BRANCH..." $(dirname $(readlink -f "$0"))/git-ftp.py -b "$BRANCH" -c "$NEW_COMMIT" || exit $? fi done true
在hooks下建立 git-ftp.py(權限775,直接複製github上的內容):
略
然後在client repository,git push後 就會更新程式到ftp上去
參考資料:
http://stackoverflow.com/questions/2950107/git-push-into-production-ftp
apt-get 安裝出現 fork failed: Cannot allocate memory錯誤
在安裝git-ftp時出現下面這個錯誤
# apt-get -f install git-ftp
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following NEW packages will be installed:
git-ftp
0 upgraded, 1 newly installed, 0 to remove and 42 not upgraded.
Need to get 0 B/14.6 kB of archives.
After this operation, 77.8 kB of additional disk space will be used.
dpkg: unrecoverable fatal error, aborting:
fork failed: Cannot allocate memory
E: Sub-process /usr/bin/dpkg returned an error code (2)
原因:
用 free -m 或 top 看,發現所剩的記憶體太少了
解法:
把apache或gitlab關掉 再裝
# service apache2 stop
or
# gitlab-ctl stop
# apt-get -f install git-ftp
... 安裝成功
# apt-get -f install git-ftp
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following NEW packages will be installed:
git-ftp
0 upgraded, 1 newly installed, 0 to remove and 42 not upgraded.
Need to get 0 B/14.6 kB of archives.
After this operation, 77.8 kB of additional disk space will be used.
dpkg: unrecoverable fatal error, aborting:
fork failed: Cannot allocate memory
E: Sub-process /usr/bin/dpkg returned an error code (2)
原因:
用 free -m 或 top 看,發現所剩的記憶體太少了
解法:
把apache或gitlab關掉 再裝
# service apache2 stop
or
# gitlab-ctl stop
# apt-get -f install git-ftp
... 安裝成功
2015年1月28日 星期三
使用git hooks管理網站
本地倉庫
$ cd ~/test/
$ mkdir website && cd website
$ git init
$ echo 'Hello, world!' > index.html
$ git add index.html
$ git commit -q -m "The humble beginnings of my web site."
註: git commit -q 是--quiet ,抑制commit 時的訊息
遠端倉庫 ( 我在同一個file system下測試,沒用ssh )
$ cd ~/test/
$ mkdir website.git && cd website.git
$ git init --bare
在website.git 資料夾下繼續操作:
$ mkdir ~/test/www.example.org
$ cat > hooks/post-receive
#!/bin/sh
GIT_WORK_TREE=/home/bear/test/www.example.org git checkout -f
$ chmod +x hooks/post-receive
註:
post- 是 "後" 的意思,遠端倉庫在收到commit後所作的動作
chmod +x 把檔案權限變成755
回到本地倉庫繼續操作
$ cd ~/test/
$ git remote add web file:///home/bear/test/website.git
$ git push web +master:refs/heads/master
簡化push的動作
$ git push --set-upstream web master #設定一次就可以了
$ git push web
檢查
在 /home/bear/test/website.git 中檢查push上來的檔案有沒有被更新
hook 有分 用戶端掛鉤 和 伺服器端掛鉤
用戶端掛鉤
位置在 ~/test/website/.git/hooks ,sample檔是bash寫的,可以用其他語言,如perl寫,只需要在第一行指定 #!/usr/bin/perl ,記得把權限改成755 ,script最後只要exit 1 就會被中止,
執行順序:
pre-commit => commit-msg => post-commit ( 我沒測 prepare-commit-msg,但我想應該是在 pre-commit和commit-msg之間 )
以 commit-msg 為例:
commit-msg 掛鉤接收一個參數,此參數是包含最近提交資訊的暫存檔路徑( .git/COMMIT_EDITMSG )。
bash 收這個參數是 $1,perl 是 $ARGV[0]
有了這些掛鉤就能客製化開發者們在commit 時限制commit message的格式,外掛jslint檢查程式碼,檢查行尾有無空白,沒有錯誤才push到伺服器上
伺服器端掛鉤
pre-receive
post-receive # 上面的例子有用到這個
update
參考資料:
http://toroid.org/ams/git-website-howto
http://git-scm.com/book/zh-tw/v1/Git-%E5%AE%A2%E8%A3%BD%E5%8C%96-Git-Hooks #hook相關屬性
$ cd ~/test/
$ mkdir website && cd website
$ git init
$ echo 'Hello, world!' > index.html
$ git add index.html
$ git commit -q -m "The humble beginnings of my web site."
註: git commit -q 是--quiet ,抑制commit 時的訊息
遠端倉庫 ( 我在同一個file system下測試,沒用ssh )
$ cd ~/test/
$ mkdir website.git && cd website.git
$ git init --bare
在website.git 資料夾下繼續操作:
$ mkdir ~/test/www.example.org
$ cat > hooks/post-receive
#!/bin/sh
GIT_WORK_TREE=/home/bear/test/www.example.org git checkout -f
$ chmod +x hooks/post-receive
註:
post- 是 "後" 的意思,遠端倉庫在收到commit後所作的動作
chmod +x 把檔案權限變成755
回到本地倉庫繼續操作
$ cd ~/test/
$ git remote add web file:///home/bear/test/website.git
$ git push web +master:refs/heads/master
簡化push的動作
$ git push --set-upstream web master #設定一次就可以了
$ git push web
檢查
在 /home/bear/test/website.git 中檢查push上來的檔案有沒有被更新
hook 有分 用戶端掛鉤 和 伺服器端掛鉤
用戶端掛鉤
位置在 ~/test/website/.git/hooks ,sample檔是bash寫的,可以用其他語言,如perl寫,只需要在第一行指定 #!/usr/bin/perl ,記得把權限改成755 ,script最後只要exit 1 就會被中止,
執行順序:
pre-commit => commit-msg => post-commit ( 我沒測 prepare-commit-msg,但我想應該是在 pre-commit和commit-msg之間 )
以 commit-msg 為例:
commit-msg 掛鉤接收一個參數,此參數是包含最近提交資訊的暫存檔路徑( .git/COMMIT_EDITMSG )。
bash 收這個參數是 $1,perl 是 $ARGV[0]
有了這些掛鉤就能客製化開發者們在commit 時限制commit message的格式,外掛jslint檢查程式碼,檢查行尾有無空白,沒有錯誤才push到伺服器上
伺服器端掛鉤
pre-receive
post-receive # 上面的例子有用到這個
update
參考資料:
http://toroid.org/ams/git-website-howto
http://git-scm.com/book/zh-tw/v1/Git-%E5%AE%A2%E8%A3%BD%E5%8C%96-Git-Hooks #hook相關屬性
linux解壓縮亂碼
解压zip文件乱码
在Ubuntu下使用unzip解压Widnows环境下天生的zip文件,会发生文件名或者目录名乱码现象,解决办法是使用 7-zip和convmv。
安装7-zip和convmv:
$ sudo apt-get install convmv p7zip-full
解压zip文件:( 需該資料夾下沒其他檔案,再解壓縮 )
$ LANG=C 7z e zip_file
$ convmv -f gbk -t utf8 -r --notest *
unzip直接解壓縮後,在文件管理器中檔名是 -Ѧ�Ψ++-+.pdf(無效的編碼) 。這樣用這招才能用
若在網頁信箱附件中檔名就已經是亂碼了,目前無法解決
參考資料:
http://nyc1991.blog.51cto.com/6424159/1132023
在Ubuntu下使用unzip解压Widnows环境下天生的zip文件,会发生文件名或者目录名乱码现象,解决办法是使用 7-zip和convmv。
安装7-zip和convmv:
$ sudo apt-get install convmv p7zip-full
解压zip文件:( 需該資料夾下沒其他檔案,再解壓縮 )
$ LANG=C 7z e zip_file
$ convmv -f gbk -t utf8 -r --notest *
unzip直接解壓縮後,在文件管理器中檔名是 -Ѧ�Ψ++-+.pdf(無效的編碼) 。這樣用這招才能用
若在網頁信箱附件中檔名就已經是亂碼了,目前無法解決
參考資料:
http://nyc1991.blog.51cto.com/6424159/1132023
WPS心得
因為工作電腦用linux的關係,避免偶爾要做文件時變成白痴,所以把一些技巧寫下來...
修改英文字型成consolas -
开始 - “AaBbCcD正文” 方块 - 右鍵”修改样式” - 把他設成Consolas
單引號和雙引號會變成中文的單雙引號
=> 點選左上角"WPS文字"旁的小箭頭 => 工具=>選項=>編輯=>自動更正=>取消勾選"自動轉換英文引號為中文引號" =>完成
WPS for Linux提示“系统缺失字体symbol、wingdings、wingdings 2、wingdings 3、webding”的解决方法
http://bbs.wps.cn/thread-22355435-1-1.html
用qq登錄後下載wps_symbol_fonts.zip 檔,把他解壓縮到 ~/.font/下,重啟WPS
=> 同時解決下面兩個問題:
1. 超連結 無法自動變成網址,必須手動新增
2. 第1. 2. 3.點無法自動完成,必須點圖示設定
減少行距
選取兩行後點右鍵 => 段落(P) => 間距 前段:0行,後段:0行, 行距:最小值 ,設置值:0 磅
項目符號和編碼 ( 項目1. 2. 3. ... 的格式 )
選取一行後點右鍵 => 項目符號和編碼 => 選你要的格式,我選 多級編號 的最後一個 => 自定義 => 字體 => 西文字體 和 複雜文種字體 調成 Consolas (之後編號我就調不成字體了)
別行要跟著加入此編碼:
選取一行後點右鍵 => 項目符號和編碼 => 自定義列表 => 選上面第一個有定義的 => 繼續前一列表 => 確定
設定目錄
點右下角的 大綱視圖 或是上方的 視圖 => 大綱
記得調成 顯示所有級別 ,把你要的那行調成你要的目錄級數
設定好後 關閉 => 上方的 引用 => 插入目錄
之後有調整目錄 就選 更新目錄 => 更新整個目錄
設定完目錄就能在最上方的目錄上 ctrl + 左鍵 ,可以跳到該目錄頁面,類似網頁的錨點
如何在Excel表格中換行
https://tw.answers.yahoo.com/question/index?qid=20100828000015KK09103
在同一個儲存格中換行:ALT+ENTER
在Excel裡,讓標題固定在上方,捲動時也不會改變位置
選擇第一列 => 視圖 => 凍結視窗
修改英文字型成consolas -
开始 - “AaBbCcD正文” 方块 - 右鍵”修改样式” - 把他設成Consolas
單引號和雙引號會變成中文的單雙引號
=> 點選左上角"WPS文字"旁的小箭頭 => 工具=>選項=>編輯=>自動更正=>取消勾選"自動轉換英文引號為中文引號" =>完成
WPS for Linux提示“系统缺失字体symbol、wingdings、wingdings 2、wingdings 3、webding”的解决方法
http://bbs.wps.cn/thread-22355435-1-1.html
用qq登錄後下載wps_symbol_fonts.zip 檔,把他解壓縮到 ~/.font/下,重啟WPS
=> 同時解決下面兩個問題:
1. 超連結 無法自動變成網址,必須手動新增
2. 第1. 2. 3.點無法自動完成,必須點圖示設定
減少行距
選取兩行後點右鍵 => 段落(P) => 間距 前段:0行,後段:0行, 行距:最小值 ,設置值:0 磅
項目符號和編碼 ( 項目1. 2. 3. ... 的格式 )
選取一行後點右鍵 => 項目符號和編碼 => 選你要的格式,我選 多級編號 的最後一個 => 自定義 => 字體 => 西文字體 和 複雜文種字體 調成 Consolas (之後編號我就調不成字體了)
別行要跟著加入此編碼:
選取一行後點右鍵 => 項目符號和編碼 => 自定義列表 => 選上面第一個有定義的 => 繼續前一列表 => 確定
設定目錄
點右下角的 大綱視圖 或是上方的 視圖 => 大綱
記得調成 顯示所有級別 ,把你要的那行調成你要的目錄級數
設定好後 關閉 => 上方的 引用 => 插入目錄
之後有調整目錄 就選 更新目錄 => 更新整個目錄
設定完目錄就能在最上方的目錄上 ctrl + 左鍵 ,可以跳到該目錄頁面,類似網頁的錨點
如何在Excel表格中換行
https://tw.answers.yahoo.com/question/index?qid=20100828000015KK09103
在同一個儲存格中換行:ALT+ENTER
在Excel裡,讓標題固定在上方,捲動時也不會改變位置
選擇第一列 => 視圖 => 凍結視窗
2015年1月22日 星期四
使用百度地圖API
做網站要內嵌地圖時,因為google地圖在國內會被牆,所以申請了百度地圖的api
http://developer.baidu.com/map/
選web開發=> javascript大眾版 => 示例Demo =>逆/地址解析 => 地址解析 (選這個才能輸入地址去定位)
直接的demo連結:
http://developer.baidu.com/map/jsdemo.htm#i7_1
接著要弄到ak key
( 弄到ak key之前要申請成為百度開發者,註冊流程會導到輕應用 http://qing.baidu.com/console# 這邊,ak key不是在這邊拿到的請注意 )
取得ak key:
http://lbsyun.baidu.com/apiconsole/key
創建應用 => 應用類型選瀏覽器 => IP白名单打 "*"
然後就能複製代碼在本機測試了
代碼:
自己寫css調整地圖大小:
实现多点标注及显示提示信息 (全國經銷商圖)
使用百度地圖工具產生
http://api.map.baidu.com/lbsapi/creatmap/
如果要看全中國地圖,定位中心点 => 当前城市 =>搜尋"全國"
添加标注 => 可以選擇標注的樣式、地點、說明(甚至你做出來後可以添加圖片, 如 http://blog.csdn.net/u013310075/article/details/24435869 上修改一些js可以辦到 )
如果要放在google blogger上,因為會被blogger的css影響到,要調一下CSS:
#dituContent #platform img { padding: 0; background: transparent; } /* #dituContent 是 百度地图容器 的div id*/
padding: 0; => 取消地圖上的白邊
background: transparent; => 讓標駐點陰影透明
實例:
同一個網頁有兩張地圖
百度地圖API不支援同一頁有兩個地圖,另一張可使用騰訊地圖 ( http://api.map.soso.com/doc/ )
參考資料:
http://blog.csdn.net/u013310075/article/details/24435869 百度地图之调用javaScript api接口实现多点标注及显示提示信息 (較舊)
http://api.map.baidu.com/lbsapi/creatmap/ 百度地圖API工具
http://developer.baidu.com/map/
選web開發=> javascript大眾版 => 示例Demo =>逆/地址解析 => 地址解析 (選這個才能輸入地址去定位)
直接的demo連結:
http://developer.baidu.com/map/jsdemo.htm#i7_1
接著要弄到ak key
( 弄到ak key之前要申請成為百度開發者,註冊流程會導到輕應用 http://qing.baidu.com/console# 這邊,ak key不是在這邊拿到的請注意 )
取得ak key:
http://lbsyun.baidu.com/apiconsole/key
創建應用 => 應用類型選瀏覽器 => IP白名单打 "*"
然後就能複製代碼在本機測試了
代碼:
<script src="http://api.map.baidu.com/api?v=2.0&ak=你的ak_key" type="text/javascript"></script> <div id="allmap"> </div> <script type="text/javascript"> // 百度地图API功能 var map = new BMap.Map("allmap"); var point = new BMap.Point(116.331398,39.897445); map.centerAndZoom(point,12); // 创建地址解析器实例 var myGeo = new BMap.Geocoder(); // 将地址解析结果显示在地图上,并调整地图视野 myGeo.getPoint("你的地址", function(point){ if (point) { map.centerAndZoom(point, 16); map.addOverlay(new BMap.Marker(point)); } }, "你的城市"); </script>
自己寫css調整地圖大小:
#allmap { width: 100px; height: 100px; }
实现多点标注及显示提示信息 (全國經銷商圖)
使用百度地圖工具產生
http://api.map.baidu.com/lbsapi/creatmap/
如果要看全中國地圖,定位中心点 => 当前城市 =>搜尋"全國"
添加标注 => 可以選擇標注的樣式、地點、說明(甚至你做出來後可以添加圖片, 如 http://blog.csdn.net/u013310075/article/details/24435869 上修改一些js可以辦到 )
如果要放在google blogger上,因為會被blogger的css影響到,要調一下CSS:
#dituContent #platform img { padding: 0; background: transparent; } /* #dituContent 是 百度地图容器 的div id*/
padding: 0; => 取消地圖上的白邊
background: transparent; => 讓標駐點陰影透明
實例:
同一個網頁有兩張地圖
百度地圖API不支援同一頁有兩個地圖,另一張可使用騰訊地圖 ( http://api.map.soso.com/doc/ )
參考資料:
http://blog.csdn.net/u013310075/article/details/24435869 百度地图之调用javaScript api接口实现多点标注及显示提示信息 (較舊)
http://api.map.baidu.com/lbsapi/creatmap/ 百度地圖API工具
php使用curl上傳檔案
起因:
在設計API時有上傳檔案的需求,上傳檔案必須用POST送,不能用GET... 怎麼辦呢?
Server 假設用php收資料,get_request.php:
使用Linux的curl:
GET:
$ curl "http://localhost/get_request.php?b=1"
結果:
$_REQUEST:Array
(
[b] => 1
)
$_FILES:Array
(
)
$_POST:Array
(
)
$_GET:Array
(
[b] => 1
)
POST:
$ curl --data "a=2&b=3" "http://localhost/get_request.php"
結果:
$_REQUEST:Array
(
[a] => 2
[b] => 3
)
$_FILES:Array
(
)
$_POST:Array
(
[a] => 2
[b] => 3
)
$_GET:Array
(
)
https連結
http://stackoverflow.com/questions/10079707/https-connection-using-curl-from-command-line
$ curl -k "https://whatever.com/script.php"
上傳檔案:
$ curl -F "file=@chrome.jpg;filename=nameinpost" -F "a=2" http://localhost/get_request.php?b=1
結果:
$_REQUEST:Array
(
[b] => 1
[a] => 2
)
$_FILES:Array
(
[file] => Array
(
[name] => nameinpost
[type] => image/jpeg
[tmp_name] => /tmp/phpNKmLsv
[error] => 0
[size] => 4164
)
)
$_POST:Array
(
[a] => 2
)
$_GET:Array
(
[b] => 1
)
註:
-F 指定檔案, 之後要post資料一樣要-F ,"file=@chrome.jpg;filename=nameinpost",filename= 可以指定新的上傳檔案名稱
ps. 如果遇到server有做 HTTP authentication ,用curl如何認證?
$ curl http://user:password@example.org/
或
$ curl -u user:password http://example.org/
使用php的curl函數,curl.php:
結果:
$_REQUEST:Array
(
[bear] => 2
[a] => 123
)
$_FILES:Array
(
[userfile] => Array
(
[name] => chrome.jpg
[type] => application/octet-stream
[tmp_name] => /tmp/phpilTGG5
[error] => 0
[size] => 4164
)
)
$_POST:Array
(
[a] => 123
)
$_GET:Array
(
[bear] => 2
)
參考資料:
http://stackoverflow.com/questions/14978411/http-post-and-get-using-curl-in-linux
http://evelynnote.blogspot.sg/2011/03/curl.html 更多的curl 指令用法
http://blog.roodo.com/esabear/archives/16358749.html
在設計API時有上傳檔案的需求,上傳檔案必須用POST送,不能用GET... 怎麼辦呢?
Server 假設用php收資料,get_request.php:
echo "\$_REQUEST:"; print_r($_REQUEST); echo "\$_FILES:"; print_r($_FILES); echo "\$_POST:"; print_r($_POST); echo "\$_GET:"; print_r($_GET);
使用Linux的curl:
GET:
$ curl "http://localhost/get_request.php?b=1"
結果:
$_REQUEST:Array
(
[b] => 1
)
$_FILES:Array
(
)
$_POST:Array
(
)
$_GET:Array
(
[b] => 1
)
POST:
$ curl --data "a=2&b=3" "http://localhost/get_request.php"
結果:
$_REQUEST:Array
(
[a] => 2
[b] => 3
)
$_FILES:Array
(
)
$_POST:Array
(
[a] => 2
[b] => 3
)
$_GET:Array
(
)
https連結
http://stackoverflow.com/questions/10079707/https-connection-using-curl-from-command-line
$ curl -k "https://whatever.com/script.php"
上傳檔案:
$ curl -F "file=@chrome.jpg;filename=nameinpost" -F "a=2" http://localhost/get_request.php?b=1
結果:
$_REQUEST:Array
(
[b] => 1
[a] => 2
)
$_FILES:Array
(
[file] => Array
(
[name] => nameinpost
[type] => image/jpeg
[tmp_name] => /tmp/phpNKmLsv
[error] => 0
[size] => 4164
)
)
$_POST:Array
(
[a] => 2
)
$_GET:Array
(
[b] => 1
)
註:
-F 指定檔案, 之後要post資料一樣要-F ,"file=@chrome.jpg;filename=nameinpost",filename= 可以指定新的上傳檔案名稱
ps. 如果遇到server有做 HTTP authentication ,用curl如何認證?
$ curl http://user:password@example.org/
或
$ curl -u user:password http://example.org/
使用php的curl函數,curl.php:
$toURL = "http://localhost/get_request.php?b=1"; $post = array( "a"=>"2", "userfile"=>"@chrome.jpg", //檔案若和程式在同一目錄或相對目錄, 可以用getcwd(), 如: // "userfile"=>"@".getcwd()."/oxox.doc", // 另外還可以在檔名後面加上分號指定mimetype(較新版的PHP才能使用) // (預設的 mimetype 為application/octet-stream) // "userfile"=>"@".getcwd()."\\somePic.png;type=image/png" ); $ch = curl_init(); $options = array( CURLOPT_URL=>$toURL, CURLOPT_POST=>true, CURLOPT_POSTFIELDS=>$post, // 直接給array ); curl_setopt_array($ch, $options); curl_exec($ch); curl_close($ch);$ php curl.php
結果:
$_REQUEST:Array
(
[bear] => 2
[a] => 123
)
$_FILES:Array
(
[userfile] => Array
(
[name] => chrome.jpg
[type] => application/octet-stream
[tmp_name] => /tmp/phpilTGG5
[error] => 0
[size] => 4164
)
)
$_POST:Array
(
[a] => 123
)
$_GET:Array
(
[bear] => 2
)
參考資料:
http://stackoverflow.com/questions/14978411/http-post-and-get-using-curl-in-linux
http://evelynnote.blogspot.sg/2011/03/curl.html 更多的curl 指令用法
http://blog.roodo.com/esabear/archives/16358749.html
2015年1月21日 星期三
MySQL REPLACE INTO和INSERT INTO ... ON DUPLICATE KEY UPDATE區別
這兩種方式的作用是如果資料庫中存在記錄就更新,否則就插入新記錄,但是在使用上也是有一點區別的
總結如下:
1. 如果表中不存在主鍵記錄,REPLACE和INSERT*UPDATE都與INSERT是一樣的特點。
2. 如果表中存在主鍵記錄,REPLACE相當於執行DELETE 和 INSERT兩條操作,而INSERT*UPDATE的相當於執行if exist do update else do insert操作。因此,如果REPLACE填充的字段不全,則會導致未被更新的字段都會修改為默認值,並且如果有自增ID的話,自增ID會變化為最新的值(這樣如果是以自增ID為標誌的話可能導致記錄丟失);而INSERT*UPDATE只是更新部分字段,對於未被更新的字段不會變化(不會強制修改為默認值)。
測試:
建一張表:
-- 資料表結構 `user` CREATE TABLE IF NOT EXISTS `user` ( `id` int(11) NOT NULL, `name` varchar(255) NOT NULL, `phone` varchar(255) NOT NULL, `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8; -- 初始資料 `user` INSERT INTO `user` (`id`, `name`, `phone`, `update_time`) VALUES (1, 'bear', '12345', NOW()), (2, 'ted', '54321', NOW()); -- 資料表索引 `user` ALTER TABLE `user` ADD PRIMARY KEY (`id`), ADD UNIQUE KEY `phone` (`phone`);
使用replace into更新
mysql > replace into user(id, name) select 1, 'bear new_name';
結果:
+----+---------------+-------------+---------------------+ | id | name | phone | update_time | +----+---------------+-------------+---------------------+ | 1 | bear new_name | | 2015-01-21 15:20:08 | | 2 | ted | 54321 | 2015-01-21 14:36:33 | +----+---------------+-------------+---------------------+沒填的欄位phone會變成預設值,會先執行delect再insert
使用INSERT INTO ... ON DUPLICATE KEY UPDATE更新
mysql > insert into user(id) select '2' on duplicate key update name='ted new_name';
結果:
+----+---------------+-------+---------------------+ | id | name | phone | update_time | +----+---------------+-------+---------------------+ | 1 | bear new_name | | 2015-01-21 15:20:08 | | 2 | ted new_name | 54321 | 2015-01-21 15:25:54 | +----+---------------+-------+---------------------+沒填的欄位不會被取代成預設值
使用INSERT INTO ... ON DUPLICATE KEY UPDATE新增資料
mysql > insert into user(id, name, phone) select NULL, 'wes', '56789' on duplicate key update name='wes new_name', phone='98765';
結果:
+----+---------------+-------+---------------------+ | id | name | phone | update_time | +----+---------------+-------+---------------------+ | 1 | bear new_name | | 2015-01-21 15:20:08 | | 2 | ted new_name | 54321 | 2015-01-21 15:25:54 | | 3 | wes | 56789 | 2015-01-21 15:28:55 | +----+---------------+-------+---------------------+新增的資料會是select裡面的資料而不是update後面的資料
參考資料:
http://www.blogjava.net/xylz/archive/2010/06/23/324242.html
2015年1月20日 星期二
gitlab 心得
使用Omnibus package embed安装的gitlab
https://about.gitlab.com/downloads/
路徑放在:
/var/opt/gitlab/
而非
/home/git/gitlab/ 下
重啟gitlab:
gitlab-ctl restart #重啟動後刷頁要等一段時間,而非像apache馬上生效
而非
/etc/init.d/gitlab restart
設定檔在:
/var/opt/gitlab/gitlab-shell/config.yml
log檔在:
tail -f /var/log/gitlab/nginx/gitlab_error.log
tail -f /var/log/gitlab/nginx/gitlab_access.log
查gitlab版本
http://yourdomain/help
git push錯誤:(這是突發事件,之前用正常)
$ git push -u origin master
Agent admitted failure to sign using the key.
Access denied.
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
修改config.yml的
gitlab_url: "http://domain" # "http://domain:8080(/)", "http://wlan_ip(/)", "http://wlan_ip:8080(/)", "http://localhost:8080(/)", "http://localhost(/)"
self_signed_cert:false => true
都無解
暴力解法:
去 /var/opt/gitlab/git-data/repositories/username 下
因為這邊在gitlab GUI介面沒開project-new.git資料夾出來,所以推上去找不到地方存
/var/opt/gitlab/git-data/repositories/bear# ls
project-old.git project-old.wiki.git project-new.wiki.git ( 沒開project-new.git )
隨便cp一個舊的project,然後把使用者改git:git,權限改777(不改777可以拉下來但推上去gitlab會沒紀錄)
# cp -r project-old.git project-new.git
# chown git:git -R project-new.git
# chmod 777 -R project-new.git
這樣在http://domain/username/project-new/commits/master 下就可以看到log了,只是會帶舊的log在裡面,我試過開新的project-new然後git init --bare,ln -s hooks /opt/gitlab/embedded/service/gitlab-shell/hooks ,但無效,gitlab看不到專案
....過了幾個小時候,又可以正常用了,看來是偶發事件....不確定跟我中間reboot重啟機契友沒有關係
更改gitlab後台repo的網址
將gitlab後台網址
git@li8xx-xxx.members.linode.com:root/test.git
改成
git@your.domain:root/test.git
修改 /opt/gitlab/embedded/service/gitlab-rails/config/gitlab.yml
host:li8xx-xxx.members.linode.com => your.domain
重啟gitlab
# gitlab-ctl restart
https://about.gitlab.com/downloads/
路徑放在:
/var/opt/gitlab/
而非
/home/git/gitlab/ 下
重啟gitlab:
gitlab-ctl restart #重啟動後刷頁要等一段時間,而非像apache馬上生效
而非
/etc/init.d/gitlab restart
設定檔在:
/var/opt/gitlab/gitlab-shell/config.yml
log檔在:
tail -f /var/log/gitlab/nginx/gitlab_error.log
tail -f /var/log/gitlab/nginx/gitlab_access.log
查gitlab版本
http://yourdomain/help
git push錯誤:(這是突發事件,之前用正常)
$ git push -u origin master
Agent admitted failure to sign using the key.
Access denied.
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
修改config.yml的
gitlab_url: "http://domain" # "http://domain:8080(/)", "http://wlan_ip(/)", "http://wlan_ip:8080(/)", "http://localhost:8080(/)", "http://localhost(/)"
self_signed_cert:
都無解
暴力解法:
去 /var/opt/gitlab/git-data/repositories/username 下
因為這邊在gitlab GUI介面沒開project-new.git資料夾出來,所以推上去找不到地方存
/var/opt/gitlab/git-data/repositories/bear# ls
project-old.git project-old.wiki.git project-new.wiki.git ( 沒開project-new.git )
隨便cp一個舊的project,然後把使用者改git:git,權限改777(不改777可以拉下來但推上去gitlab會沒紀錄)
# cp -r project-old.git project-new.git
# chown git:git -R project-new.git
# chmod 777 -R project-new.git
這樣在http://domain/username/project-new/commits/master 下就可以看到log了,只是會帶舊的log在裡面,我試過開新的project-new然後git init --bare,ln -s hooks /opt/gitlab/embedded/service/gitlab-shell/hooks ,但無效,gitlab看不到專案
....過了幾個小時候,又可以正常用了,看來是偶發事件....不確定跟我中間reboot重啟機契友沒有關係
更改gitlab後台repo的網址
將gitlab後台網址
git@li8xx-xxx.members.linode.com:root/test.git
改成
git@your.domain:root/test.git
修改 /opt/gitlab/embedded/service/gitlab-rails/config/gitlab.yml
host:
重啟gitlab
# gitlab-ctl restart
2015年1月19日 星期一
git合併兩個現有repos的紀錄到同一個repos
假設要把mp3合併到mp2(主要)
下載兩個repos並進入其中主要的branch
$ git clone git@your.domain:bear/mp2.git
$ git clone git@your.domain:bear/mp3.git
$ cd mp2
把mp3加入mp2的remote
$ git remote add mp3 ../mp3
$ git fetch mp3
$ git branch mp3 mp3/master
$ git merge mp3
合併後的git log圖如下:
* 0f54c78 2015-01-19 | fix conflict merge [bear]
|\
| * dc09a26 2015-01-19 | add mp3.txt (mp3/master, mp3) [bear]
| * d6b0993 2015-01-19 | mp3 test commit 2 [bear]
| * 9d89949 2015-01-19 | mp3 first commit [bear]
* 4fea708 2014-11-23 | Merge branch 'master' of your.domain:bear/mp2 (origin/master, origin/HEAD) [b
|\
| * fdc6ced 2014-11-23 | gitlab [bear]
* 719d8ef 2014-11-23 | gitlab [bear]
* a66d115 2014-11-23 | Initial commit [kalecgos0616]
( ~/.bashrc:設定 alias glog='git log --pretty=format:"%h %ad | %s%d [%an]" --graph --date=short')
要重新回到mp2 被merge前的 commit( 4fea708 ) 並保留log,因為 0f54c78 中混合了4fea708 和 dc09a26 的code,有衝突的檔案要手動解決conflict,要回到最原本的4fea708
方法1. ( 會多3個revert的commit )
$ git revert dc09a26 d6b0993 9d89949
方法2. ( 只會多一個commit,並回到 4fea708 的狀態)
$ git revert -m 1 0f54c78
下面這方法試不出來,可能是我的0f54c78 是兩個repos merge的node
$ git revert HEAD~2..HEAD
ps. 把本地端某個branch推到gitlab上
$ git checkout -b branch_name remote_name/branch_name
$ git push -u origin branch_name
參考資料:
http://stackoverflow.com/questions/4114095/revert-to-a-previous-git-commit
http://blog.caplin.com/2013/09/18/merging-two-git-repositories/
http://stackoverflow.com/questions/2765421/push-a-new-local-branch-to-a-remote-git-repo-and-track-it-too
下載兩個repos並進入其中主要的branch
$ git clone git@your.domain:bear/mp2.git
$ git clone git@your.domain:bear/mp3.git
$ cd mp2
把mp3加入mp2的remote
$ git remote add mp3 ../mp3
$ git fetch mp3
$ git branch mp3 mp3/master
$ git merge mp3
合併後的git log圖如下:
* 0f54c78 2015-01-19 | fix conflict merge [bear]
|\
| * dc09a26 2015-01-19 | add mp3.txt (mp3/master, mp3) [bear]
| * d6b0993 2015-01-19 | mp3 test commit 2 [bear]
| * 9d89949 2015-01-19 | mp3 first commit [bear]
* 4fea708 2014-11-23 | Merge branch 'master' of your.domain:bear/mp2 (origin/master, origin/HEAD) [b
|\
| * fdc6ced 2014-11-23 | gitlab [bear]
* 719d8ef 2014-11-23 | gitlab [bear]
* a66d115 2014-11-23 | Initial commit [kalecgos0616]
( ~/.bashrc:設定 alias glog='git log --pretty=format:"%h %ad | %s%d [%an]" --graph --date=short')
要重新回到mp2 被merge前的 commit( 4fea708 ) 並保留log,因為 0f54c78 中混合了4fea708 和 dc09a26 的code,有衝突的檔案要手動解決conflict,要回到最原本的4fea708
方法1. ( 會多3個revert的commit )
$ git revert dc09a26 d6b0993 9d89949
方法2. ( 只會多一個commit,並回到 4fea708 的狀態)
$ git revert -m 1 0f54c78
下面這方法試不出來,可能是我的0f54c78 是兩個repos merge的node
$ git revert HEAD~2..HEAD
ps. 把本地端某個branch推到gitlab上
$ git checkout -b branch_name remote_name/branch_name
$ git push -u origin branch_name
參考資料:
http://stackoverflow.com/questions/4114095/revert-to-a-previous-git-commit
http://blog.caplin.com/2013/09/18/merging-two-git-repositories/
http://stackoverflow.com/questions/2765421/push-a-new-local-branch-to-a-remote-git-repo-and-track-it-too
2015年1月16日 星期五
git 搬移log到svn下
需求:
git下的所有log資料搬到svn 某新資料夾下(svn其他資料夾已有log)
過程照參考資料做基本上就可以了...
1. Create Subversion-aware Git clone ( 首先你要安裝git-sv )
$ git svn clone http://svn.localhost/svn/trunk/company
$ cd trunk
$ git fetch git@your.domain:username/project.git # 我是抓我gitlab上的git
$ git branch tmp $(cut -b-40 .git/FETCH_HEAD)
$(cut -b-40 .git/FETCH_HEAD) 是原本gitlab最後一個commit id
$ git tag -a -m "Last fetch" last tmp
2. Apply initial commit
$ INIT_COMMIT=$(git log tmp --pretty=format:%H | tail -1)
$(git log tmp --pretty=format:%H | tail -1)是tmp branch log的最後一個 commit id
$ git checkout $INIT_COMMIT . #注意最後要有點(.)
$ git commit -C $INIT_COMMIT
3. Rebase and submit
$ git rebase master tmp
$ git branch -M tmp master
$ git svn dcommit
4. Update Google Code
...
$ mv .git/refs/tags/newlast .git/refs/tags/last #這步我沒做
參考資料:
http://code.google.com/p/support/wiki/ImportingFromGit
git下的所有log資料搬到svn 某新資料夾下(svn其他資料夾已有log)
過程照參考資料做基本上就可以了...
1. Create Subversion-aware Git clone ( 首先你要安裝git-sv )
$ git svn clone http://svn.localhost/svn/trunk/company
$ cd trunk
$ git fetch git@your.domain:username/project.git # 我是抓我gitlab上的git
$ git branch tmp $(cut -b-40 .git/FETCH_HEAD)
$(cut -b-40 .git/FETCH_HEAD) 是原本gitlab最後一個commit id
$ git tag -a -m "Last fetch" last tmp
2. Apply initial commit
$ INIT_COMMIT=$(git log tmp --pretty=format:%H | tail -1)
$(git log tmp --pretty=format:%H | tail -1)是tmp branch log的最後一個 commit id
$ git checkout $INIT_COMMIT . #注意最後要有點(.)
$ git commit -C $INIT_COMMIT
3. Rebase and submit
$ git rebase master tmp
$ git branch -M tmp master
$ git svn dcommit
4. Update Google Code
...
$ mv .git/refs/tags/newlast .git/refs/tags/last #這步我沒做
參考資料:
http://code.google.com/p/support/wiki/ImportingFromGit
2015年1月13日 星期二
diff 兩個資料夾的某些內容並上色
目標:
使用diff像git diff比較兩資料夾下的所有檔案,排除某些資料夾,並上色
1. 使用git diff
http://stackoverflow.com/questions/5751567/git-diff-branch-name-status-ignore
$ git diff -w --name-only app/ ../cakephp-84/app/ | grep -v 'app/tmp/' | xargs git diff app/
fatal: ../cakephp-84/app/Controller/UsersController.php: '../cakephp-84/app/Controller/UsersController.php' is outside repository
原因:cakephp-84不在同一個git repos中,stackoverflow的解法似乎是比同個git下不同branch的東西
注意:git diff 必須在有.git的資料夾下才能使用,但如果只是簡單的比較不限定在該git下的檔案
2. 使用colordiff
安裝colordiff:
$ sudo pacman -S colordiff
使用:
$ diff -rw --exclude="tmp" --exclude="webroot" cakephp/app cakephp-84/app | colordiff | less -R
使用diff像git diff比較兩資料夾下的所有檔案,排除某些資料夾,並上色
1. 使用git diff
http://stackoverflow.com/questions/5751567/git-diff-branch-name-status-ignore
$ git diff -w --name-only app/ ../cakephp-84/app/ | grep -v 'app/tmp/' | xargs git diff app/
fatal: ../cakephp-84/app/Controller/UsersController.php: '../cakephp-84/app/Controller/UsersController.php' is outside repository
原因:cakephp-84不在同一個git repos中,stackoverflow的解法似乎是比同個git下不同branch的東西
注意:git diff 必須在有.git的資料夾下才能使用,但如果只是簡單的比較不限定在該git下的檔案
2. 使用colordiff
安裝colordiff:
$ sudo pacman -S colordiff
使用:
$ diff -rw --exclude="tmp" --exclude="webroot" cakephp/app cakephp-84/app | colordiff | less -R
--exclude => 可以連續使用,不比較某些資料夾下的檔案
-r => 遞迴,連子資料夾一起比
-w => 不比較空白
colordiff => 也可以把最前面的diff直接換成colordiff,這樣後面就不用pipe line 去加colordiff
less -R => 直接用less配合colordiff會有亂碼,用這招移除ANSI編碼並轉成顏色
參考資料:
http://unix.stackexchange.com/questions/76224/how-do-i-pipe-colored-diff-output-to-less # colordiff 搭配 | less -R使用
2015年1月12日 星期一
arch 安裝memcached和php-memcached、php-memcache
安裝系統memcached
$ sudo pacman -S memcached
開機時啟用memcached
# systemctl enable memcached.service
啟動memcached
# systemctl start memcached.service
檢查memcached有沒有跑
# ps aux | grep memcached
或
# netstat -tap | grep memcached (如果用netstat -ant的話就看預設的port 11211 有沒有開,但是port可以改)
檢查執行中的設定值
$ echo "stats settings" | nc localhost 11211
# vim /etc/conf.d/memcached (注意:2013/5後,裝好memcache,arch不再有這個檔案,要自己建)
-l 127.0.0.1 => listen to localhost
預設的port是11211( -p 11211 是禁止的)
-m 1024 => 1024MB RAM分給Memcached(-m 64是禁止的),64MB是最小值
編輯/usr/lib/systemd/system/memcached.service:
# systemctl restart memcached
然後再度檢查執行中的設定值:
安裝php memcached 擴展
我曾想用 pacman -S php-memcache 和 pacman -S php-memcached,來安裝,但是就算更改memcache.ini、memcached.ini後在phpinfo()裡面都沒看到memcached載入。
最後使用pecl來安裝
# pecl install memcache
# pecl install memcached
然後把/etc/php/conf.d 下的memcache.ini 、 memcached.ini 註解拿掉,
memcache.ini:
extension=memcache.so
memcached.ini:
extension=memcached.so
如果ubuntu使用apt-get安裝php5-memcache、php5-memcached
# apt-get install php5-memcache php5-memcached
且web server跑的是nginx
先去 /etc/php5/fpm/conf.d 檢查 memcached.ini 、 memcache.ini
重啟fpm(如果沒有重啟php5-fpm,phpinfo()是不會新增memcache和memcached的擴展的)
# service php5-fpm restart
重啟nginx
# service nginx restart
寫一段程式測試:
No data on Cache. Please refresh page pressing F5
# php memcache.php
test data pulled from Cache!
$ sudo pacman -S memcached
開機時啟用memcached
# systemctl enable memcached.service
啟動memcached
# systemctl start memcached.service
檢查memcached有沒有跑
# ps aux | grep memcached
或
# netstat -tap | grep memcached (如果用netstat -ant的話就看預設的port 11211 有沒有開,但是port可以改)
檢查執行中的設定值
$ echo "stats settings" | nc localhost 11211
STAT maxbytes 67108864 #預設最小的64MB STAT maxconns 1024 STAT tcpport 11211 STAT udpport 11211 STAT inter 127.0.0.1 STAT verbosity 0 STAT oldest 0 STAT evictions on STAT domain_socket NULL STAT umask 700 STAT growth_factor 1.25 STAT chunk_size 48 STAT num_threads 4 #預設4個threads STAT num_threads_per_udp 4 STAT stat_key_prefix : STAT detail_enabled no STAT reqs_per_event 20 STAT cas_enabled yes STAT tcp_backlog 1024 STAT binding_protocol auto-negotiate STAT auth_enabled_sasl no STAT item_size_max 1048576 STAT maxconns_fast no STAT hashpower_init 0 STAT slab_reassign no STAT slab_automove 0 END更改memcache設定值:
# vim /etc/conf.d/memcached (注意:2013/5後,裝好memcache,arch不再有這個檔案,要自己建)
# user to run memcached as; also used for pid file ownership MEMCACHED_USER="memcached" # see 'memcached -h' for available options MEMCACHED_ARGS="-m 1024 -l 127.0.0.1 -t 1"-t 1 =>number of threads to use
-l 127.0.0.1 => listen to localhost
預設的port是11211( -p 11211 是禁止的)
-m 1024 => 1024MB RAM分給Memcached(-m 64是禁止的),64MB是最小值
編輯/usr/lib/systemd/system/memcached.service:
[Unit] Description=Memcached Daemon After=network.target [Service] -EnvironmentFile=/etc/conf.d/memcached -ExecStart=/usr/bin/memcached -u $MEMCACHED_USER $MEMCACHED_ARGS +User=memcached +# Remove '-l 127.0.0.1' to listen on all addresses +ExecStart=/usr/bin/memcached -l 127.0.0.1 +Restart=always [Install] WantedBy=multi-user.target重啟memcached
# systemctl restart memcached
然後再度檢查執行中的設定值:
STAT maxbytes 1073741824 #更改為1024MB STAT maxconns 1024 STAT tcpport 11211 STAT udpport 11211 STAT inter 127.0.0.1 STAT verbosity 0 STAT oldest 0 STAT evictions on STAT domain_socket NULL STAT umask 700 STAT growth_factor 1.25 STAT chunk_size 48 STAT num_threads 1 #更改為1個threads STAT num_threads_per_udp 1 STAT stat_key_prefix : STAT detail_enabled no STAT reqs_per_event 20 STAT cas_enabled yes STAT tcp_backlog 1024 STAT binding_protocol auto-negotiate STAT auth_enabled_sasl no STAT item_size_max 1048576 STAT maxconns_fast no STAT hashpower_init 0 STAT slab_reassign no STAT slab_automove 0 END
安裝php memcached 擴展
我曾想用 pacman -S php-memcache 和 pacman -S php-memcached,來安裝,但是就算更改memcache.ini、memcached.ini後在phpinfo()裡面都沒看到memcached載入。
最後使用pecl來安裝
# pecl install memcache
# pecl install memcached
然後把/etc/php/conf.d 下的memcache.ini 、 memcached.ini 註解拿掉,
memcache.ini:
extension=memcache.so
memcached.ini:
extension=memcached.so
如果ubuntu使用apt-get安裝php5-memcache、php5-memcached
# apt-get install php5-memcache php5-memcached
且web server跑的是nginx
先去 /etc/php5/fpm/conf.d 檢查 memcached.ini 、 memcache.ini
重啟fpm(如果沒有重啟php5-fpm,phpinfo()是不會新增memcache和memcached的擴展的)
# service php5-fpm restart
重啟nginx
# service nginx restart
寫一段程式測試:
$mc = new Memcached(); $mc->addServer("127.0.0.1", 11211); $result = $mc->get("test_key"); if($result) { echo $result; } else { echo "No data on Cache. Please refresh page pressing F5"; $mc->set("test_key", "test data pulled from Cache!") or die ("Failed to save data at Memcached server"); }# php memcache.php
No data on Cache. Please refresh page pressing F5
# php memcache.php
test data pulled from Cache!
批量刪除key特定開頭的緩存
https://stackoverflow.com/a/25168042 memcache and wildcards
新增一個deleteKeysByIndex.php檔案
function deleteKeysByIndex($search) { $m = new Memcached(); $m->addServer('127.0.0.1', 11211); // 127.0.0.1 緩存server IP $keys = $m->getAllKeys(); foreach ($keys as $index => $key) { if (strpos($key,$search) !== false) { $m->delete($key); } else { unset($keys[$index]); } } // returns an array of keys which were deleted return $keys; } $keys = deleteKeysByIndex("CacheKey-User-"); // 刪除 CacheKey-User-開頭的緩存。如:CacheKey-User-1、CacheKey-User-2 ... print_r($keys); // 輸出被刪除的key
用法:
$ php deleteKeysByIndex.php
apache錯誤:Request exceeded the limit of 10 internal redirects due to probable configuration error.
主機:CentOS
讀取網址 http://localhost
頁面出現錯誤:
500 Internal Server Error
apache error log:
[Mon Jan 12 12:04:40 2015] [error] [client x.x.x.x] Request exceeded the limit of 10 internal redirects due to probable configuration error. Use 'LimitInternalRecursion' to increase the limit if necessary. Use 'LogLevel debug' to get a backtrace.
但是讀取
http://localhost/index.php、http://localhost/index.html、http://localhost/test.php
正常
原因:
httpd.conf 開了Rewrite( LoadModule rewrite_module modules/mod_rewrite.so
)
且
<Directory "/var/www/html">裡面的AllowOverride 被改成All
解法:
把<Directory "/var/www/html">裡面的 AllowOverride 改成None
讀取網址 http://localhost
頁面出現錯誤:
500 Internal Server Error
apache error log:
[Mon Jan 12 12:04:40 2015] [error] [client x.x.x.x] Request exceeded the limit of 10 internal redirects due to probable configuration error. Use 'LimitInternalRecursion' to increase the limit if necessary. Use 'LogLevel debug' to get a backtrace.
但是讀取
http://localhost/index.php、http://localhost/index.html、http://localhost/test.php
正常
原因:
httpd.conf 開了Rewrite( LoadModule rewrite_module modules/mod_rewrite.so
)
且
<Directory "/var/www/html">裡面的AllowOverride 被改成All
解法:
把<Directory "/var/www/html">裡面的 AllowOverride 改成None
2015年1月9日 星期五
PHP常見問題
取某段字串裡的數字
preg_match_all('!\d+!', $str, $matches);
取某段字串裡的日期 (我們假設日期格式是 YYYY-MM-DD HH-ii-ss)
preg_match('/^\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}/', $str, $matches);
去除前後的空白
$ php -r '$str = " hello world "; echo trim($str);'
hello world
參考資料:
http://stackoverflow.com/questions/6278296/extract-numbers-from-a-string
去除陣列所有字串前後的空白
http://stackoverflow.com/questions/6769464/how-can-i-trim-all-strings-in-an-array
使用array_map()
$source_array = array(" hey ", "bla ", " test");
$result = array_map('trim', $source_array); // $result = array("hey", "bla", "test");
開發時在網頁上顯示錯誤
編輯/etc/php5/apache2/php.ini 修改以下設定
error_reporting = E_ALL
display_errors = On
( nginx+fpm )
If you have /etc/php5/fpm/php.ini (used in Debian, Ubuntu style config) then changes to this file should take effect, and that configuration may be further overridden per pool by making changes to specific /etc/php5/fpm/pool.d/*.conf files.
如果你有 /etc/php5/fpm/php.ini (Debian, ubuntu) ,則編輯修改以下設定即可(採用)
; enable display of errors
display_errors = On
display_startup_errors = On
而該設定會被 /etc/php5/fpm/pool.d/*.conf 的設定覆蓋,例 ( /etc/php5/fpm/pool.d/www.conf ):
; enable display of errors
php_flag[display_errors] = on
php_flag[display_startup_errors] = on
註:
; Production Value: E_ALL & ~E_DEPRECATED & ~E_STRICT =>產品上線用
; Development Value: E_ALL => 開發用
參考資料:
http://stackoverflow.com/questions/5680831/php-does-not-display-error-messages
http://stackoverflow.com/questions/13929314/display-errors-for-php5-fpm-not-working-with-nginx display_errors for php5-fpm not working with nginx
在PHP腳本中修改錯誤輸出的級別
error_reporting(0); // Turn off all error reporting
error_reporting(E_ALL ^ E_NOTICE); // Report all errors except E_NOTICE, This is the default value set in php.ini
http://stackoverflow.com/questions/2867057/how-do-i-turn-off-php-notices
file_put_contents的LOCK_EX 參數
在php.net中,file_put_contens的描述是
int file_put_contents ( string $filename , mixed $data [, int $flags = 0 [, resource $context ]] )
而地三個參數$flags常用的有:
FILE_APPEND=>直接在該檔已有的內容後面追加內容
LOCK_EX=>寫檔的時候先鎖定,防止多人同時寫入造成內容丟失
當需要頻繁操作file_put_contents函數寫txt檔時,經常出現前半截內容缺失的情況,非常苦惱。此時LOCK_EX非常有用,加上它之後,再也沒有出現過內容缺失的情況了。LOCK_EX的意思很直白,就是寫檔時,先鎖上這個檔,這樣只允許某個客戶端訪問的時候寫,其他客戶端訪問不能寫了。
http://www.wyxuan.com/184.html PHP写文件函数file_put_contents确实给力
unlink()函數
unlink() 函数删除文件。若成功,则返回 true,失败则返回 false。
Ex.
$ touch test2
$ ls
smarty test test2
$ php -r 'unlink("test2");'
$ ls
smarty test
php的refrence符号&用法
& 可以當二位元AND運算也可以當reference,以下為reference的例子
$arr2:Array ( [0] => 1 [1] => 4 [2] => 9 )
$arr:Array ( [0] => 1 [1] => 4 [2] => 9 )
如果a(&$arr)這樣呼叫,在PHP5.3.0會產生警告,在PHP5.4.0+會產生fatal error.
以純變數為例子:
拉屎小妹哥
傳值呼叫(call By Value) - 將變數的值傳入函數,並不會更變原來的值
傳址呼叫(call By Reference) - 將變數實際儲存的位址傳入,在函數變更參數值,也會同時更變傳入的變數值
參考資料:
http://stackoverflow.com/questions/3737139/reference-what-does-this-symbol-mean-in-php Reference - What does this symbol mean in PHP?
http://www.php.net/manual/en/language.references.php References Explained
http://php.net/manual/en/language.references.pass.php Passing by Reference
http://syunguo.blogspot.com/2013/04/php_1.html [PHP]傳址與傳值呼叫
array_chunk()
http://w3school.com.cn/php/func_array_chunk.asp
把array分割,chunk=>大塊 的意思
Ex.
preserve_key = true - 保留原始数组中的键名
$ php -r '$a=array("a"=>"Cat","b"=>"Dog","c"=>"Horse"); print_r(array_chunk($a,2,true));'
Array
(
[0] => Array
(
[a] => Cat
[b] => Dog
)
[1] => Array
(
[c] => Horse
)
)
$ php -r '$a=array("a"=>"Cat","b"=>"Dog","c"=>"Horse","d"=>"Cow"); print_r(array_chunk($a,2));'
Array
(
[0] => Array
(
[0] => Cat
[1] => Dog
)
[1] => Array
(
[0] => Horse
[1] => Cow
)
)
array_slice()
http://www.w3school.com.cn/php/func_array_slice.asp
陣列中根據條件取出一段值,並返回
Ex.
從第二個開始往後取兩個
$ php -r '$a=array("e"=>"Cat","b"=>"Dog","c"=>"Horse","d"=>"Cow"); print_r(array_slice($a,1,2));'
Array
(
[b] => Dog
[c] => Horse
)
從倒數第二個(與key的升降冪無關)開始往後取兩個
$ php -r '$a=array(5=>"Cat",1=>"Dog",2=>"Horse",3=>"Cow"); print_r(array_slice($a,-2,2));'
Array
(
[0] => Horse
[1] => Cow
)
preserve = true,數字型key保留鍵值
$ php -r '$a=array(5=>"Cat",1=>"Dog",2=>"Horse",3=>"Cow"); print_r(array_slice($a,-2,2,true));'
Array
(
[2] => Horse
[3] => Cow
)
字串轉unicdoe,unicode轉字串
http://stackoverflow.com/questions/7106470/utf-8-to-unicode-code-points
快速檢查必填欄位有無缺失(無法判斷是缺哪個欄位)
http://stackoverflow.com/questions/13169588/how-to-check-if-multiple-array-keys-exists
過濾掉不合法的欄位
http://stackoverflow.com/questions/4260086/php-how-to-use-array-filter-to-filter-array-keys
$my_array = array("foo" => 1, "hello" => "world");
$allowed = array("foo", "bar");
$inserted_data = array_intersect_key($my_array, array_flip($allowed)); // array("foo" => 1);
計算生肖
https://en.wikipedia.org/wiki/Chinese_zodiac
必須把每年除夕的日子存起來,再另外處理。最後我只用國曆做簡單的判斷
PHP多維陣列搜尋(由值找key)
http://stackoverflow.com/questions/8102221/php-multidimensional-array-searching-find-key-by-specific-value
$key:2
(找$porducts 中 shortname為 Variable Temperature Kettle 的key值(通常為id))
備份上傳的檔案(框架以ThinkPHP為例)
http://www.w3school.com.cn/php/func_filesystem_copy.asp
input[type=file]的name記得要寫$_FILES['excel']['tmp_name'],不然抓不到檔案會複製不出結果
從陣列的值求其key
http://stackoverflow.com/questions/8729410/php-get-key-name-of-array-value
避免PHP Deprecated: preg_replace(): The /e modifier is deprecated, use preg_replace_callback instead in xxx.php on line xx錯誤
http://stackoverflow.com/questions/2082207/calling-function-inside-preg-replace-thats-inside-a-function calling function inside preg_replace thats inside a function
http://stackoverflow.com/questions/21334934/deprecated-preg-replace-the-e-modifier-is-deprecated-use-preg-replace-call Deprecated: preg_replace(): The /e modifier is deprecated, use preg_replace_callback instead in
http://stackoverflow.com/questions/20951133/deprecated-preg-replace-how-to-convert-to-preg-replace-callback Deprecated: preg_replace(): How to convert to preg_replace_callback?
直接看程式
PHP Deprecated: preg_replace(): The /e modifier is deprecated, use preg_replace_callback instead in xx.php on line 14
$url:http://youtube.com/id/xxxxxxpron
$result:http://youtube.com/id/xxxxxxpron
Array
(
[0] => [video]http://youtube.com/id/xxxxxxpron[/video]
[1] => http://youtube.com/id/xxxxxxpron
)
$url:http://youtube.com/id/xxxxxxpron
$result2:http://youtube.com/id/xxxxxxpron
注意:
改成preg_replace_callback後,第一個參數 $pattern ( "/\[video\](.+?)\[\/video\]/e" ),必須把 替換操作符 的 /e ( 替換字符串作為表達式 ) 拿掉,否則會報錯
PHP Warning: preg_replace_callback(): Modifier /e cannot be used with replacement callback in xx.php on line xx
Don't use the \e modifier in your preg_replace_callback() call or php will throw the following warning and return nothing
不要使用 modifier 在 preg_replace_callback() 呼叫,否則php會丟警告且返回空值
較簡單的範例
PHP Deprecated: preg_replace(): The /e modifier is deprecated, use preg_replace_callback instead in xx.php on line 10
$x:abcdEfgHijkLmnop
Array
(
[0] => -e
[1] => e
)
Array
(
[0] => -h
[1] => h
)
Array
(
[0] => -l
[1] => l
)
$x:abcdEfgHijkLmnop
避免PHP Strict Standards: Only variables should be passed by reference in strict_standards.php on line xx錯誤
http://stackoverflow.com/questions/9848295/strict-standards-only-variables-should-be-passed-by-reference-error “Strict Standards: Only variables should be passed by reference” error
直接看程式
PHP Strict Standards: Only variables should be passed by reference in /home/ds/strict_standards.php on line 6
d
解法:
把explode()放到外面處理,多一行
d
( PHP Strict Standards 錯誤沒了 )
檢查class有無方法和在一行中if兩次
http://stackoverflow.com/questions/10287789/check-if-class-has-method-in-php
$where = (method_exists($Model, "get_where")) ? $Model->get_where() : ( (isset($this->_map['where']))? $this->_map['where'] : null );
1. 使用 method_exists($Class, "method_name") 檢查
2. 在一行中使用兩次if:$result = ( condition1 ) ? a : ( ( condition2 )? b : c );
得到陣列中最後一個key
http://stackoverflow.com/questions/2348205/how-to-get-last-key-in-an-array
$array = array(
'first' => 123,
'second' => 456,
'last' => 789,
);
end($array); // move the internal pointer to the end of the array
$key = key($array); // fetches the key of the element pointed to by the internal pointer
echo $key; // last, 但$array的順序是不變的
使用sprintf連結字串
http://www.w3school.com.cn/php/func_string_sprintf.asp
喇叭王:要組合字串都改用sprintf,考量之後維護的人的關係。今天要是這字串比較長 超過一個畫面 你在維護的時候怎麼知道裡面有幾個變數 你能保證不會看漏嗎
例:
Daniel Lin, Laba King
Daniel Lin, Laba King
結果是一樣的,看起來用sprintf()好像比較好
XML字串轉陣列
http://stackoverflow.com/questions/12148662/xml-to-array-php
使用json_decode(json_encode(simplexml_load_string($xml)),TRUE)
$array:Array
(
[Formula] => Array
(
[formulaname] => Basic
[movespeed] => 1
[box] => 4
[chicken] => 3
[ducks] => 1
[cereal] => 2
)
)
in_array() 的BUG
https://stackoverflow.com/questions/7669589/in-array-does-not-work-as-expected
in_array('string', [1,0]) // true,因為 0 == "string"為true
in_array('string', [1,0], true) // false. working as expected
兩個變數中的&
https://stackoverflow.com/questions/22376222/what-does-a-single-ampersand-operator-do-in-php
What does a single ampersand ('&') operator do in PHP?
這是bitwise operator AND
ex.
$a = 9;
$b = 10;
echo $a & $b;
place value 128 64 32 16 8 4 2 1
$a 0 0 0 0 1 0 0 1 =9
$b 0 0 0 0 1 0 1 0 =10
result 8
使用microtime(true)計算php程序代碼執行消耗時間
https://blog.csdn.net/eflyq/article/details/19130141
https://stackoverflow.com/questions/33107182/php-microtime-is-correct
$start = microtime(true);
// code
$time_elapsed_secs = microtime(true) - $start; // code執行了多少「秒」
preg_match_all('!\d+!', $str, $matches);
取某段字串裡的日期 (我們假設日期格式是 YYYY-MM-DD HH-ii-ss)
preg_match('/^\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}/', $str, $matches);
去除前後的空白
$ php -r '$str = " hello world "; echo trim($str);'
hello world
參考資料:
http://stackoverflow.com/questions/6278296/extract-numbers-from-a-string
去除陣列所有字串前後的空白
http://stackoverflow.com/questions/6769464/how-can-i-trim-all-strings-in-an-array
使用array_map()
$source_array = array(" hey ", "bla ", " test");
$result = array_map('trim', $source_array); // $result = array("hey", "bla", "test");
開發時在網頁上顯示錯誤
編輯/etc/php5/apache2/php.ini 修改以下設定
error_reporting = E_ALL
display_errors = On
( nginx+fpm )
If you have /etc/php5/fpm/php.ini (used in Debian, Ubuntu style config) then changes to this file should take effect, and that configuration may be further overridden per pool by making changes to specific /etc/php5/fpm/pool.d/*.conf files.
如果你有 /etc/php5/fpm/php.ini (Debian, ubuntu) ,則編輯修改以下設定即可(採用)
; enable display of errors
display_errors = On
display_startup_errors = On
而該設定會被 /etc/php5/fpm/pool.d/*.conf 的設定覆蓋,例 ( /etc/php5/fpm/pool.d/www.conf ):
; enable display of errors
php_flag[display_errors] = on
php_flag[display_startup_errors] = on
註:
; Production Value: E_ALL & ~E_DEPRECATED & ~E_STRICT =>產品上線用
; Development Value: E_ALL => 開發用
參考資料:
http://stackoverflow.com/questions/5680831/php-does-not-display-error-messages
http://stackoverflow.com/questions/13929314/display-errors-for-php5-fpm-not-working-with-nginx display_errors for php5-fpm not working with nginx
在PHP腳本中修改錯誤輸出的級別
error_reporting(0); // Turn off all error reporting
error_reporting(E_ALL ^ E_NOTICE); // Report all errors except E_NOTICE, This is the default value set in php.ini
http://stackoverflow.com/questions/2867057/how-do-i-turn-off-php-notices
file_put_contents的LOCK_EX 參數
在php.net中,file_put_contens的描述是
int file_put_contents ( string $filename , mixed $data [, int $flags = 0 [, resource $context ]] )
而地三個參數$flags常用的有:
FILE_APPEND=>直接在該檔已有的內容後面追加內容
LOCK_EX=>寫檔的時候先鎖定,防止多人同時寫入造成內容丟失
當需要頻繁操作file_put_contents函數寫txt檔時,經常出現前半截內容缺失的情況,非常苦惱。此時LOCK_EX非常有用,加上它之後,再也沒有出現過內容缺失的情況了。LOCK_EX的意思很直白,就是寫檔時,先鎖上這個檔,這樣只允許某個客戶端訪問的時候寫,其他客戶端訪問不能寫了。
http://www.wyxuan.com/184.html PHP写文件函数file_put_contents确实给力
unlink()函數
unlink() 函数删除文件。若成功,则返回 true,失败则返回 false。
Ex.
$ touch test2
$ ls
smarty test test2
$ php -r 'unlink("test2");'
$ ls
smarty test
php的refrence符号&用法
& 可以當二位元AND運算也可以當reference,以下為reference的例子
$arr = array(1, 2, 3); function a(&$arr2){ foreach ($arr2 as &$value) { $value = $value*$value; } echo '$arr2:'; print_r($arr2); // print_r($arr); // Notice: Undefined variable: arr } a($arr); echo '<br>$arr:'; print_r($arr); // print_r($arr2); // Notice: Undefined variable: arr2 // a(&$arr); // Fatal error: Call-time pass-by-reference has been removed => And as of PHP 5.4.0( PHP Version 5.6.8 on my server ), call-time pass-by-reference was removed, so using it will raise a fatal error.輸出:
$arr2:Array ( [0] => 1 [1] => 4 [2] => 9 )
$arr:Array ( [0] => 1 [1] => 4 [2] => 9 )
如果a(&$arr)這樣呼叫,在PHP5.3.0會產生警告,在PHP5.4.0+會產生fatal error.
以純變數為例子:
$a='小妹哥'; $b=$a; $c=&$a; $b='大妹哥'; $c='拉屎小妹哥'; echo $a;輸出:
拉屎小妹哥
傳值呼叫(call By Value) - 將變數的值傳入函數,並不會更變原來的值
傳址呼叫(call By Reference) - 將變數實際儲存的位址傳入,在函數變更參數值,也會同時更變傳入的變數值
參考資料:
http://stackoverflow.com/questions/3737139/reference-what-does-this-symbol-mean-in-php Reference - What does this symbol mean in PHP?
http://www.php.net/manual/en/language.references.php References Explained
http://php.net/manual/en/language.references.pass.php Passing by Reference
http://syunguo.blogspot.com/2013/04/php_1.html [PHP]傳址與傳值呼叫
array_chunk()
http://w3school.com.cn/php/func_array_chunk.asp
把array分割,chunk=>大塊 的意思
Ex.
preserve_key = true - 保留原始数组中的键名
$ php -r '$a=array("a"=>"Cat","b"=>"Dog","c"=>"Horse"); print_r(array_chunk($a,2,true));'
Array
(
[0] => Array
(
[a] => Cat
[b] => Dog
)
[1] => Array
(
[c] => Horse
)
)
$ php -r '$a=array("a"=>"Cat","b"=>"Dog","c"=>"Horse","d"=>"Cow"); print_r(array_chunk($a,2));'
Array
(
[0] => Array
(
[0] => Cat
[1] => Dog
)
[1] => Array
(
[0] => Horse
[1] => Cow
)
)
array_slice()
http://www.w3school.com.cn/php/func_array_slice.asp
陣列中根據條件取出一段值,並返回
Ex.
從第二個開始往後取兩個
$ php -r '$a=array("e"=>"Cat","b"=>"Dog","c"=>"Horse","d"=>"Cow"); print_r(array_slice($a,1,2));'
Array
(
[b] => Dog
[c] => Horse
)
從倒數第二個(與key的升降冪無關)開始往後取兩個
$ php -r '$a=array(5=>"Cat",1=>"Dog",2=>"Horse",3=>"Cow"); print_r(array_slice($a,-2,2));'
Array
(
[0] => Horse
[1] => Cow
)
preserve = true,數字型key保留鍵值
$ php -r '$a=array(5=>"Cat",1=>"Dog",2=>"Horse",3=>"Cow"); print_r(array_slice($a,-2,2,true));'
Array
(
[2] => Horse
[3] => Cow
)
字串轉unicdoe,unicode轉字串
http://stackoverflow.com/questions/7106470/utf-8-to-unicode-code-points
function unicode2utf8($str){ if(!$str) return $str; $decode = json_decode($str); if($decode) return $decode; $str = '["' . $str . '"]'; $decode = json_decode($str); if(count($decode) == 1){ return $decode[0]; } return $str; } echo json_encode('測試'); // \u6e2c\u8a66 echo " unicode2utf8('\u6e2c\u8a66'):".unicode2utf8('\u6e2c\u8a66'); // 測試s
快速檢查必填欄位有無缺失(無法判斷是缺哪個欄位)
http://stackoverflow.com/questions/13169588/how-to-check-if-multiple-array-keys-exists
//The values in this arrays contains the names of the indexes (keys) that should exist in the data array $required = array('key1', 'key2', 'key3' ); $data = array( 'key1' => 10, 'key2' => 20, 'key3' => 30, 'key4' => 40 ); if(count(array_intersect_key(array_flip($required), $data)) === count($required)) { //All required keys exist! }
過濾掉不合法的欄位
http://stackoverflow.com/questions/4260086/php-how-to-use-array-filter-to-filter-array-keys
$my_array = array("foo" => 1, "hello" => "world");
$allowed = array("foo", "bar");
$inserted_data = array_intersect_key($my_array, array_flip($allowed)); // array("foo" => 1);
計算生肖
https://en.wikipedia.org/wiki/Chinese_zodiac
必須把每年除夕的日子存起來,再另外處理。最後我只用國曆做簡單的判斷
PHP多維陣列搜尋(由值找key)
http://stackoverflow.com/questions/8102221/php-multidimensional-array-searching-find-key-by-specific-value
function search($columns, $field, $value){ foreach ($columns as $key => $column) { if ($column[$field] === $value) { return $key; } } return false; } $products = array ( 1 => array( 'shortname' => 'The One-Touch Tea Maker', 'price' => '249.99', ), 2 => array( 'shortname' => 'Variable Temperature Kettle', 'price' => '129.99', ), ); $key = search($products, 'shortname', 'Variable Temperature Kettle'); echo "\$key:".$key;輸出:
$key:2
(找$porducts 中 shortname為 Variable Temperature Kettle 的key值(通常為id))
備份上傳的檔案(框架以ThinkPHP為例)
http://www.w3school.com.cn/php/func_filesystem_copy.asp
$project_path =pathinfo(THINK_PATH, PATHINFO_DIRNAME); $import_path = $project_path."/Uploads/import"; $file_name = "import-".microtime(true)."-".$_FILES['excel']['name']; $file_full_path = $import_path."/".$file_name; copy($_FILES['excel']['tmp_name'],$file_full_path);注意:
input[type=file]的name記得要寫$_FILES['excel']['tmp_name'],不然抓不到檔案會複製不出結果
從陣列的值求其key
http://stackoverflow.com/questions/8729410/php-get-key-name-of-array-value
$arr = array ('first' => 'a', 'second' => 'b', ); $key = array_search ('a', $arr); // $key = 'first'array_search()可以從值反查key
避免PHP Deprecated: preg_replace(): The /e modifier is deprecated, use preg_replace_callback instead in xxx.php on line xx錯誤
http://stackoverflow.com/questions/2082207/calling-function-inside-preg-replace-thats-inside-a-function calling function inside preg_replace thats inside a function
http://stackoverflow.com/questions/21334934/deprecated-preg-replace-the-e-modifier-is-deprecated-use-preg-replace-call Deprecated: preg_replace(): The /e modifier is deprecated, use preg_replace_callback instead in
http://stackoverflow.com/questions/20951133/deprecated-preg-replace-how-to-convert-to-preg-replace-callback Deprecated: preg_replace(): How to convert to preg_replace_callback?
直接看程式
error_reporting(E_ALL); function embed_video($url) { echo "\n\$url:".$url; return $url; } $result = "[video]http://youtube.com/id/xxxxxxpron[/video]"; $result = preg_replace( "/\[video\](.+?)\[\/video\]/e", "embed_video('$1')", $result ); echo "\n\$result:" . $result."\n"; $result2 = "[video]http://youtube.com/id/xxxxxxpron[/video]"; $result2 = preg_replace_callback( "/\[video\](.+?)\[\/video\]/", function($matches) { print_r($matches); return embed_video($matches[1]); }, $result2 ); echo "\n\$result2:" . $result2;結果:
PHP Deprecated: preg_replace(): The /e modifier is deprecated, use preg_replace_callback instead in xx.php on line 14
$url:http://youtube.com/id/xxxxxxpron
$result:http://youtube.com/id/xxxxxxpron
Array
(
[0] => [video]http://youtube.com/id/xxxxxxpron[/video]
[1] => http://youtube.com/id/xxxxxxpron
)
$url:http://youtube.com/id/xxxxxxpron
$result2:http://youtube.com/id/xxxxxxpron
注意:
改成preg_replace_callback後,第一個參數 $pattern ( "/\[video\](.+?)\[\/video\]/e" ),必須把 替換操作符 的 /e ( 替換字符串作為表達式 ) 拿掉,否則會報錯
PHP Warning: preg_replace_callback(): Modifier /e cannot be used with replacement callback in xx.php on line xx
Don't use the \e modifier in your preg_replace_callback() call or php will throw the following warning and return nothing
不要使用 modifier 在 preg_replace_callback() 呼叫,否則php會丟警告且返回空值
較簡單的範例
error_reporting(E_ALL); $x = 'abcd-efg-hijk-lmnop'; $x = preg_replace( '/-(.)/e', //pattern "strtoupper('$1')", $x //subject ); echo "\n\$x:" . $x . "\n"; //abcdEfgHijkLmnop $x = 'abcd-efg-hijk-lmnop'; $x = preg_replace_callback( '/-(.)/', //pattern function ($matches) { //callback print_r($matches); return strtoupper($matches[1]); }, $x //subject ); echo "\n\$x:" . $x; //abcdEfgHijkLmnop結果:
PHP Deprecated: preg_replace(): The /e modifier is deprecated, use preg_replace_callback instead in xx.php on line 10
$x:abcdEfgHijkLmnop
Array
(
[0] => -e
[1] => e
)
Array
(
[0] => -h
[1] => h
)
Array
(
[0] => -l
[1] => l
)
$x:abcdEfgHijkLmnop
避免PHP Strict Standards: Only variables should be passed by reference in strict_standards.php on line xx錯誤
http://stackoverflow.com/questions/9848295/strict-standards-only-variables-should-be-passed-by-reference-error “Strict Standards: Only variables should be passed by reference” error
直接看程式
error_reporting(E_ALL); $value = "a.b.c.d"; $extension = strtolower(array_pop(explode(".", $value))); print_r($extension);結果:
PHP Strict Standards: Only variables should be passed by reference in /home/ds/strict_standards.php on line 6
d
解法:
把explode()放到外面處理,多一行
error_reporting(E_ALL); $value = "a.b.c.d"; $explodes = explode(".", $value); $extension = strtolower(array_pop($explodes)); print_r($extension);結果:
d
( PHP Strict Standards 錯誤沒了 )
檢查class有無方法和在一行中if兩次
http://stackoverflow.com/questions/10287789/check-if-class-has-method-in-php
$where = (method_exists($Model, "get_where")) ? $Model->get_where() : ( (isset($this->_map['where']))? $this->_map['where'] : null );
1. 使用 method_exists($Class, "method_name") 檢查
2. 在一行中使用兩次if:$result = ( condition1 ) ? a : ( ( condition2 )? b : c );
得到陣列中最後一個key
http://stackoverflow.com/questions/2348205/how-to-get-last-key-in-an-array
$array = array(
'first' => 123,
'second' => 456,
'last' => 789,
);
end($array); // move the internal pointer to the end of the array
$key = key($array); // fetches the key of the element pointed to by the internal pointer
echo $key; // last, 但$array的順序是不變的
使用sprintf連結字串
http://www.w3school.com.cn/php/func_string_sprintf.asp
喇叭王:要組合字串都改用sprintf,考量之後維護的人的關係。今天要是這字串比較長 超過一個畫面 你在維護的時候怎麼知道裡面有幾個變數 你能保證不會看漏嗎
例:
$a = "Daniel"; $b = "Lin"; $c = "Laba King"; $text = sprintf("%s %s, %s", $a, $b, $c ); echo $text."\n"; $text2 = $a." ". $b.", ". $c; echo $text2;結果:
Daniel Lin, Laba King
Daniel Lin, Laba King
結果是一樣的,看起來用sprintf()好像比較好
XML字串轉陣列
http://stackoverflow.com/questions/12148662/xml-to-array-php
使用json_decode(json_encode(simplexml_load_string($xml)),TRUE)
$s =<<<EOS <root> <Formula> <formulaname>Basic</formulaname> <movespeed>1</movespeed> <box>4</box> <chicken>3</chicken> <ducks>1</ducks> <cereal>2</cereal> </Formula> </root> EOS; $array = json_decode(json_encode(simplexml_load_string($s)),TRUE); echo "<pre>\$array:"; print_r($array); echo "</pre>";結果:
$array:Array
(
[Formula] => Array
(
[formulaname] => Basic
[movespeed] => 1
[box] => 4
[chicken] => 3
[ducks] => 1
[cereal] => 2
)
)
in_array() 的BUG
https://stackoverflow.com/questions/7669589/in-array-does-not-work-as-expected
in_array('string', [1,0]) // true,因為 0 == "string"為true
in_array('string', [1,0], true) // false. working as expected
兩個變數中的&
https://stackoverflow.com/questions/22376222/what-does-a-single-ampersand-operator-do-in-php
What does a single ampersand ('&') operator do in PHP?
這是bitwise operator AND
ex.
$a = 9;
$b = 10;
echo $a & $b;
place value 128 64 32 16 8 4 2 1
$a 0 0 0 0 1 0 0 1 =9
$b 0 0 0 0 1 0 1 0 =10
result 8
使用microtime(true)計算php程序代碼執行消耗時間
https://blog.csdn.net/eflyq/article/details/19130141
https://stackoverflow.com/questions/33107182/php-microtime-is-correct
$start = microtime(true);
// code
$time_elapsed_secs = microtime(true) - $start; // code執行了多少「秒」
laravel判斷model的特定欄位是否被更改
https://stackoverflow.com/a/28866535 Laravel Eloquent update just if changes have been made
https://stackoverflow.com/a/40544518 How to search if the key value in an array exists in another array, using PHP?
$dirty = $user->getDirty(); $columns = [ 'phone', 'address', ]; if (array_intersect(array_keys($dirty), $columns)){ // 用戶電話或地址已被更改 }
s
php的svn_log()速度過慢
目標:
在網頁上顯示svn log
使用php的svn_log()函數
php官方文件的svn_log():
array svn_log ( string
$start_revision 、$end_revision和$limit 設0 代表無限制
$flags:
SVN_DISCOVER_CHANGED_PATHS - 顯示所有值(預設)
SVN_OMIT_MESSAGES - 不顯示msg和paths
SVN_STOP_ON_COPY - 不顯示paths
例:
$log:Array
(
[0] => Array
(
[rev] => 1
[author] => root
[msg] => init
[date] => 2014-10-29T04:13:15.632694Z
[paths] => Array
(
[0] => Array
(
[action] => A
[path] => /branches
)
)
)
)
因為某些commit提交檔案太多,即使調整$flags,svn_log()速度依然很慢
只好使用原生的svn log來在網頁上顯示紀錄
PHP:
exec("export LANG=zh_TW.UTF8; svn log file:///path/to/svndb/repos/ ", $svn_log);
注意:
export LANG=zh_TW.UTF8; 很重要,否則出來會是亂碼,我用system("export")看不到LANG的設定,而且export LANG=zh_TW.UTF8;和 svn log 必須寫在同一個exec()中
然後細節在處理$svn_log陣列即可顯示到網頁上
參考資料:
http://php.net/manual/en/function.svn-log.php
在網頁上顯示svn log
使用php的svn_log()函數
php官方文件的svn_log():
array svn_log ( string
$repos_url
[, int $start_revision
[, int $end_revision
[, int $limit
= 0 [, int $flags
= SVN_DISCOVER_CHANGED_PATHS | SVN_STOP_ON_COPY ]]]] )$start_revision 、$end_revision和$limit 設0 代表無限制
$flags:
SVN_DISCOVER_CHANGED_PATHS - 顯示所有值(預設)
SVN_OMIT_MESSAGES - 不顯示msg和paths
SVN_STOP_ON_COPY - 不顯示paths
例:
svn_auth_set_parameter(SVN_AUTH_PARAM_DEFAULT_USERNAME, 'username'); svn_auth_set_parameter(SVN_AUTH_PARAM_DEFAULT_PASSWORD, 'password'); $log = svn_log('http://svn.xxx/repos/trunk', 1, 2, 1);OUTPUT:
$log:Array
(
[0] => Array
(
[rev] => 1
[author] => root
[msg] => init
[date] => 2014-10-29T04:13:15.632694Z
[paths] => Array
(
[0] => Array
(
[action] => A
[path] => /branches
)
)
)
)
因為某些commit提交檔案太多,即使調整$flags,svn_log()速度依然很慢
只好使用原生的svn log來在網頁上顯示紀錄
PHP:
exec("export LANG=zh_TW.UTF8; svn log file:///path/to/svndb/repos/ ", $svn_log);
注意:
export LANG=zh_TW.UTF8; 很重要,否則出來會是亂碼,我用system("export")看不到LANG的設定,而且export LANG=zh_TW.UTF8;和 svn log 必須寫在同一個exec()中
然後細節在處理$svn_log陣列即可顯示到網頁上
參考資料:
http://php.net/manual/en/function.svn-log.php
2015年1月7日 星期三
svn merge log的測試shell script
承前篇 Arch啟用http存取svn和svn搬移log到另一個repos下
後來寫了個建構環境和merge log的script:
建立該篇文章的環境:
用法:
$ bash create_env.sh /home/svn/ #在 /home/svn/ 下建立test和test2的repos,並建立那篇文章的資料結構
merge log:
用法:
# bash test_merge_log.sh /home/svn/test /home/svn/test2 trunk/media/cloud/web/internet # 把test的log搬到test2的 trunk/media/cloud/web/internet 資料夾下
原始碼:
https://github.com/kalecgos0616/tools/tree/master/svn
注意:
要在該tty 也cd到資料夾要用 . xxx.sh (要多一個點),否則用bash xxx.sh不會換目錄,但仍然會在該目錄執行指令
The reason is that each process has its own current directory, and when you execute a program from the shell it is run in a new process. The standard "cd", "pushd" and "popd" are builtin to the shell interpreter so that they affect the shell process.
翻譯:
每個process 擁有自己的資料夾,當你執行一個shell程式時等於開了一個新的process。"cd"那些指令被內置到shell解釋器,仍影響shell進程。使用source(.) 會讓該process在現在的tty環境執行
參考資料:
http://stackoverflow.com/questions/874452/change-current-directory-from-a-script
後來寫了個建構環境和merge log的script:
建立該篇文章的環境:
用法:
$ bash create_env.sh /home/svn/ #在 /home/svn/ 下建立test和test2的repos,並建立那篇文章的資料結構
#!/bin/bash # $ bash create_env.sh# eg. # bash create_env.sh /home/svn/ SVN_REPOS_PATH=$1 cd ${SVN_REPOS_PATH} svnadmin create test svnadmin create test2 # cook test repos svn checkout file://${SVN_REPOS_PATH}test test_checkout cd test_checkout mkdir trunk tags branches touch trunk/hello.txt svn add * svn commit -m "hello test" svn update svn log cd .. # cook test2 repos svn checkout file://${SVN_REPOS_PATH}test2 test2_checkout cd test2_checkout mkdir trunk tags branches mkdir -p trunk/media/cloud/web/internet svn add * svn commit -m "hello test2" svn update svn log cd .. rm -rf test_checkout test2_checkout ls -l
merge log:
用法:
# bash test_merge_log.sh /home/svn/test /home/svn/test2 trunk/media/cloud/web/internet # 把test的log搬到test2的 trunk/media/cloud/web/internet 資料夾下
#!/bin/bash # merge REPOS1 log to REPOS2 folder # run it as root # # bash test_merge_log.sh# eg. # bash test_merge_log.sh /home/svn/test /home/svn/test2 trunk/media/cloud/web/internet SVN_REPOS1_PATH=$1 SVN_REPOS2_PATH=$2 REPOS2_FOLDER=$3 svnadmin dump ${SVN_REPOS1_PATH} > test.dump cat test.dump | svndumpfilter include "trunk" --drop-empty-revs --renumber-revs > test_trunk.dump find . -name test_trunk.dump | xargs perl -ne 'open NEW, ">>test_trunk_new.dump"; s/trunk\///g; print NEW' svnadmin load ${SVN_REPOS2_PATH} --parent-dir ${REPOS2_FOLDER} --ignore-uuid < test_trunk_new.dump rm *.dump # check svn checkout file://${SVN_REPOS2_PATH} test2_checkout cd test2_checkout svn log cd .. rm -rf test2_checkout
原始碼:
https://github.com/kalecgos0616/tools/tree/master/svn
注意:
要在該tty 也cd到資料夾要用 . xxx.sh (要多一個點),否則用bash xxx.sh不會換目錄,但仍然會在該目錄執行指令
The reason is that each process has its own current directory, and when you execute a program from the shell it is run in a new process. The standard "cd", "pushd" and "popd" are builtin to the shell interpreter so that they affect the shell process.
翻譯:
每個process 擁有自己的資料夾,當你執行一個shell程式時等於開了一個新的process。"cd"那些指令被內置到shell解釋器,仍影響shell進程。使用source(.) 會讓該process在現在的tty環境執行
參考資料:
http://stackoverflow.com/questions/874452/change-current-directory-from-a-script
2015年1月6日 星期二
Arch啟用http存取svn和svn搬移log到另一個repos下
系統:
Arch Linux
svn, version 1.8.9+
Apache/2.4.10
目標:
1. 使用http存取svn
2. 搬移一個svn repos的log到另一個repos下
使用http存取svn
我們假設現有的svn倉庫放在這裡:
/home/svn/test
1. 編輯 /etc/httpd/conf/httpd.conf,要注意順序
LoadModule dav_module modules/mod_dav.so # 取消註解
LoadModule dav_fs_module modules/mod_dav_fs.so # 取消註解
LoadModule dav_svn_module modules/mod_dav_svn.so # 新增這行
LoadModule authz_svn_module modules/mod_authz_svn.so # 新增這行
使用SSL? => 不使用,所以後面設定檔設在vhost中
新建 /home/svn/.svn-policy-file:
[/]
* = r
[REPO_NAME:/]
USER_NAME = rw
新建 /home/svn/.svn-auth-file:
# htpasswd -cs /home/svn/.svn-auth-file USER_NAME #沒有檔案時,新建第一個user
# htpasswd -s /home/svn/.svn-auth-file OTHER_USER_NAME #在檔案後面新建其他的user
設定權限:
# chown -R http:http /home/svn/test
編輯 /etc/httpd/conf/sites-available/svn.localhost.conf:
(注意:這邊我是設在vhost設定檔中、網路上有些設在httpd-ssl.conf、mod_dav_svn.conf中)
<VirtualHost *:80>
DocumentRoot "/srv/http/" 必須設不同於svn repos的位置否則出現錯誤:{
Redirecting to URL 'http://svn.localhost/test':
Redirecting to URL 'http://svn.localhost/test':
svn: E195019: Redirect cycle detected for URL 'http://svn.localhost/test'
}
ServerName svn.localhost
ServerAdmin you@example.com
ErrorLog "/var/log/httpd/svn.localhost-error_log"
TransferLog "/var/log/httpd/svn.localhost-access_log"
<Directory />
Options +Indexes +FollowSymLinks +ExecCGI
AllowOverride All
Order deny,allow
Allow from all
Require all granted
</Directory>
<Location /test/>
DAV svn
#SVNParentPath /home/svn/test
SVNPath /home/svn/test
AuthzSVNAccessFile /home/svn/.svn-policy-file
AuthName "SVN Repositories"
AuthType Basic
AuthUserFile /home/svn/.svn-auth-file
Require valid-user
</Location>
# 如果有其他repos就複製上面粗體那段加在這後面
</VirtualHost>
設定完就加入網址
# a2ensite svn.localhost
重啟apache
# systemctl restart httpd
沒設dns的話記得要設hosts
接著打開瀏覽器 http://svn.localhost/test/ 就能看到svn了,便可使用svn checkout http://svn.localhost/test/trunk/ 來下載svn
注意:
必須使用svn checkout http://svn.localhost/test/trunk/ ,否則會出現錯誤:
$ svn checkout http://svn.localhost/test/
svn: E175002: Unexpected HTTP status 405 'Method Not Allowed' on '/test'
svn: E175002: Additional errors:
svn: E175002: PROPFIND request on '/test' failed: 405 Method Not Allowed
若想要checkout出 svn.localhost/test/ 下所有東西(含branches、tags、trunk),則必須打開SSL用https去存取
打開SSL:
# cd /etc/httpd/conf/
# openssl req -new -x509 -keyout server.key -out server.crt -days 365 -nodes
(會在這資料夾下產生server.key和server.crt)
編輯 /etc/httpd/conf/extra/httpd-ssl.conf:
#SSLSessionCache "shmcb:/run/httpd/ssl_scache(512000)" #註解掉,我不確定為什麼在這邊要註解掉,因為用 journalctl -xn 查到這行有syntax error,所以註解掉
#SSLSessionCacheTimeout 300 #註解掉
在</VirtualHost> 前加入:
<Location /svn>
DAV svn
SVNParentPath /home/svn/
AuthzSVNAccessFile /home/svn/.svn-policy-file
AuthName "SVN Repositories"
AuthType Basic
AuthUserFile /home/svn/.svn-auth-file
Require valid-user
</Location>
編輯 /etc/httpd/conf/httpd.conf :
LoadModule ssl_module modules/mod_ssl.so #取消註解
Include conf/extra/httpd-ssl.conf #取消註解
重啟apache後就能用 svn checkout https://svn.localhost/svn/test (因為沒吃到vhost,所以 https://localhost/svn/test 也可以)下載含有trunk、branches、tags的svn資料了,只是他第一次連會要你接受他的憑證
如果要移除svn 在console的某個網址(http)的登錄設定:
$ rm ~/.subversion/auth/svn.simple/xxx #用grep查網址再刪除他
搬移一個svn repos的log到另一個repos下
有兩個repos
svn checkout file:///home/svn/test:
test
├── branches
├── tags
└── trunk
└── hello.txt
svn checkout file:///home/svn/test2:
test2
├── branches
├── tags
└── trunk
└── media
└── cloud
└── web
└── internet
欲把test的trunck下的code(hello.txt)搬到test2的trunk/media/cloud/web/internet 下面:
$ sudo svnadmin dump /home/svn/test > test.dump
$ cat test.dump | svndumpfilter include "trunk" --drop-empty-revs --renumber-revs > test_trunk.dump #只留trunk的資料
用vim移除trunk的資料夾,若沒做這步,之後檔案會移到 trunk/media/cloud/web/internet/trunk 下面
$ vim test_trunk.dump
:1,$s/trunk\///g
或用bash+perl 取代,注意:find到的檔案(test_trunk.dump)和>>儲存的檔案(test_trunk_new.dump)不能為同一隻檔案,否則會造成無窮迴圈,必須另外儲存
$ find . -name test_trunk.dump | xargs perl -ne 'open NEW, ">>test_trunk_new.dump"; s/trunk\///g; print NEW'
將dump檔load進test2 repos
$ sudo svnadmin load /home/svn/test2 --parent-dir trunk/media/cloud/web/internet --ignore-uuid < test_trunk_new.dump
檢查:
$ svn checkout file:///home/svn/test2/ test2_new
$ tree test2_new
test2_new
├── branches
├── tags
└── trunk
└── media
└── cloud
└── web
└── internet
├── hello.txt
└── trunk
查log有沒有搬移進去:
$ cd test2_new/ ; svn log
------------------------------------------------------------------------
r2 | bear | 2015-01-06 16:33:57 +0800 (二, 06 1月 2015) | 1 line
hello test
------------------------------------------------------------------------
r1 | bear | 2015-01-07 09:29:23 +0800 (三, 07 1月 2015) | 1 line
hello test2
------------------------------------------------------------------------
最後再手動移除 trunk/media/cloud/web/internet 下的trunk資料夾,即成功
參考資料:
https://wiki.archlinux.org/index.php/Subversion_Setup
https://blog.tinned-software.net/merge-two-svn-repositories/ # Merge two SVN repositories
http://stackoverflow.com/questions/1948318/how-to-configure-svn-web-access-for-different-write-permissions # 注意:用SVNPath時要用 <Location /svn/> 而非 <Location /svn>
http://stackoverflow.com/questions/11240581/subversion-405-method-not-allowed # 405 Method Not Allowed 可改用https解決
http://stackoverflow.com/questions/10524646/tortoise-svn-giving-me-redirect-cycle-detected-for-url-domain-svn # DocumentRoot 和 SVNPath 不能設一樣
http://stackoverflow.com/questions/9234852/how-to-replace-strings-in-a-file-and-save-it-as-another-file # bash+perl 取代檔案並另存新檔
Arch Linux
svn, version 1.8.9+
Apache/2.4.10
目標:
1. 使用http存取svn
2. 搬移一個svn repos的log到另一個repos下
使用http存取svn
我們假設現有的svn倉庫放在這裡:
/home/svn/test
1. 編輯 /etc/httpd/conf/httpd.conf,要注意順序
LoadModule dav_module modules/mod_dav.so # 取消註解
LoadModule dav_fs_module modules/mod_dav_fs.so # 取消註解
LoadModule dav_svn_module modules/mod_dav_svn.so # 新增這行
LoadModule authz_svn_module modules/mod_authz_svn.so # 新增這行
使用SSL? => 不使用,所以後面設定檔設在vhost中
新建 /home/svn/.svn-policy-file:
[/]
* = r
[REPO_NAME:/]
USER_NAME = rw
新建 /home/svn/.svn-auth-file:
# htpasswd -cs /home/svn/.svn-auth-file USER_NAME #沒有檔案時,新建第一個user
# htpasswd -s /home/svn/.svn-auth-file OTHER_USER_NAME #在檔案後面新建其他的user
設定權限:
# chown -R http:http /home/svn/test
編輯 /etc/httpd/conf/sites-available/svn.localhost.conf:
(注意:這邊我是設在vhost設定檔中、網路上有些設在httpd-ssl.conf、mod_dav_svn.conf中)
<VirtualHost *:80>
DocumentRoot "/srv/http/" 必須設不同於svn repos的位置否則出現錯誤:{
Redirecting to URL 'http://svn.localhost/test':
Redirecting to URL 'http://svn.localhost/test':
svn: E195019: Redirect cycle detected for URL 'http://svn.localhost/test'
}
ServerName svn.localhost
ServerAdmin you@example.com
ErrorLog "/var/log/httpd/svn.localhost-error_log"
TransferLog "/var/log/httpd/svn.localhost-access_log"
<Directory />
Options +Indexes +FollowSymLinks +ExecCGI
AllowOverride All
Order deny,allow
Allow from all
Require all granted
</Directory>
<Location /test/>
DAV svn
#SVNParentPath /home/svn/test
SVNPath /home/svn/test
AuthzSVNAccessFile /home/svn/.svn-policy-file
AuthName "SVN Repositories"
AuthType Basic
AuthUserFile /home/svn/.svn-auth-file
Require valid-user
</Location>
# 如果有其他repos就複製上面粗體那段加在這後面
</VirtualHost>
設定完就加入網址
# a2ensite svn.localhost
重啟apache
# systemctl restart httpd
沒設dns的話記得要設hosts
接著打開瀏覽器 http://svn.localhost/test/ 就能看到svn了,便可使用svn checkout http://svn.localhost/test/trunk/ 來下載svn
注意:
必須使用svn checkout http://svn.localhost/test/trunk/ ,否則會出現錯誤:
$ svn checkout http://svn.localhost/test/
svn: E175002: Unexpected HTTP status 405 'Method Not Allowed' on '/test'
svn: E175002: Additional errors:
svn: E175002: PROPFIND request on '/test' failed: 405 Method Not Allowed
若想要checkout出 svn.localhost/test/ 下所有東西(含branches、tags、trunk),則必須打開SSL用https去存取
打開SSL:
# cd /etc/httpd/conf/
# openssl req -new -x509 -keyout server.key -out server.crt -days 365 -nodes
(會在這資料夾下產生server.key和server.crt)
編輯 /etc/httpd/conf/extra/httpd-ssl.conf:
#SSLSessionCache "shmcb:/run/httpd/ssl_scache(512000)" #註解掉,我不確定為什麼在這邊要註解掉,因為用 journalctl -xn 查到這行有syntax error,所以註解掉
#SSLSessionCacheTimeout 300 #註解掉
在</VirtualHost> 前加入:
<Location /svn>
DAV svn
SVNParentPath /home/svn/
AuthzSVNAccessFile /home/svn/.svn-policy-file
AuthName "SVN Repositories"
AuthType Basic
AuthUserFile /home/svn/.svn-auth-file
Require valid-user
</Location>
編輯 /etc/httpd/conf/httpd.conf :
LoadModule ssl_module modules/mod_ssl.so #取消註解
Include conf/extra/httpd-ssl.conf #取消註解
重啟apache後就能用 svn checkout https://svn.localhost/svn/test (因為沒吃到vhost,所以 https://localhost/svn/test 也可以)下載含有trunk、branches、tags的svn資料了,只是他第一次連會要你接受他的憑證
如果要移除svn 在console的某個網址(http)的登錄設定:
$ rm ~/.subversion/auth/svn.simple/xxx #用grep查網址再刪除他
搬移一個svn repos的log到另一個repos下
有兩個repos
svn checkout file:///home/svn/test:
test
├── branches
├── tags
└── trunk
└── hello.txt
svn checkout file:///home/svn/test2:
test2
├── branches
├── tags
└── trunk
└── media
└── cloud
└── web
└── internet
欲把test的trunck下的code(hello.txt)搬到test2的trunk/media/cloud/web/internet 下面:
$ sudo svnadmin dump /home/svn/test > test.dump
$ cat test.dump | svndumpfilter include "trunk" --drop-empty-revs --renumber-revs > test_trunk.dump #只留trunk的資料
用vim移除trunk的資料夾,若沒做這步,之後檔案會移到 trunk/media/cloud/web/internet/trunk 下面
$ vim test_trunk.dump
:1,$s/trunk\///g
或用bash+perl 取代,注意:find到的檔案(test_trunk.dump)和>>儲存的檔案(test_trunk_new.dump)不能為同一隻檔案,否則會造成無窮迴圈,必須另外儲存
$ find . -name test_trunk.dump | xargs perl -ne 'open NEW, ">>test_trunk_new.dump"; s/trunk\///g; print NEW'
將dump檔load進test2 repos
$ sudo svnadmin load /home/svn/test2 --parent-dir trunk/media/cloud/web/internet --ignore-uuid < test_trunk_new.dump
檢查:
$ svn checkout file:///home/svn/test2/ test2_new
$ tree test2_new
test2_new
├── branches
├── tags
└── trunk
└── media
└── cloud
└── web
└── internet
├── hello.txt
└── trunk
查log有沒有搬移進去:
$ cd test2_new/ ; svn log
------------------------------------------------------------------------
r2 | bear | 2015-01-06 16:33:57 +0800 (二, 06 1月 2015) | 1 line
hello test
------------------------------------------------------------------------
r1 | bear | 2015-01-07 09:29:23 +0800 (三, 07 1月 2015) | 1 line
hello test2
------------------------------------------------------------------------
最後再手動移除 trunk/media/cloud/web/internet 下的trunk資料夾,即成功
參考資料:
https://wiki.archlinux.org/index.php/Subversion_Setup
https://blog.tinned-software.net/merge-two-svn-repositories/ # Merge two SVN repositories
http://stackoverflow.com/questions/1948318/how-to-configure-svn-web-access-for-different-write-permissions # 注意:用SVNPath時要用 <Location /svn/> 而非 <Location /svn>
http://stackoverflow.com/questions/11240581/subversion-405-method-not-allowed # 405 Method Not Allowed 可改用https解決
http://stackoverflow.com/questions/10524646/tortoise-svn-giving-me-redirect-cycle-detected-for-url-domain-svn # DocumentRoot 和 SVNPath 不能設一樣
http://stackoverflow.com/questions/9234852/how-to-replace-strings-in-a-file-and-save-it-as-another-file # bash+perl 取代檔案並另存新檔
訂閱:
文章 (Atom)