幹! 顛覆了我對 xampp的使用經驗.. (以前一直是在 Windows上用的);
現在用了 Centos7 下裝的 xampp, 一切似乎變得很卡! 不僅目錄位置移開了傳統 linux之 /var/www/html 外, 今天讓我最訝異的是: (前幾天在 Centos7上試跑簡單的 php程式, 老說我沒有權限!?... 你他媽的. 都已是 root了. 還要誰才能有權限ㄚ?!... 換軟體就是幹!!~ )
裝了 xampp. 還需要令外裝 php嗎?...
https://www.mysql.tw/2021/12/mysql-php-example.html
歌曲資料庫的新增/修改/刪除/顯示。
首先我們先把登入登出的功能做出來。
預計要有幾個檔案 :
login.php 用來顯示登入表單,以及進行登入驗證。
logout.php 用來登出,清除已登入的狀態。
check.inc.php 用來檢查是否為登入狀態。
process.php 當完成登入後的處理作業。
insert into users(username) values("apple") 這就是一個 SQL query <?php require_once('conn.php'); $result = $conn->query('insert into users(username) values("apple")'); if (!$result) { die($conn->error); } print_r($result); ?> print_r($result); 的 output 會是 1,
1 就代表 true (有成功)的意思
會發現,當我在 add.php 的頁面第二次重新整理後,回到 phpMyAdmin 看,就會出現第二個 apple
add.php:
$username 取代$sql 印出來,看是不是正確的 SQL query把 SQL query 獨立出來變成一個變數 $sql,這樣程式碼的可讀性比較高。在 debug 時,也可以先把 $sql 印出來 echo $sql;,看是不是正確的 SQL query
debug 完之後,記得要把 echo $sql; 拿掉
sprintf() 函式來寫 SQL query,提高程式碼可讀性在 PHP 有一個叫做 sprintf() 的函式,建議是把 SQL query 用 sprintf() 來寫,讓整個 SQL query 字串更好寫也更好看懂:
%d 和 "%s",類似於 placeholder 的感覺 %d 代表:我要放入的是一個 number (這裡的 d 是 decimal 十進位的意思) "%s" 代表:我要放入的是一個 string會按照順序,把 15 帶到 %d 的位置,把 $username 帶到 "%s" 的位置
<?php require_once('conn.php'); $username = 'apple'; $sql = sprintf( 'insert into users(id, username) values(%d, "%s")', 15, $username ); echo $sql; exit(); $result = $conn->query($sql); if (!$result) { die($conn->error); } print_r($result); ?> 組出來的 SQL query 會長這樣:
index.php:
<?php require_once('conn.php'); $result = $conn->query('select * from users;'); if (!$result) { die($conn->error); } while ($row = $result->fetch_assoc()) { echo 'id: '. $row['id'] . '<br>'; echo 'username: ' . $row['username'] . '<br>'; } ?> <h2>新增 user</h2> <form method="POST" action="add.php"> username: <input name="username"> <input type="submit"> </form> header('Location: index.php'); 意思就是:我要回傳一個 response Header 叫做 Location: index.php。瀏覽器接收到這個 response Header 後,就知道我的目的是要跳轉到 index.php,因此就會自動幫我跳轉回到 index.php 這個檔案去 (因為跳轉的太快了,甚至不會看到中間的 add.php 的畫面,就直接跳轉到 index.php 去了)
add.php:
<?php require_once('conn.php'); if (empty($_POST['username'])) { die('請輸入 username'); } $username = $_POST['username']; $sql = sprintf( 'insert into users(username) values("%s")', $username ); echo 'sql: ' . $sql. '<br>'; $result = $conn->query($sql); if (!$result) { die($conn->error); } // 如果有新增成功 echo '新增成功!'; header('Location: index.php'); ?> 上面 add.php 的程式碼,做錯誤處理的地方有兩個:
$_POST['username'] 是否為空值 $conn->query($sql); 這段$result 是 false,那就會執行 die($conn->error);現在,我把 username 欄位設為 unique (代表:不能有重複的 username)
然後我到 index.php 輸入一個重複的 username 叫做 aaa,按下 submit 後就會出現一行錯誤訊息「Duplicate entry 'aaa' for key 'username'」,就是因為在執行到 $conn->query($sql); 時發生錯誤($result 會是 false),因此這行錯誤訊息就是從 die($conn->error); 這行印出來的
「資料庫的讀取結果」的排序不一定會按照 id 順序,如果想要按照 id 排序的話,就在 index.php 的 SQL query 加上 order by id asc 或是 order by id desc
asc 是「由小到大」排列<?php require_once('conn.php'); $result = $conn->query('select * from users order by id asc;'); if (!$result) { die($conn->error); } while ($row = $result->fetch_assoc()) { echo 'id: '. $row['id'] . '<br>'; echo 'username: ' . $row['username'] . '<br>'; } ?> <h2>新增 user</h2> <form method="POST" action="add.php"> username: <input name="username"> <input type="submit"> </form> desc 是「由大到小」排列<?php require_once('conn.php'); $result = $conn->query('select * from users order by id desc;'); if (!$result) { die($conn->error); } while ($row = $result->fetch_assoc()) { echo 'id: '. $row['id'] . '<br>'; echo 'username: ' . $row['username'] . '<br>'; } ?> <h2>新增 user</h2> <form method="POST" action="add.php"> username: <input name="username"> <input type="submit"> </form> conn.php:
<?php $server_name = 'localhost'; $username = 'saffran'; $password = 'rox'; $db_name = 'saffran_db'; $conn = new mysqli($server_name, $username, $password, $db_name); if ($conn->connect_error) { die('資料庫連線錯誤:' . $conn->connect_error); } $conn->query('SET NAMES UTF8'); $conn->query('SET time_zone = "+8:00"'); ?> index.php:
<?php require_once('conn.php'); $result = $conn->query('select * from users order by id desc;'); if (!$result) { die($conn->error); } while ($row = $result->fetch_assoc()) { echo 'id: '. $row['id'] . '<br>'; echo 'username: ' . $row['username'] . '<br>'; } ?> <h2>新增 user</h2> <form method="POST" action="add.php"> username: <input name="username"> <input type="submit"> </form> add.php:
<?php require_once('conn.php'); if (empty($_POST['username'])) { die('請輸入 username'); } $username = $_POST['username']; $sql = sprintf( 'insert into users(username) values("%s")', $username ); $result = $conn->query($sql); if (!$result) { die($conn->error); } // 如果有新增成功 header('Location: index.php'); ?> 後端最基本的這四個功能,就是 CRUD
Create 新增
Read 讀取
Update 編輯
Delete 刪除
透過 PHP 從 MySQL 資料庫拿資料的步驟如下:
query()$conn->query('select now();'); 就是在「向資料庫拿資料」 $result 是否有拿到結果$result 是空的)就代表 query() 發生錯誤。這時,就把錯誤印出來,程式碼不再繼續往下執行 $result 有拿到結果,就用 $row = $result->fetch_assoc();fetch_assoc() 是在把相對應的結果取出來放到 $row 裡面。$row 就是 MySQL query 之後的結果,會根據我 select 的東西給我一個 array,陣列的 key 就是「我 select 的東西 now()」,value 就是「now() 所對應到的值」now() 是 MySQL 提供的一個 function,可以取得現在的時間
data.php:
<?php require_once('conn.php'); $result = $conn->query('select now() as n;'); if (!$result) { die($conn->error); } $row = $result->fetch_assoc(); print_r($row); echo '<br> now: ' . $row['n']; ?> output:
現在,在 MySQL 資料庫裡有這三筆資料:
<?php require_once('conn.php'); $result = $conn->query('select * from users;'); if (!$result) { die($conn->error); } $row = $result->fetch_assoc(); print_r($row); ?> output:
可以看到,每執行一次 $row = $result->fetch_assoc(); 只會印出一筆資料而已
因此,如果想要取得每一筆資料,就需要跑 while 迴圈
while 迴圈取得 table 中的每一筆資料在跑每圈 while 迴圈時,實際上是分成兩個步驟
$result->fetch_assoc(),並把結果放到 $row while 實際上會判斷的是 $row,判斷 $row 是否為空(當資料都拿完後,$row 就會是空的),$row 是空的就是 false<?php require_once('conn.php'); $result = $conn->query('select * from users;'); if (!$result) { die($conn->error); } while ($row = $result->fetch_assoc()) { print_r($row); } ?> output:
可以看到,這樣就可以拿到 table 中的每一筆資料了
把資料用自訂的樣子顯示出來:
<?php require_once('conn.php'); $result = $conn->query('select * from users;'); if (!$result) { die($conn->error); } while ($row = $result->fetch_assoc()) { echo 'id: '. $row['id'] . '<br>'; echo 'username: ' . $row['username'] . '<br>'; } ?> output:
<?php
echo '<div style="position:absolute;top:100px;left:100px">Hello World!</div>';
?>
| 代碼: |
| <?php echo ' <!DOCTYPE html> <html> <head> <title> </title> </head> <body> <span>測試頁面</span> </body> </html> '; ?> |
| 代碼: |
| <?php $Content='Hello!'; echo "$Content"; echo '<br>'; echo '$Content'; ?> |
| 代碼: |
| 1 Hello! 2 $Content |
| 代碼: |
| <?php $Content='Hello!'; //下面寫出了一個HEREDOC,其中標識LABEL可以自定義為任何字串,但要保證�}頭的標識和結尾的標識一樣 echo <<<LABEL $Content LABEL; //結尾的方法:另起一行,打上LABEL。注意結尾的標識前面和後面不要插入任何字元,空格�]不行 echo '<br>';//為了演示方便換行 //NOWDOC和HEREDOC的書寫方式差別在於NOWDOC的識別符號需要用單引號�]圍 echo <<<'LABEL' $Content LABEL; //其他無異 ?> |
| 代碼: |
| <?php //首先在這裡寫好相關的呼叫�{式碼 function OutputTitle(){ echo 'TestPage'; } function OutputContent(){ echo 'Hello!'; } //然後再下面呼叫相關函式就可以了 ?> <!DOCTYPE html> <html> <head> <title><?php OutputTitle(); ?></title> </head> <body> <span><?php OutputContent(); ?></span> </body> </html> |
| 函數 | 描述 |
| basename() | 返迴路徑中的文件名部分。 |
| chgrp() | 改變文件組。 |
| chmod() | 改變文件模式。 |
| chown() | 改變文件所有者。 |
| clearstatcache() | 清除文件狀態緩存。 |
| copy() | 複製文件。 |
| delete() | 參見 unlink() 或 unset() |
| dirname() | 返迴路徑中的目錄名稱部分。 |
| disk_free_space() | 返回目錄的可用空間。 |
| disk_total_space() | 返回一個目錄的磁盤總容量。 |
| diskfreespace() | disk_free_space() 的別名。 |
| fclose() | 關閉打開的文件。 |
| feof() | 測試文件指針是否到了文件末尾。 |
| fflush() | 向打開的文件刷新緩衝輸出。 |
| fgetc() | 從打開的文件中返回字符。 |
| fgetcsv() | 從打開的文件中解析一行,校驗 CSV 字段。 |
| fgets() | 從打開的文件中返回一行。 |
| fgetss() | 從打開的文件中返回一行,並過濾掉 HTML 和 PHP 標籤。 |
| file() | 把文件讀入一個數組中。 |
| file_exists() | 檢查文件或目錄是否存在。 |
| file_get_contents() | 把文件讀入字符串。 |
| file_put_contents() | 把字符串寫入文件。 |
| fileatime() | 返回文件的上次訪問時間。 |
| filectime() | 返回文件的上次修改時間。 |
| filegroup() | 返回文件的組 ID。 |
| fileinode() | 返回文件的 inode 編號。 |
| filemtime() | 返回文件內容的上次修改時間。 |
| fileowner() | 返回文件的用戶 ID (所有者)。 |
| fileperms() | 返回文件的權限。 |
| filesize() | 返回文件大小。 |
| filetype() | 返回文件類型。 |
| flock() | 鎖定或釋放文件。 |
| fnmatch() | 根據指定的模式來匹配文件名或字符串。 |
| fopen() | 打開一個文件或 URL。 |
| fpassthru() | 從打開的文件中讀數據,直到文件末尾(EOF),並向輸出緩衝寫結果。 |
| fputcsv() | 把行格式化為 CSV 並寫入一個打開的文件中。 |
| fputs() | fwrite() 的別名。 |
| fread() | 讀取打開的文件。 |
| fscanf() | 根據指定的格式對輸入進行解析。 |
| fseek() | 在打開的文件中定位。 |
| fstat() | 返回關於一個打開的文件的信息。 |
| ftell() | 返回在打開文件中的當前位置。 |
| ftruncate() | 把打開文件截斷到指定的長度。 |
| fwrite() | 寫入打開的文件。 |
| glob() | 返回一個包含匹配指定模式的文件名/目錄的數組。 |
| is_dir() | 判斷文件是否是一個目錄。 |
| is_executable() | 判斷文件是否可執行。 |
| is_file() | 判斷文件是否是常規的文件。 |
| is_link() | 判斷文件是否是連接。 |
| is_readable() | 判斷文件是否可讀。 |
| is_uploaded_file() | 判斷文件是否是通過 HTTP POST 上傳的。 |
| is_writable() | 判斷文件是否可寫。 |
| is_writeable() | is_writable() 的別名。 |
| lchgrp() | 改變符號連接的組所有權。 |
| lchown() | 改變符號連接的用戶所有權。 |
| link() | 創建一個硬連接。 |
| linkinfo() | 返回有關一個硬連接的信息。 |
| lstat() | 返回關於文件或符號連接的信息。 |
| mkdir() | 創建目錄。 |
| move_uploaded_file() | 把上傳的文件移動到新位置。 |
| parse_ini_file() | 解析一個配置文件。 |
| parse_ini_string() | 解析一個配置字符串。 |
| pathinfo() | 返回關於文件路徑的信息。 |
| pclose() | 關閉由 popen() 打開的進程。 |
| popen() | 打開一個進程。 |
| readfile() | 讀取一個文件,並寫入到輸出緩衝。 |
| readlink() | 返回符號連接的目標。 |
| realpath() | 返回絕對路徑名。 |
| realpath_cache_get() | 返回高速緩存條目。 |
| realpath_cache_size() | 返回高速緩存大小。 |
| rename() | 重命名文件或目錄。 |
| rewind() | 倒回文件指針的位置。 |
| rmdir() | 刪除空的目錄。 |
| set_file_buffer() | 設置已打開文件的緩衝大小。 |
| stat() | 返回關於文件的信息。 |
| symlink() | 創建符號連接。 |
| tempnam() | 創建唯一的臨時文件。 |
| tmpfile() | 創建唯一的臨時文件。 |
| touch() | 設置文件的訪問和修改時間。 |
| umask() | 改變文件的文件權限。 |
| unlink() | 刪除文件。 |
<?php
// 將文本中的年份增加一年.
$text = "April fools day is 04/01/2002\n";
$text.= "Last christmas was 12/24/2001\n";
// 回調函數
function next_year($matches)
{
// 通常: $matches[0]是完成的匹配
// $matches[1]是第一個捕獲子組的匹配
// 以此類推
return $matches[1].($matches[2]+1);
}
echo preg_replace_callback( "|(\d{2}/\d{2}/)(\d{4})|", "next_year", $text);
?>
將 CentOS 7 網卡名稱修改, 用回 Eth0 的方法: 1) # vi /etc/sysconfig/grub 內容大概是這樣: GRUB_TIMEOUT=5 GRUB_DISTRIBUTOR="$(sed 's, release...