【PHP】PDO::query()

參考資料 ----
PDO::query
The PDOStatement class

突然發現老人家的寄掛網站主機有 error_log,下載來看,裡面有警告,內容如下:
 
Parameter must be an array or an object that implements Countable in .... xxx.php on line 10
 

對照我的程式,我是這樣寫的:
 
...
...

$sql = "SELECT * FROM table1";
$rs = $pdo->query($sql);
if(count($rs)>0)
{    // 查詢有記錄
    ...
    ...
}
 

這樣的寫法為什麼會有警告?於是上 PHP 官網看了 PDO::query() 的用法
 
PDO::query() executes an SQL statement in a single function call, returning the result set (if any) returned by the statement as a PDOStatement object.

For a query that you need to issue multiple times, you will realize better performance if you prepare a PDOStatement object using PDO::prepare() and issue the statement with multiple calls to PDOStatement::execute(). 
(如果有段查詢語句需要執行多次,使用 PDO::prepare() 會有更佳的效能)
 

似乎 官方較建議 要有 PDO::prepare(),雖然我的查詢只執行一次,於是嘗試下面的寫法:
 
...
...

$sql = "SELECT * FROM table1";
$pdoStat = $pdo->prepare($sql);
$pdoStat->execute();
$rs = $pdoStat->fetchAll();
if(count($rs)>0)
{   // 查詢有記錄
    ...
    ...
}
 
這樣 error_log 就不會出現警告了

順便一提,千萬不要用 PDOStatement::rowCount() 去取得查詢結果的記錄筆數,官方並不保證這樣的寫法可適用所有的資料庫!!!!!!
雖然從字面很容易誤以為這是查詢結果的記錄筆數
老人家的朋友就曾經用這方法去取得查詢筆數,結果造成災難!

PHP 官方文件寫道:
這個函式的功能是用來取得執行 INSERT, UPDATE, DELETE 後,受影響的記錄數,
就像是我們在資料庫管理工具(如:ToadSQLServer Enterprise Manager...) 下了 INSERT, UPDATE, DELETE 後,會顯示受影響的記錄數。 

【Android Studio】Dependencies using groupId com.android.support and androidx.* can not be combined ...

參考資料 ----
Migrating to AndroidX


隨著 Android Studio 更新 Gradle Version5.1.1,在 app 層級的 build.gradle 出現了錯誤



把滑鼠移到 com.android.support:support-v4:28.0.0 的紅底線,出現的說明
,老人家有閱讀障礙,所以把說明做了斷行,如下:
Dependencies using groupId com.android.support and androidx.* can not be combined 
but found 
IdeMavenCoordinates
{
 myGroupId='com.android.support', 
 myArtifactId='asynclayoutinflater', 
 myVersion='28.0.0', 
 myPacking='aar', 
 myClassifier='null'
} 

and 

IdeMavenCoordinates
{
 myGroupId='androidx.localbroadcastmanager', 
 myArtifactId='localbroadcastmanager', 
 myVersion='1.0.0', 
 myPacking='aar', 
 myClassifier='null'
}

 incompatible dependencies less... (Ctrl+F1) 

 Inspection info:
 There are some combinations of libraries, 
 or tools and libraries, 
 that are incompatible, 
 or can lead to bugs.
 
 One such incompatibility is compiling with a version of the Android support libraries that is not the latest version
 (or in particular, a version lower than your targetSdkVersion).  
 
 Issue id: GradleCompatible



大意好像是說我的專案所相依的函式庫出現衝突!一個是 com.android.support,一個是 androidx.localbroadcastmanager,印象中 androidx. 開頭的函式庫是 jetpack 在用的;可是一來我還不懂 jetpack,所以沒改用 jetpack,二來是我的專案也沒使用 jetpack......

爬了好多文,嘗試加入設定,讓 Android Studio 明確使用來自 com.android.support,或是排除引用 androidx. 開頭的,不過都失敗。

Dependencies using groupId com.android.support and androidx.* can not be combined 搜尋,跳出了 Migrating to AndroidX 這一篇,看似要開發者改用這個。

依照指示,在該頁的 Artifact mappings 置換成 AndroidX
 
...
...

