顯示具有 專案 標籤的文章。 顯示所有文章
顯示具有 專案 標籤的文章。 顯示所有文章

2017年11月19日 星期日

安裝 XAMPP PHP 架站工具包

由於在載入從 Hostinger 備份下來的 .sql 檔後發現我筆電 AppServ 裡的 phpMyAdmin 無法正常運作, 原本想重裝 AppServ, 但想到如果原因是 AppServ 裡面的 phpMyAdmin 版本太舊的話, 重裝應該也無法解決問題, 既然要重新架設本機伺服器, 何不試試看很受歡迎的 XAMPP 工具包?

我找到下面這篇文章, 依照其描述下載了 XAMPP 免安裝版, 解壓後放在 E 碟 (我筆電資料碟分割是 E 不是 D), 據作者說這樣就可避免因為安裝版預設安裝在 C 帶來的 UAC 權限困擾. 也對, 這樣就不用每次做測試都要複製檔案到 C:\Appsserv\www 下了.

# XAMPP 網頁伺服器架站工具設定與使用教學

XAMPP 官網如下 :

# https://www.apachefriends.org/zh_tw/index.html

按首頁最上方 Appache Friends 後面的 "下載" 連結, 會看到 Windows 目前都只有 32 位元版本 :




但這些都是安裝版, 下載免安裝的 zip 檔要按下方的 "更多檔案" 進入 SourceForge 檔案下載網站 :

# https://sourceforge.net/projects/xampp/files/

點選 XAMPP Windows 連結 :



點選最新的 7.1.11 版連結 :




會發現有三個免安裝檔案 (portable), 由上而下分別是 .exe, .7z, 與 .zip 壓縮檔, 都可以用, 我下載的是第一個 .exe 壓縮包, 它會導引整個解壓縮過程 :




執行下載的 xampp-portable-win32-7.1.11-0-VC14-installer.exe 壓縮包會先看到如下提示訊息, 因為偵測到我的電腦有啟用 UAC, 為了避免權限問題不要將 XAMPP 解壓縮到 C 碟下面 :




 所以接下來指定解壓縮路徑時要改為非 C 碟 (此處為 E:\XAMPP), 注意, 路徑名稱要全部是英數字, 千萬不要有中文字 :




選擇全部元件 :




這樣就完成解壓過成了, 接下來要先點選 XAMPP 路徑下的 setup_xampp.bat 檔執行路徑設定, 它會打開一個 DOS 畫面, 執行完直接關掉即可 :




如果將此 XAMPP 放到隨身碟或複製到其他電腦, 第一件事情便是執行這個 setup_xampp.bat 更新路徑才能使用 XAMPP.

接下來就可以點選 xampp-control.exe 進入 XAMPP 控制面板, 首先會出現語言選擇, 只有英語與德語, 預設英語即可 :




按 Save 即顯示 XAMPP 的控制台, 但預設似乎隱藏了右邊一排按鈕, 這時要按住視窗右下角向右拉即顯示全景如下 :




按右上角的 Config 按鈕可設定 XAMPP 的文字編輯器, 預設的記事本不好用, 我將其改為習慣的 EditPlus, 也可以設定為 Notepad++ :




在啟動 Apache 與 MySQL 伺服器之前還要將資料庫認證模式從預設較不安全的 "Config" 模式改成較安全的 Cookie 模式或最安全的 http 模式, 按 Appache 第三個按鈕 "Config", 點選 "phpMyAdmin(config.inc.php)" :




這時會用上面設定的預設編輯器開啟 config.inc.php 檔, 將 $cfg['Servers'][$i]['auth_type'] 改為 cookie 或 http 存檔即可. 以上即完成所有設定, 可以按 Appache 與 MySQL 的第一個按鈕 "Start" 開啟伺服器了. 這時會跳出 Windows 安全性警訊, 都必須按 "允許存取" 才會啟動這兩個伺服器 :






看到 Apache 與 MySQL 的第一個按鈕都變成 Stop 即表示兩個伺服器都起來了, 可見 Apache 打開了 80 (HTTP 用) 與 443 埠 (HTTPS 用); 而 MySQL 預設打開 3306 埠, 參考 :

# 常用 TCP Port作用(各種Port介紹)

這時在瀏覽器輸入 localhost 或 127.0.0.1 應該會顯示 XAMPP 的 dashboard 網頁 :




按右上角的 PHPInfo 顯示 PHP 資訊; 按 phpMyAdmin 鈕則進入 MySQL 資料庫管理網頁 (現已改名為相容之 MariaDB), 輸入管理帳號 root, 預設無密碼直接按執行鈕即可 :




若要設定密碼, 登入後按上方的 "使用者帳號" 鈕, 點選欲設定密碼之帳號右邊的 "編輯權限" :




然後按上面的 "修改密碼" 鈕 :




輸入密碼按執行即可 (我慣用的密碼 mysql 竟然是即弱) :




這樣登出後再登入就必須輸入密碼了, 若要取消密碼就選最上方的 "無密碼", 一般在本機測試其實不需要設密碼. 接下來就可以把自己的 PHP 專案目錄放在 xampp 的 hdoc 目錄下, 例如我的是 E:\xampp\htdocs, 在瀏覽器中輸入 http://localhost/myproject 即可測試專案網頁矣.