dependencies {
    // implementation 'com.android.support:support-v4:28.0.0'
    // implementation "com.android.support:customtabs:28.0.0"
    implementation 'androidx.legacy:legacy-support-v4:1.0.0'
    implementation 'androidx.browser:browser:1.0.0'

 


就 Sync 成功了,不知道是不是正解,提供遇到同樣問題的朋友參考。





【CentOS7】top 的進階版 htop

[root]# yum  install  htop


安裝後,任何權限的使用者都可使用

[user]$ htop

【CentOS7】圖形界面套件管理 yumex

[root]# yum  install  yumex


安裝後,按功能表的 "應用程式"
其他
→ 就可以看到 "Yum Extender"


【Delphi7】字串的處理

uses ..., StrUtils;

...
...

var
    wstr: WideString;
    str: string;
    ss: string;
    x: integer;
begin
    // 同樣的字串, 存成不同的字串型態
    // 就會有不同的結果
    wstr := '一二三四五67八九十';
    str := '一二三四五67八九十';
    x := Length(str);     // x = 18 = 8 個中文字 + 2 個英數字 = 8*2 + 2 = 18
    x := Length(wstr):    // x = 10 = 實際字數

    ss := LeftStr(str,6);     // ss = '一二三四五6'
    ss := LeftStr(wstr,6);    // ss = '一二三四五6'
    ss := copy(str, 6);       // ss = '一二三' 
    ss := copy(wstr, 6);      // ss = '一二三四五6'
end;

【Delphi】以程式碼建立 Excel 檔

本筆記會持續補充


 
...
const
    xlWorksheet = -4167;

var
    myExcel, mySheet: Variant;
    sFileName: string;
    iRow: integer;
begin
    // 若資料夾不存在, 則建立
    CreateDir('C:\TEMP');
    sFileName := 'C:\TEMP\test.xls';
    Deletefile(sFileName);    // 則已存在同名檔案, 則刪除
    
    MyExcel := CreateOleOBject('Excel.Application');    // 新建一個 Excel 檔
    MyExcel.WorkBooks.Add;    // 新增活頁簿
    MyExcel.Visible := true;    // 程式在對 Excel 寫入資料期間, 可以看得到過程
                                // 若 false, 就看不到
    // 指定 工作表顯示比例
    mExcel.ActiveWindow.Zoom := 75;    // 顯示比例為 75%

    MyExcel.WorkBooks[1].Saveas(sFileName);    // 指定給 Excel 的檔名

    // 新增工作表
    myWorkSheets := MyExcel.WorkBooks[1].WorkSheets;
    myWorkSheets.Add(null, null, 新增的工作表數量, xlWorksheet);    // 注意要在 const 區 或 var 區 宣告 xlWorksheet 的值
    // 第 1 個參數: 新工作表要在目前哪個工作表前
    // 第 2 個參數: 新工作表要在目前哪個工作表後
    // 第 3 個參數: 新增工作表數量, 預設值為 1
    // 第 4 個參數: xlWorksheet(工作表,-4167)、 xlChart(圖表, -4109)、 xlExcel4MacroSheet(Excel 版本 4 巨集表, 3)、 xlExcel4IntlMacroSheet(Excel 版本 4 國際巨集表, 4)
    
    iRow := 1;

    // 切換目前編輯的工作表
    myExcel.WorkSheets[1].Activate;

    // 指定工作表
    mySheet := myExcel.WorkBooks[1].WorkSheets[1];
    mySheet.Cells[iRow,1] := '文字';    // 括號內 [橫列, 直欄]
    mySheet.Cells[iRow,1].Font.Bold := True;    // 設定粗體字
    mySheet.Range['B1','E1'].Merge;   // 合併儲存格

    // 輸入的資料是數字, 但要 Excel 當做文字處理(例如:電話號碼)
    mySheet.Cells[iRow,1] := '''0912345678';    // 可以看到該儲存格的左上角有個綠色的三角標記
    // 另一種表示法
    mySheet.Cells[iRow,1].NumberFormatLocal := '@';    // 指定儲存格格式為文字, 但注意要在儲存格存入值前指定
                                                       // 不然數字太大, 會馬上被轉成科學記號表示法
    mySheet.Cells[iRow,1] := '0912345678';

    Inc(iRow);    // 移至下一列

    mySheet.Cells[iRow,1] := 1;    // 第一欄: A
    mySheet.Cells[iRow,2] := 2;    // 第二欄: B
    mySheet.Cells[iRow,3] := 3;    // 第三欄: C
    mySheet.Cells[iRow,4] := 4;    // 第四欄: D
    mySheet.Cells[iRow,5] := 5;    // 第五欄: E
    // 儲存格內寫公式
    mySheet.Cells[iRow,6] := '=SUM(A'+IntToStr(iRow)+':E'+IntToStr(iRow)+')';
    // 另一種表示法, 這種寫法的好處是不用去算第 某 欄的英文是什麼
    mySheet.Cells[iRow,6] := '=SUM(R'+IntToStr(iRow)+'C1:R'+IntToStr(iRow)+'C5)';

    // 給予某個儲存格別名
    mySheet.Cells[iRow,6].Name := 'TotalAmount';
    // 使用時機舉例
    // 列數不確定
    // 每列的第 1 欄為單品金額,
    // 第 2 欄是單品金額佔總金額的百分比, 計算公式為 第 1 欄/總金額 * 100
    // 要列完所有單品金額後的下一列才會列總金額
    // 這時還無法得知總金額在第幾列, 所以(以第 1 列為例) 公式可以寫 '=A1/TotalAmount'


    // 儲存格是數字
    // 指定儲存格的格式
    mySheet.Cells[iRow,6].NumberFormatLocal := '#,##0_ ';    // 數值(整數位 三位一撇)
    mySheet.Cells[iRow,6].NumberFormatLocal := '0.00%';  // 百分比(小數兩位)


    // 單一儲存格畫框線
    // Borders 內的數字 5:左上右下斜線, 6:左下右上斜線, 7:左邊線, 8:上邊線, 9:下邊線, 10:右邊線, 11:垂直線, 12:水平線
    mySheet.Cells[iRow,4].Borders[6].LineStyle := 1;    // 1:實線, -4115:短虛線, 4:長短虛線, 5:長短短虛線, -4118:細虛線, -4119:雙實線
    mySheet.Cells[iRow,4].Borders[6].Weight := 1;    // 框線粗細, 數字愈大愈粗

    // 指定某一區域劃框線
    mySheet.Range['A1','I8'].Borders[7].LineStyle := 1;
    mySheet.Range['A1','I8'].Borders[8].LineStyle := 1;
    mySheet.Range['A1','I8'].Borders[9].LineStyle := 1;
    mySheet.Range['A1','I8'].Borders[10].LineStyle := 1;
    mySheet.Range['A1','I8'].Borders[11].LineStyle := 1;
    mySheet.Range['A1','I8'].Borders[12].LineStyle := 1;

    // 凍結窗格
    mySheet.Cells[2,1].Select;    // 指定要凍結的位置
    myExcel.ActiveWindow.FreezePanes := true;

    // 最適欄寬
    mySheet.Cells.EntireColumn.AutoFit;

    // 變更工作表名稱
    mySheet.Name := '自定工作表名稱';
end;
 

【Delphi】多橫列文字的 TButton


Form 設計時期:

放一個 TLabelForm
滑鼠移至 Form
點滑鼠右鍵
View as Text
畫面切換到文字模式,找到 TLabel 所在位置,將原 Caption 的文字加上 #13 再加第二列的文字,#13 就是讓 TLabelCaption 多列,如:

原來為

Caption = 'Label1'

加上

Caption = 'Label1' + #13 + '第二列'


點滑鼠右鍵
View as Form


再到程式碼內
 
type
    // 建立一個繼承自 StdCtrls.TButton 的自定 TButton 類別
    TButton = class(StdCtrls.TButton)
    protected
        procedure CreateParams(var Params: TCreateParams); override;
    end;

    ...
    ...

implementation

    ...
    ...

procedure TButton.CreateParams(var Params: TCreateParams);
begin
  inherited CreateParams(Params);
  Params.Style := Params.Style or BS_MULTILINE;
end;
 




相關筆記 ----
【Delphi】多橫列的 TLabel

【Android】AdMob / AdSense 與 Google Play APP的禁忌

我也真夠荽的,踩了好幾次 AdMob 及 AdSense 的地雷,因此寫下這篇筆記,供要加入 AdMob 及 AdSense,成為其廣告發佈商的朋友做為參考,前車之鑑,避免重蹈覆轍。

若您有部落格 或 APP,部落格及 APP 都不能有 YouTube 的連結,除非您能證明所連結的 YouTube 影片版權為您所有。

Android APP 內若有連結,該連結所導向的網站不能有 Donate (捐贈) 的功能;Google Play 規定所有與金流有關的動作,都必須透過 Google Play 進行,除非您的 APP 是販售實體商品的購物 APP。

插頁廣告是在從某一個 Activity 畫面至另一個 Activity 畫面時顯示的廣告,不能在 APP 一啟動時APP 結束時 播放;但也不能每次跳轉時都顯示,播放廣告的比率應低於 50%,也就是至多只能每跳轉 2 次才能播一次




【Oracle】查詢當 欄位1 值相同時,取 欄位2, 3, ... 排序後第一筆記錄

查詢當 欄位1 值相同時,取 欄位2, 3, ... 排序後第一筆記錄

通常用在某欄位值相同時有數筆記錄,只取第一筆。


SELECT * FROM
(
    SELECT a.*, row_number() OVER (PARTITION BY field1 ORDER BY field2 DESC, field3 DESC) rn FROM
    (
        SELECT field1, field2, field3, field4, field5  FROM table1
            WHERE field5='關鍵值'
    ) a
) WHERE rn=1

【Delphi7】讀取 UTF-8 文字檔

Delphi 預設讀取 ASCII 文字檔,若要讀取 UTF-8 格式的文字檔,則需要轉換。

Form1 上放一個 buttonmemo,然後在 button onclick event 寫入以下程式碼:


procedure TForm1.Button1Click(Sender: TObject);
var
    myfile: TextFile;
    s: string;
begin
    memo1.clear;

    AssignFile(myfile, 'd:\temp\list.csv');
    Reset(myfile);

    while not EOF(myfile) do
    begin
        ReadLn(myfile,s);
        s := UTF8ToAnsi(s);
        memo1.Lines.Add(s);
    end;

    CloseFile(myfile);
end;