# What's the difference between utf8_general_ci and utf8_unicode_ci

2018-04-29 補充 :

今天將鄉下 Win10 電腦裡面的 AppServ 移除改安裝 xampp, 照上面修改 MySQL 密碼後出現 "無法連線: 設定錯誤" 訊息 :



查 Google 找到下列網頁 :

# xampp設定mysql密碼後phpmyadmin無法登入的解決方法

我照其說明去改 config.inc.php 檔  "Authentication type and info" 內的 password 為 "mysql" (原為空白) :

/* Authentication type and info */
$cfg['Servers'][$i]['auth_type'] = 'config';
$cfg['Servers'][$i]['user'] = 'root';
$cfg['Servers'][$i]['password'] = 'mysql';
$cfg['Servers'][$i]['extension'] = 'mysqli';
$cfg['Servers'][$i]['AllowNoPassword'] = true;
$cfg['Lang'] = '';

存檔後再次開啟 PHPMyAdmin 就不會出現錯誤訊息了. 早知就直接改檔案就好了.

2017年11月17日 星期五

證交所信用額度總量管制餘額表

最近這一個月每周六載二哥去學校上 APCS 課, 我就去附近家樂福看書, 連續看了三本理財書後, 想起因為證交所網站改版而停擺超過半年的爬蟲專案, 所租的 Hostinger 主機變成閒置資產實在浪費, 因此這周突然有了動手改版的動力, 接下來的一段時間要集中全力在網站改版上.

今天要盤點的對象是信用額度總量管制餘額表, 其舊網址格式如下  :

# http://www.twse.com.tw/ch/trading/exchange/TWT93U/TWT93U.php?input_date=104/05/20

現在連過去會看到如下說明 :

您好:

本公司全球資訊網已於106年5月23日改版,您目前瀏覽使用的網址並不正確,建議您自首頁(http://www.twse.com.tw/)重新瀏覽,並更新瀏覽器「我的最愛」或「書籤」設定。

如須進一步協助請參閱本公司官網改版問答集(http://www.twse.com.tw/downloads/zh/home/TWSE_QA.pdf),或洽投資人服務中心專線:(02)2792-8188
錯誤代碼為:8348613256455828716
事件代碼為:62855325295449445

TWSE revised the official website on 23rd May, 2017. The URL address you were trying to reach seem to be incorrect or outdated. Please update your browser bookmark(s), thank you.

TWSE official website: http://www.twse.com.tw/
Page Error Code:8348613256455828716
Event ID:62855325295449445

新版網址已改為 :

# http://www.twse.com.tw/zh/page/trading/exchange/TWT93U.html

但這是分頁式網頁, 需選取下拉式選單中的 "全部" 才會能取得全部上市股票與 ETF 的信用交易資料. 如果要取得全頁式網頁則要按左上角的 "HTML" 超連結 :




其網址格式為 :

# http://www.twse.com.tw/exchangeReport/TWT93U?response=html&date=20171110

可見雖然網頁標題使用民國紀元 但 URL 卻用西元紀元. 這日期若傳入非交易日的話會得到一個只有表頭的空表格 (有日期); 若傳入未來日期則顯示 "查詢日期大於今日,請重新查詢!".

信用交易資料放在一個唯一的 tbody 表格中, 而且表格相當乾淨, 沒有任何 inline 的屬性, 所以相當容易剖析, 只要用下列指令去除多於 1 個的空格 :

$data=preg_replace("/([\s]{2,})/","",$data);

然後逐列逐行拆解即可 :

            <tbody>         
                <tr>                 
                        <td>0050</td>                 
                        <td>元大台灣50</td>                 
                        <td>216,000</td>                 
                        <td>1,000</td>                 
                        <td>0</td>                 
                        <td>0</td>                 
                        <td>217,000</td>                 
                        <td>119,000,000</td>                 
                        <td>2,716,000</td>                 
                        <td>0</td>                 
                        <td>160,000</td>                 
                        <td>0</td>                 
                        <td>2,556,000</td>                 
                        <td>940,467</td>                 
                        <td></td>                 
                </tr>

此網頁對應的爬蟲程式為 fetch_twse_daily_debit.php, 除了擷取的網頁網址要改外, 還有網頁表格的起迄信標也要改為如下 :

  $start="<tbody>";  //起始字串
  $end="</tbody>";   //結束字串

除此之外的程式碼都不用修改.

這張表格中需要擷取的欄位有四個 :

融券賣出 : bearish_sale=$brr[3]
融券餘額 : bearish_balance=$brr[6]
借券賣出 : short_sale=$brr[9]
借券餘額 : short_balance=$brr[12]

都寫入個股的 zxxxx 日報表欄位中. 由於證交所每天 20:30 與 22:30 各更新一次, 因此只要在這兩個時間之後去 query 即可.

"股價持續上漲但借券賣出也同時增加時要注意高點可能已近, 但借券賣出餘額減少卻可能是多頭訊號. 借券餘額增加表示有潛在賣壓, 但借券不一定會賣出, 若借券賣出也增加就要小心了."

參考 :

# http://www.cmoney.tw/notes/note-detail.aspx?nid=15403

2017年11月13日 星期一

證交所上市櫃股票列表

由於證交所網站在 2017-05-23 左右改版, 新版網頁拋棄全部資訊集中顯示在一張網頁的方式, 改採輸入股號股名查詢, 導致之前寫的爬蟲軟體無法再抓取到資料, 必須進行改版. 之前一頁式網頁股票名單就在網頁表單中, 只要單純剖析網頁即可獲得全部收盤資料, 但現在得分成兩步驟, 首先須取得最新上市櫃股票名單, 然後再一一查詢各股收盤資料. 但問題是如何得知最新的上市櫃股票名單呢?

原來證交所網站就有提供此最新名單, 參考 :

# 本國上市證券國際證券辨識號碼一覽表
# 本國上櫃證券國際證券辨識號碼一覽表

這兩張表格都只需要抓 "股票" 與 "ETF" 部分, 剖析表格中的 "有價證券代號及名稱", "上市日", "市場別", "產業別" 這四個欄位即可, 將其存入 stocks_list 資料表的 stock_id, stock_name, listed_date, market, 以及 category 等 5 個欄位中, 其中 listed_date 與 market 是此次改版要新增的欄位.


上市股票

上市 ETF

上櫃股票

上櫃 ETF


以擷取上市股票資料為例, 開頭位置在標示 "股票" 這一列; 而結束位置在 標示 "上市認購(售)權證" 字樣前面, 如下所示 :




檢視網頁原始碼可以找到具體的開始與結束位置 (保留 tr), 如下所示 :





用這兩個頭尾信標為界就可以抓到上市股票的資料了.

$start="<B> 股票 <B> </td></tr>";  //起始字串
$end="<tr><td bgcolor=#FAFAD2 colspan=7 ><B> 上市認購(售)權證 <B>";   //結束字串

抓下來之後就用迴圈一列列去拆解表格內容, 在迴圈內又將每一列的儲存格拆解成陣列, 這樣就可分離出各欄資料了. 注意, 在拆解股名與股號時要注意, 分隔兩者的是全形空白, 我是直接由網頁複製到記事本, 再複製到程式中 :

list($stock_id,$stock_name)=explode(" ", $brr[0]); //分出股號與股名

抓 ETF 方式一樣, 只要更改頭尾信標即可 :





$start="<B> ETF <B> </td></tr>";  //起始字串
$end="<tr><td bgcolor=#FAFAD2 colspan=7 ><B> 臺灣存託憑證(TDR) <B>";   //結束字串

注意, 證交所的原始網頁使用 MS950 編碼, 可從網頁的標頭中看出 :

Server: Apache-Coyote/1.1
Content-Type: text/html;charset=MS950 
Transfer-Encoding: chunked
Date: Tue, 14 Nov 2017 12:54:07 GMT

MS950 是在 BIG5 碼的基礎上進行的編碼擴充, 增加了 7 個中文字以及一些符號, 也是 Windows 繁中版預設字元集, 關於編碼參考 :



在 PHP 中 MS950 編碼可以當成 BIG5 碼來處理, 但是以前用 iconv() 將 BIG5 轉成 UTF-8 都沒問題 : 

$file=iconv("BIG5","UTF-8",$web_page['FILE']);  //MS950 轉 UTF-8 有問題

但這回用此指令轉換後, 剖析時讀取到宏碁的 "碁" 時卻停止轉換, WHY?  後來在下面這篇看到作者用 mb_convert_encoding() 函數做轉換 : 


$file=mb_convert_encoding($web_page['FILE'],"utf8","big5");

這樣就沒問題了. 如果要偵測一個字串是甚麼編碼則要用 mb_detect_encoding() 函數, 參考 :


由上市日期可以計算至今該公司已上市多久, 在選股時通常上市未滿 5 年者我都不予考慮. 從證交所網頁取得的資料經剖析後每一列會放在陣列 $brr 中, 上市日期位於第三欄, 因此索引為 2 即 $brr[2], 格式為 YYYY/MM/DD, 先用 str_replace() 將 "/" 換成 "-",  拆出年月日後呼叫 mktime() 轉成時戳, 再與目前時戳相減即得上市秒數, 最後轉換成年 :

  $listed_date=str_replace("/","-",$brr[2]);
  list($Y,$M,$D)=explode("-",$listed_date); //拆分 1987-02-21
  $listed_time=mktime(0,0,0,$M,$D,$Y); //計算 1970-01-01 以來至上市日秒數
  $listed_years=round((time()-$listed_time)/3600/24/365,1); //小數一位

另外, 漲跌家數資訊已改在下列網頁提供 :


2015年4月22日 星期三

用 jQuery EasyUI 打造輕量級 CMS (十二) : Pclzip 壓縮解壓縮

今天突發奇想, 既然 Appfog 不提供 web 介面來管理檔案上傳與下載, 何不自己寫一個呢? 其實我不需要實作 cPanel 那種完整的檔案與目錄管理, 只要下列三個功能即可 :
  1. 將整個根目錄下全系統備份為 zip 檔下載
  2. 刪除全部資料
  3. 上傳 zip 檔自動解壓縮覆蓋原系統
首先去官網下載 :

# Pclzip 官方網站 (Pclzip 下載)

解開後將其中的 pclzip.lib.php 複製到 EasyUICMS 專案目錄下的 lib 下, 然後於系統檔 sys.php 前面增加匯入此函式庫 :

require_once("lib/pclzip.lib.php");  //匯入zip/unzip模組     (選項)

不過接下來要在哪裡放置這個系統更新與備份下載功能按鈕就費思量了. 因為昨日測試發現已安裝 af 的 Ruby 免安裝版可以移到其他電腦使用, 所以利用 Pclzip 來自行打造系統更新備份功能的計畫暫緩, 以後有需要再進行.

關於 Pclzip 的用法請參考 :

# AJAXPLORER:超強大的 PHP + AJAX 開源文件管理系統
# PHP解壓縮和製作壓縮 (使用pclzip)
# php 解壓縮zip 使用pclzip
# PHP CONTENT : PclZip Overview


2015年4月20日 星期一

用 jQuery EasyUI 打造輕量級 CMS (十一)

睽違一個多月沒動這個專案了, 這兩三天因為 000a.biz 停止了我的應用程式, 無奈之下只好另擇良木而棲. 還好 000z.biz 有把程式跟資料庫還我, 所以我將這兩天自行修改部分與 000a.biz 還我的程式做個混合調整, 修改了部分EasyUICMS 系統與 STOCK 專案程式, 由近而遠摘要如下.

今天將調整後的專案 ZIP 檔上傳以前用過的 000webhost 這一家虛擬主機商, 結果系統安裝後竟然沒有出現成功訊息視窗, 我研判應該是 Ajax 回傳訊息有問題, 用 F12 觀察 Response 發現, 果然回傳訊息後面還帶了 000webhost 的統計用 Javascript :

{"status":"success","msg":"MySQL \u8cc7\u6599\u5eab\u53c3\u6578 : <br>MYSQL_ADDRESS=mysql3.000webhost.com<br>........."}
<!-- Hosting24 Analytics Code -->
<script type="text/javascript" src="http://stats.hosting24.com/count.php"></script>
<!-- End Of Analytics Code -->

而 index.htm 的 Ajax 回傳訊息處理如下 :

      $("#install_form").form({
        url:"install.php",
        method:"post",
        success:function(data){
          var data=eval('(' + data + ')');
          $("#install_dialog").dialog("close");
          if (data.status==="success") {  //不會符合
            $.messager.alert("訊息",data.msg,"",function(btn){
              if (btn){window.location.href="index.php";}
              else {window.location.href="index.php";}
              });          
            }
          else {
            $.messager.alert("訊息",data.msg,"info",function(btn){
              if (btn){window.location.href="index.php";}
              else {window.location.href="index.php";}
              });          
            }        
          }
        });

這樣用 eval() 把 data 轉成物件時就會失敗, 以至於雖然安裝成功了 (可由 phpMyAdmin 觀察資料表都正常建立得知), 但卻沒有顯示成功訊息. 我用 substr 擷取回傳訊息中的 {} 部分解決 :

          var r=data.substr(0,data.indexOf("}") + 1); //取出 {} 部分字串
          var data=eval('(' + r + ')');  //轉成物件

所以以後處理 Ajax 回傳異常時, 不要以為自己的程式有錯, 要馬上想到免費主機大都會在回傳訊息後面安插統計資訊, 使 Ajax 回傳處理函式破功, 這在本機 localhost 以及某些免費主機 (如以前免費的 Appfog) 都不會有這問題. 事實上不只是在 index.htm 裡有此 Ajax 回應被加上額外訊息導致的錯誤, 在 sys.php 中也有同樣的問題, 甚至應用程式 STOCK.php 也是, 所以都一併修改了.

其次我修改了系統程式 sys.php 裡的 remove_app 模組, 添加移除應用程式在網頁左方導覽列中所建立的超連結 :

        //找出屬於此 APP 的導覽區塊
        $RS=search("sys_nav_blocks","app",$app_name);
        for ($i=0; $i          $block_id=$RS[$i]["id"];
          //從 sys_nav_links 刪除此 app 所建立之超連結
          $result=delete_record("sys_nav_links","block_id",$block_id);
          if ($result===FALSE) {
            $status="failure";
            $msg .= "刪除應用程式在 sys_nav_links 之超連結失敗
";
            }
          }
        //從 sys_nav_blocks 刪除此 app 所建立之超連結
        $result=delete_record("sys_nav_blocks","app",$app_name);
        if ($result===FALSE) {
          $status="failure";
          $msg .= "刪除應用程式在 sys_nav_blocks 之超連結失敗
";
          }

當移除應用程式時, 會先找出資料表 sys_nav_blocks 中屬於該應用程式的導覽區塊找出來, 然後到 sys_nav_links 資料表中刪除該區塊的所有連結. 最後刪除 sys_nav_blocks 中該應用程式的導覽區塊. 當然, 為了配合這個功能, 在安裝程式 install.php 中, 建立 sys_nav_blocks 資料表時, 要添加 app 欄位 :

    //插入 sys_nav_blocks 之連結
    $data_array["title"]="主功能";
    $data_array["sequence"]=0;  
    $data_array["display"]="Y";  
    $data_array["app"]="varchar(255)";         //所屬應用程式名稱
    $result=insert("sys_nav_blocks", $data_array);
    $data_array=NULL;

另外, sys.php 程式中的 nav_blocks, list_nav_blocks, add_nav_block, update_nav_block 這四個模組也要為了這個新增的 app 欄位添加程式碼.

最後在應用程式的安裝檔, 例如 STOCK_install.php 裡面, 要建立導覽區塊時, 務必在 sys_nav_blocks 資料表的 app 欄位指定應用程式名稱, 例如下面是為 STOCK 應用程式建立 STOCK 與 BROKER 這兩個導覽區塊 :

//插入 sys_nav_blocks 之連結
$data_array["title"]="STOCK";
$data_array["sequence"]=2;  
$data_array["display"]="Y";  
$data_array["app"]="STOCK";  
$result=insert("sys_nav_blocks", $data_array);
$data_array=NULL;
$RS=search("sys_nav_blocks","title","STOCK");
$nav_block_1=$RS[0]["id"]; //sys_nav_links 用

//插入 sys_nav_blocks 之連結
$data_array["title"]="BROKER";
$data_array["sequence"]=3;  
$data_array["display"]="Y";  
$data_array["app"]="STOCK";  
$result=insert("sys_nav_blocks", $data_array);
$data_array=NULL;
$RS=search("sys_nav_blocks","title","BROKER");
$nav_block_2=$RS[0]["id"]; //sys_nav_links 用

//插入 sys_nav_links 之連結
$data_array["title"]="台股觀測站";            
$data_array["url"]="https://2330.tw/";                
$data_array["target"]="_blank";
$data_array["sequence"]=0;
$data_array["block_id"]=$nav_block_1;
$data_array["hint"]="台股觀測站";
$result=insert("sys_nav_links", $data_array);

$data_array=NULL;

另外, 為了佈署在 Appfog, 又把 index.htm 中原本已拿掉的 Appfog 專用安裝程式碼放回去 (因為 Appfog 的 MySQL 參數必須用環境參數 VCAP_SERVICES 取得後再用 $mysql_config[] 讀取) :

  //先判斷是否為 Appfog 雲端虛擬主機以讀取 MySQL 連線參數
  $services_json=json_decode(getenv("VCAP_SERVICES"),true);
  if (is_array($services_json)) { //appfog 雲端虛擬主機
      $mysql_config=$services_json["mysql-5.1"][0]["credentials"];
      $username=$mysql_config["username"];
      $password=$mysql_config["password"];
      $hostname=$mysql_config["hostname"];
      $port=$mysql_config["port"];
      $address="$hostname:$port";
      $db=$mysql_config["name"];
      } //end of if
  else { //一般 PHP+MySQL 虛擬主機 (從 dbsettings.php 檔讀取)
    $str=read_file("db.php"); //讀取資料庫設定檔初始值 (或參考值)
    $username=return_between($str,"'MYSQL_USERNAME','","')","EXCL");
    $password=return_between($str,"'MYSQL_PASSWORD','","')","EXCL");
    $address=return_between($str,"'MYSQL_ADDRESS','","')","EXCL");
    $db=return_between($str,"'DATABASE','","')","EXCL");
    } //end of else

最後修改了檔案上傳功能的一個 Bug, 
 在 sys.php 的 files 模組增添表單 validate 功能, 否則若檔案說明沒填, 上傳會當在那邊沒有回應 :

    $("#upload_file_go").bind("click",function(){
      var arr=$("#uploader").filebox("getText").split("\\");
      filename=arr[arr.length-1];
      var reg=/^[a-zA-Z0-9._-]+$/g;
      if (reg.test(filename) && $("#upload_file_form").form("validate")) {
        $("#uploading").css("visibility","visible");
        $("#upload_file_form").form("submit");    
        }
      else {
        var msg="每一欄位均須填寫! 檔名必須為英數字, 小數點, 底線, " +
                "或減號之組合! 請更改檔名!<br>";
        $.messager.alert("訊息",msg,"warning");
        }

      });

以上便是此次意料之外的大改版, 沒想到換個虛擬主機竟然發現這麼多需要修改的地方.

2014年5月11日 星期日

PHP 微框架對 Appfog 的特別處理

太久沒有玩自己寫的 PHP 微框架, 忘記安裝時是如何處理資料庫設定檔 dbsettings.php, 所以花了一些時間去看原始碼, 原來對 Appfog 是有特別處理的, 亦即, 若是 Appfog 主機, 那麼用 getenv() 讀取伺服器的 "VCAP_SERVICES" 系統變數時, 它會傳回資料, 經 json_decode() 解碼後轉為陣列, 這樣就可以讀取 Appfog 主機傳回的 MySQL 資料庫設定參數. 參考 Appfog 的MySQL 文件 :

# https://docs.appfog.com/services/mysql

如果不是 Appfog 主機, 當然就不會有傳回值, 這時就要從 dbsettings.php 去讀取. 所以對於 Appfog 主機而言, 是不需要 dbsettings.php 檔的; 但其他一般 PHP 主機就需要, 而且最好在上傳程式前, 先用 phpMyAdmin 先設定好資料庫, 取得其存取參數 (host, user, pwd, database), 改好 dbsettings.php 再上傳整個系統檔案比較好, 這樣瀏覽首頁轉到 install.php 時就不需要輸入這些參數了.

<?php
$installed=find_table("sys_settings"); //檢查資料庫是否已安裝
if ($installed === FALSE) { //系統尚未安裝, 先安裝系統
    //先判斷是否為 Appfog 雲端虛擬主機以讀取 MySQL 連線參數
    $services_json=json_decode(getenv("VCAP_SERVICES"),true);
    if (is_array($services_json)) { //appfog 雲端虛擬主機
        $mysql_config=$services_json["mysql-5.1"][0]["credentials"];
        $username=$mysql_config["username"];
        $password=$mysql_config["password"];
        $hostname=$mysql_config["hostname"];
        $port=$mysql_config["port"];
        $db=$mysql_config["name"];
        $address="$hostname:$port";
        } //end of if
    else { //一般 PHP+MySQL 虛擬主機 (從 dbsettings.php 檔讀取)
        $str=read_file("dbsettings.php");
        $username=return_between($str,"'MYSQL_USERNAME','","')","EXCL");
        $password=return_between($str,"'MYSQL_PASSWORD','","')","EXCL");
        $address=return_between($str,"'MYSQL_ADDRESS','","')","EXCL");
        $db=return_between($str,"'DATABASE','","')","EXCL");
        } //end of else
?>

即使是自己寫的東西, 過一段時間就會想不起來當初是如何寫, 為何要這麼寫, 因此在每一行程式碼後面儘可能加註, 這樣才能快速喚醒記憶.


2014年3月12日 星期三

AppFog 新用戶要收費了

上個月就收到 AppFog 來信告知, 要縮減免費使用者的可用資源, 但沒仔細看, 結果 2/20 後我放在 AppFog 的機器人就沒有定時回報股市資訊運算結果, 但實在太多事要忙, 沒空去檢查原因, 今日趁下載學姊的龐大語音檔時, 找出那封信, 哇, 仔細看才發現, 還好今天有看, 不然到 3/19 以後, 所有未登入的免費使用者帳號都會被砍掉.

摘要 :
  1. 不再開放免費使用. 已註冊之免費使用者將縮減資源為 512MB RAM, 2 Apps, 2 services
  2. 所有免費使用者的應用程式與服務都會在 2/20 被停掉, 使用者須在 3/5 前登入並將程式與服務重新啟動, 否則帳號會被暫停. 若 3/19 前仍未登入, 帳號將被刪除.
  3. 若提升為付費會員 (最低消費每月 $20 美元), 程式與服務會自動重新啟動.
總之, 有交錢好辦事啦. 不過, 說句公道話, AppFog 是我用過除了 Google App Engine 以外最穩定的雲端主機, 可惜我當初只註冊了兩個帳號.

來函全文如下 :

THIS EMAIL CONTAINS IMPORTANT INFORMATION THAT REQUIRES YOUR IMMEDIATE ATTENTION AND ACTION
Next Wednesday, February 19, we are reducing the size of our free account plans. As a free account owner, this will impact you.
Our overriding goal is to provide a stable, reliable, and incredibly easy-to-use PaaS for all of our customers. Over the past few months, a subset of free users have engaged in abusive actions that has negatively affected the stability and uptime for all users.
We have taken numerous steps and dedicated resources toward addressing abuse, but have come to the realization that larger changes are needed to bring AppFog back to the level of reliability our customers have every right to expect. We want all developers to have an opportunity to try our service. We also need to maintain a level of control over the reliability experienced by our paying customers.

This is going to result in several changes to AppFog’s systems and plans. Our goal is to make these changes as minimal as possible while still improving the experience for everyone. To reach these goals, we are making the following changes:
  • New customers will no longer have the option to sign up for a free plan. We will offer a trial starting very soon.
  • Existing users of our free plan will see a modified free plan, with a smaller set of resources available for your use.
    • 512MB RAM (previously 2GB RAM)
    • 2 app instances (previously limited by available memory)
    • 2 services instances (previously 8 services instances)

ACTION REQUIRED
A rolling 4-hour maintenance window will begin at 6pm US Pacific Time (UTC-08:00) on Wednesday, February 19. All applications will be stopped and unavailable during the maintenance window. You should notify your users of this maintenance period when applications will be down.  
Each infrastructure will come down to begin a 4-hour maintenance period at the following US Pacific times (with each datacenter’s local time in parentheses):
  • AWS-AP - 1pm Wed, Feb 19 US Pacific  (5am Thurs, Feb 20 SGT/GMT+8)
  • AWS-EU - 3pm Wed, Feb 19 US Pacific  (11pm Wed, Feb 19 GMT)
  • AWS-US - 6pm Wed, Feb 19 US Pacific  (9pm Wed, Feb 19 US ET/GMT-5)
  • HP-US - 10pm Wed, Feb 19 US Pacific  (11pm Wed, Feb 19 US MT/GMT-7)
ALL FREE PLAN CUSTOMERS WILL NEED TO RESTART THEIR APPLICATIONS
You will need to login to your AppFog account and restart your applications after the maintenance is complete.  We will post regular maintenance updates to the Twitter account @appfogstatus and on the http://status.appfog.com page.
IMPORTANT: WE WILL ALSO BE REMOVING INACTIVE ACCOUNTS

You must login within 14 days (by Wed. March 5). After this date, inactive accounts not logged into will suspended and the account owner notified. Suspended accounts with no activity (login) after 30 days (by Fri. Mar 19) will be deleted.

As a Free Account Owner affected by these changes, you have two options:
  1. Upgrade to a paid account before the restart. Running apps in paid accounts will be automatically restarted.
  2. Continue with your free plan account; all apps in free plans will remain stopped until you restart them. Restart as many as you want, as long as you stay below the new thresholds outlined above (512MB, 2 app instances, 2 service instances).  If you have been consuming more than these resource limits, we hope you will consider upgrading to one of our subscription plans.
Thank you for being an AppFog user and customer. We appreciate our developers and know that this maintenance could be disruptive for many of our users. These changes are critical and intended to enable us to focus our resources on the goal of stability and uptime for all of our customers moving forward.
Sincerely,
The AppFog Team

2013年8月2日 星期五

專案進度:修改 hello 程式

為了瞭解打招呼程式 hello.php 是否正常運作, 早上做了一些修改, 紀錄 GAE 最近一次打招呼時間跟遠端拜訪者資訊 :

date_default_timezone_set("Asia/Taipei");
include_once("lib/file.php");
$out="Hello! ".date("Y-m-d H:i:s")." from ".$_SERVER["REMOTE_ADDR"].
         ":".$_SERVER["REMOTE_PORT"]." ".$_SERVER["HTTP_USER_AGENT"];
write_file("./hello.txt",$out."\r\n");
echo $out."<br>";

2013年7月31日 星期三

專案進度 : 停掉 cron

因為 stockbot.x90x.net 被停權了, 但每天還是會收到空信, 所以晚上把 cron 清掉, 同時把 gaetrader (webabc999) 的 cron 也停掉, 以免沒用的 mail 一堆.
這兩天整理讀書心得, 所以專案沒什麼進度. 看懂新聞 2 這本書有人預約, 本週要還, 所以閱讀筆記要優先寫完.

2013年7月28日 星期日

專案進度 : 我的免費網站又掛點了

昨晚連線 stockbot 專案網站發現無法顯示, 登入後台才發現帳號又被 x90x.net 停權了, 原因是執行太多次 MySQL 查詢, 建議我升級為付費方案. 而我在 Appfog 的相同網站卻依然運轉良好, 我打算以後就轉移到 Appfog, 而 x90x.net 就用作純測試用吧.

FreeSuspendedAbuseAccount stockbot.x90x.net has executed more than 70000 MySQL queries that took more than 1 second to complete. Our shared hosting servers are not designed to host websites that create excessive or slow MySQL queries. Please optimize your website or move it to VPS / dedicated server  

2013年7月24日 星期三

專案進度:修改月營收追蹤程式

今天重新修改月營收追蹤程式, 除了近三月營收年增率均為正以外, 加入新的追蹤變數 :

(1).近三月營收年增率是否遞增
(2).近三月營收年增率是否負轉正
(3).近三月營收年增率是否遞減
(4).近三月營收年增率是否正轉負

長短期營收年增率變化方面, 由於今年實施 IFRSs, 所以擷取24個月資料會新舊雜陳, 沒有意義, 等明年資料一致後再寫.

2013年7月23日 星期二

2013年7月21日 星期日

專案進度:修改股利政策

今天把股利政策程式做了大幅度修改, 不再從 Yahoo 抓資料, 同時每一支程式都加上測試模式, 只要在網址後面加上 ?id=股號, 就可以指定抓取該股資訊.

2013年7月19日 星期五

專案進度:完成現金流量表

昨晚把現金流量表搞定, 此表主要是觀察長短期 (3 年/8 年) 營運現金流與自由現金流, 分別計算其占稅後淨利之比率, 也就是所謂的稅後純益含金量, 營運現金占稅後淨利應大於 100% 為佳, 而自由現金占稅後淨利應大於 50% 為宜. 另外就是長期自由現金總和應為正, 過去 8 年中至少 5 年為正值.
另外, 由於 cron job 檔案越來越多, 放在根目錄下顯得很凌亂, 所以全部搬到 cron 資料夾, 當然 GAE 的 main.py 的 router 也隨同修改. 系統更新後目前看來跑得很順.

2013年7月16日 星期二

PHP 計算日期差距的方法

使用 PHP/cURL 可以從 Yahoo 股市可以抓到一家企業的上市日期 $listed_date (注意是民國年), 但要計算這家公司已上市幾年, 這在 PHP 要怎麼寫? 翻了一下書, 發現其實這很簡單, 只要利用 time() 跟 mktime() 這兩個函數就可以辦到 :

//計算已上市年數
list($Y,$M,$D)=explode("/",$listed_date); //拆分 83/09/05 (年/月/日)
$Y=$Y+1911; //轉成西元年
$listed_time=mktime(0,0,0,$M,$D,$Y); //計算 1970/1/1 以來至上市日秒數
$listed_years=round((time()-$listed_time)/3600/24/365,1); //四捨五入至小數一位
echo "上市日期=$Y-$M-$D (已上市 $listed_years 年)";

其中 time() 是計算 1970/1/1 至目前之秒數, 減掉至上市日秒數, 就是上市至今的秒數, 除以 31536000 即得上市年數. 通常上市兩年以上的企業才值得進一步評估, 新上市股宜剔除.

2013年7月15日 星期一

專案進度

上週為了評鑑忙翻了, 每年這時都要接受考試, 雖然很討厭, 但也趁這機會建立幾個 SOP 也不錯, 反正無法躲避就要轉念.
這兩天專案有大大的進步, 完成損益表與資產負債表分析, 增加了營收市值比與市值淨值比這兩個指標的計算程式, 只剩下現金流量表了. 簡單紀錄一下.

2013年6月22日 星期六

AmyPHP 更新使用者的 BUG

今天又發現了 AmyPHP 一個嚴重 BUG, 中午吃完香 Q 麵回來, 用 iPad 上 stockbot 網站看看執行狀況, 卡好, superuser 竟然無法登入! 這是怎麼回事? 回想了一下出去吃飯前我改了 superuser 的資料, 該不會是 update user 時把密碼也改了吧? 果然, 檢查 sys.php 的 update_users 模組, 嘿嘿, 當初把 add_users 的程式複製過來改時, 忘記把 md5 拿掉, 所以原本的 md5 再 md5 一次存進去, 當然密碼也被改啦! 正確作法應該先檢查使用者是否有更改密碼, 沒改就原來的 md5 密碼存進去, 有改就必須 md5 加密 :

              $id=$_REQUEST["id"];
              //先檢查密碼是否有更改
              $RS=search("users","id",$id);
              if (is_array($RS)) { //有找到
                  if ($_REQUEST["password"]==$RS[0]["password"]) { //沒改
                      $data_array["password"]=$_REQUEST["password"];
                      } //end of if
                  else { //有改
                      $data_array["password"]=md5($_REQUEST["password"]);
                      } //end of else
                  } //end of if

AmyPHP 微框架修改安裝程式列表

今天發現 AmyPHP 管理頁面的應用程式列表向右撐破了 jQuery UI tabs 的框框, 非常的不協調, 這在一般表格也會有此現象, 例如使用 Javascript 的 join() 方法將陣列 tabs 組合成陣列時, 預設是用逗號 "," 串接各元素 :

var table_names=tabs.join(); //預設以 "," 串接
alert table_names;

這樣會得到類似下列這樣毫無空隙的字串 (沒有空格) :

snowball,z0000,z0050,international,inventory,tracking,report,compound_annuity,cron,stock_settings

這個字串如果放在表格中, 就會向右撐破表格的寬度, 破壞整個頁面的規劃. 如果這字串的逗號後面有一個空格, 那就不一樣了 :

snowball, z0000, z0050, international, inventory, tracking, report, compound_annuity, cron, stock_settings

這個字串會被表格的 td 寬度限制, 到右邊界時會折到下一行顯示, 因此不會破壞頁面. 所以 join 時要用 ", " :

var table_names=tabs.join(", ");  //逗號後面加一個空格

同樣的, 在 PHP 用 join() 串接陣列元素時, 也要用這樣的方式為宜 :

$table_name=join(", ", $tabs); //逗號後面加一個空格

而 AmyPHP 需要修改的地方有兩個, 一是 apps/app_install.php 結尾處, 把 tab_names 與 table_names 之串接多加一個空格 :

/*--- 以下是系統作業, 不可修改刪除 ---*/
//更新系統 apps 資料表的 app_name='app' 欄位
$data_array["installed"]="Y";                            //已安裝 "Y"/"N"
$data_array["show_tabs"]="Y";                        //顯示頁籤 "Y"/"N"
$data_array["tab_names"]=join(", ",$tabs);      //空格是為了避免撐破表格
$data_array["table_names"]=join(", ",$tables); //空格是為了避免撐破表格
$data_array["remark"]="OK";                           //安裝結果

二是 sys.php 的 case "remove_app" 模組, 要刪除應用程式 (解除安裝) 時, 須將該應用程式所安裝的 tab 移除, 也要將相關資料表移除, 這時就要從 apps 資料表中讀出這些資料表與頁籤名稱字串, 用 explode 分拆時也要配合以逗號與空格為界 :

//分隔字元為 ", ", 其中空格是為了避免顯示時撐破表格
$tab_names=explode(", ",$RS[0]["tab_names"]); //空格
$table_names=explode(", ",$RS[0]["table_names"]);

2013年6月21日 星期五

更新 jqueryui.php 函式庫的 get_datepicker 函式

為 stock_settings 添加 test_date 欄位時發現 get_datepicker() 函式中的 input 元素忘了給 name 屬性, 這樣表單傳送時將無法傳出 test_date 變數, 故加以修改如下 :
function get_datepicker($id, $change_YM=false, $show_week=false, $locale="zh-TW") {
  .....
  $opt="{".join(",", $opt)."}";
  $result="<input id='".$id."' name='".$id."'>\n".
              "<script>$('#".$id."').datepicker(".$opt.");\n</script>\n";
  return $result;
  }

2012年1月4日 星期三

stockbot 測試問題

今天又申請了3 個 free 的 PHP 伺服器帳號, 結果都一樣, cron jobs 只能允許兩個. 看來要測試 stockbot 只能半用人工, 或以接力方式一個個測試完再申請付費帳號了. 今晚再試試 nopayhost 與 heliohost (這都是 2082 port), 如果都只能用 2 個 cron 就算了. 只有 0000webhost 似乎無限制, 但 mail 有點問題.