Ruofan Wei
    • Create new note
    • Create a note from template
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Write
        • Only me
        • Signed-in users
        • Everyone
        Only me Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
      • Invitee
      • No invitee
    • Publish Note

      Publish Note

      Everyone on the web can find and read all notes of this public team.
      Once published, notes can be searched and viewed by anyone online.
      See published notes
      Please check the box to agree to the Community Guidelines.
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Save as template
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Sharing URL Create Help
Create Create new note Create a note from template
Menu
Options
Versions and GitHub Sync Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Write
Only me
  • Only me
  • Signed-in users
  • Everyone
Only me Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
Invitee
No invitee
Publish Note

Publish Note

Everyone on the web can find and read all notes of this public team.
Once published, notes can be searched and viewed by anyone online.
See published notes
Please check the box to agree to the Community Guidelines.
Engagement control
Commenting
Permission
Disabled Forbidden Owners Signed-in users Everyone
Enable
Permission
  • Forbidden
  • Owners
  • Signed-in users
  • Everyone
Suggest edit
Permission
Disabled Forbidden Owners Signed-in users Everyone
Enable
Permission
  • Forbidden
  • Owners
  • Signed-in users
Emoji Reply
Enable
Import from Dropbox Google Drive Gist Clipboard
   owned this note    owned this note      
Published Linked with GitHub
Subscribed
  • Any changes
    Be notified of any changes
  • Mention me
    Be notified of mention me
  • Unsubscribe
Subscribe
# 後端基礎 `PHP` 與 `MySQL` ###### tags: `Tag(後端基礎 PHP 與 MySQL!)` ## `PHP` 是什麼 >[參考資料](https://www.happycoding.today/posts/23) 3分鐘快速認識PHP PHP語言是伺服器端(Server)執行的網頁,==PHP必須先在伺服器端執行完==後,再將結果傳至使用者端(Client)的瀏覽器中檢視結果,所以<font color="#c7b198">必須使用網站伺服器,且伺服器要支援PHP。</font> ## 前端與後端的差別 >[參考資料](https://noootown.com/frontend-backend-breakfast/) 買早餐也能了解前端 vs 後端? >[參考資料](https://15days.website/posts/frontend-vs-backend) 什麼是前端?什麼是後端? 連到網站,==帶有畫面和動畫的這些檔案==,都是從伺服器傳送來的,製作這些畫面的,都是前端。 填入帳號密碼,按下發送,內容傳到伺服器。伺服器處理各個request和response,然後會==幫你做驗證,確定你可不可以登入==,都是後端。 回到主畫面,右上角寫著「嗨!XXX」,這個XXX叫什麼名字,也都是後端幫忙前端填上去的,而這些==動態填上去的資料,都是存放在伺服器的資料庫(database)==。 ## 什麼是資料庫 >[參考資料](https://medium.com/pierceshih/%E7%AD%86%E8%A8%98-%E4%BD%95%E8%AC%82%E8%B3%87%E6%96%99%E5%BA%AB%E7%B3%BB%E7%B5%B1-53b59aacbfb7) 何謂資料庫系統 >[參考資料](https://ithelp.ithome.com.tw/articles/10185512) 資料庫系統應用 - 關聯式資料庫 資料庫可以當成是資料的檔案櫃,當需要的時候才將所需的資聊拉出來。一般來說,==資料庫可以提供「新增 Create」、「查詢 Read」、「更新 Update」、「刪除 Delete」,簡稱 CRUD。== 資料庫大致上可以分為兩種類型: ``` c * 關聯式資料庫(Relational Database Management System,縮寫為RDBMS) * 非關係型資料庫(Not Only SQL,縮寫為 NoSQL) ``` ### 關聯式資料庫 ==使用簡單,穩定度高==,常見如 MySQL、PostgreSQL、Microsoft SQL Server、SQLite。 ``` c * 資料是以一個或是多個資料表 (table) 的方式存放 * 資料之間有明確的關聯 以 To-do List 舉例,以 table 資料表來存放 todo 跟 user 這兩種資料, 並在兩個資料表之間,設定「使用者擁有 todo」這個關聯。 * 關聯式資料庫是以 SQL 語言操作 SQL管理與查詢關聯式資料庫的程式語言 ``` ### 非關聯式資料庫 NoSQL 資料庫,常見為 mongoDB。 ``` c * 彈性高,不限定於「關聯式資料庫」的做法 NoSQL 更關注資料所代表的人(例如使用者)與物(例如一篇分享在社交平台上的文章)的「狀態」變動, 例如文章被分享、按讚等。 * 不講求資料同步,只求最後結果一致 處理一篇在 Facebook 上的 po 文有多少人按讚時,這個訊息的準確性就不是非常重要。 部分使用者可能要隔數十秒後才看到按讚數從 99 轉到 100 ``` ## 什麼是 `Session` >[參考資料](https://fred-zone.blogspot.com/2014/01/web-session.html) Web 技術中的 Session 是什麼? >[白話 Session 與 Cookie:從經營雜貨店開始](https://medium.com/@hulitw/session-and-cookie-15e47ed838bc) > [淺談 Session 與 Cookie:一起來讀 RFC](https://blog.huli.tw/2019/08/09/session-and-cookie-part2/) > [深入 Session 與 Cookie:Express、PHP 與 Rails 的實作](https://blog.huli.tw/2019/08/09/session-and-cookie-part3/) ==Session 的機制==<font color="#ad9d9d">就像是你去飲料店下了單以後,得到號碼牌,然後你走開幾步,店員就忘了你是誰。 如果你想去取飲料,你就得靠這張號碼牌,去跟店員領,店員會跟據這號碼牌,認定你是顧客、是否點過餐、知道你點了什麼東西,然後可以接著給你屬於你的飲料。 點了什麼飲料,都是記錄在 Server 裡,可能是 Database、記憶體或是檔案,可以以任何一種形式儲存。然後,當你去領飲料時,店員會輸入你的號碼,用你的號碼得知你是否點過餐、點了什麼東西。</font> ## 什麼是 `Cookie` >[參考資料](https://fred-zone.blogspot.com/2014/01/web-session.html) Web 技術中的 Session 是什麼? <font color="#ad9d9d">兩種方法讓 Client 取得號碼牌,一個是用 ==Cookie==,另一個是直接輸出並嵌入頁面之中的方法(就是要你把號碼背起來)。 拿號碼牌去 Server 要資料,主要也分為兩種方法,Cookie 和運用標準的 Query string/POST body方法。(其實只要能把號碼傳到 Server 上,任何方法都行) Cookie 就是</font>==存在瀏覽器裡的一些資訊。== --- ## `Apache` 與 `PHP` 原理簡介 >[color=#c4a244]Server → 專門處理 request & response 的程式 >[color=#c4a244]資料資料庫系統 → 專門處理資料的程式 :::warning ``` c request → apache(server) → php → output(html) → apache → response ``` ``` c * 接收 request * server 轉給 php 處理 * php 處理轉成 html * html 傳給 server * server 回傳 response ``` ::: --- ## 基礎 `PHP` 語法 ``` c * 要用 <?php ?> 包起來 * 每一步指令完成後一定要加 ; * 宣告變數用 $ 開頭 * 字串連接用 . 而不是 + ``` ##### 陣列 `array` ###### 設定陣列: ```php $arr = array(1,2,3,4,5) ``` ###### 取得陣列元素: ```ph echo $arr[i]; ``` ###### 取得陣列長度: ```ph echo sizeof($arr); ``` ###### 輸出完整陣列 ##### `var_dump `: 輸出每一個內容的型態跟值: type, value ##### `print_r` : 比較簡潔、沒有輸出型態: value --- ## `MySQL` 基礎語法 #### <font color="#3ca59d">新增`(INSERT)`</font> ###### 使用 `INSERT INTO `指令可以新增資料: ```php INSERT INTO "表格名" ("欄位1", "欄位2", ...) VALUES ("值1", "值2", ...); ``` ```php= INSERT INTO users ("name", "email", "age", "salary") VALUES ("Mark", "mark@gmail.com", 20, 70000); ``` #### <font color="#3ca59d">查詢`(SELECT)`</font> ###### 使用 `*` 查詢全部資料: ```ph SELECT * FROM [資料表名稱]; ``` ###### (條件)`where`針對特定屬性選取: ```ph SELECT * FROM [資料表名稱] WHERE [條件式]; ``` ###### ==排序加上 `ORDER BY`==,設定由大到小 `DESC` 或由小到大 `ASC`: ```ph SELECT * FROM users ORDER BY age DESC; ``` ###### ==`as` 改名==,後面接 `<new-name>` ```ph SELECT created_at as time, nickname as name FROM users ``` ###### 函式→數量 `COUNT`、加總 `SUM`、平均值 `AVG`、最大值 `MAX` 和最小值 `MIN`。 ###### `COUNT`計算筆數 ```ph SELECT COUNT([欄位]) FROM [資料表名稱] WHERE [條件式]; ``` ###### 取該欄位底下最大值`MAX` / 最小值`MIN` ```ph SELECT MAX([欄位]) FROM [資料表名稱]; ``` ```ph SELECT MIN([欄位]) FROM [資料表名稱]; ``` ###### `SUM`欄位底下值加總 ```ph SELECT SUM([欄位]) FROM [資料表名稱]; ``` #### <font color="#3ca59d">刪除 `DELETE`</font> ###### 先用 `SELECT` 指令撈取要操作的資料 ##### <font color="#c7b198">`WHERE` 在這一項非常重要,沒有加上 `WHERE `則系統會對所有行進行動作,即會刪除所有資料。</font> ```ph DELETE FROM users WHERE id=1; ``` #### <font color="#3ca59d">修改`(UPDATE)`</font> ```php UPDATE "表格名" SET "欄位1"=[新值] WHERE "條件"; ``` ###### `SET` 指定要修改的列和值 ##### <font color="#c7b198">`WHERE` 很重要,如果忘記寫上 `WHERE` 子句,會意外更新表中的所有行。</font> ```p UPDATE users SET name=Mark WHERE id=1; ``` --- ## 前端傳資料給後端 #### `form `方法 ``` c * 在 form 標籤中將資料帶到後端 * form 當中要加入 method 跟 action 兩個屬性 * method: HTTP method * action: 要帶入的檔案 ``` ```c // 將內容帶入 index.php 這個檔案當中 <form method="GET" action="index.php"> id: <input type="text" name="id"/> name: <input type="text" name="name"/> age: <input type="text" name="age"/> <input type="submit"/> </form> ``` #### `index.php`可以用`$_GET`把送的資料拿出來 ```c <?php // 用empty檢查表單是否為空的 if(empty($_GET['name']) || empty($_GET['age'])){ echo '資料有缺,請再次填寫<br>'; exit(); // 終止程序 }; // 接收 method 為 GET 的 From input echo "Hello!" . $_GET['name'] . "<br>"; echo "Your age is" . $_GET['age'] . "<br>"; print_r($_GET); ?> ``` #### 用 GET 回傳的代號來做對應的處理 ##### `錯誤處理` ```c <?php echo "wheeeeeeeeee" ?> <form method="GET" action="data.php"> name: <input type="text" name="name"> age: <input type="text" name="age"> <input type="submit"> </form> ``` ###### `用 query string 在導向時加上 errCode` ```c if (empty($username) || empty($password)) { header('Location: login.php?errCode=1'); die('請檢查資料'); } ``` ###### `導回到 login.php 時,可用 $_GET 取得 query string 的值,以做對應的處理` ```c if (!empty($_GET['errCode'])) { $code = $_GET['errCode']; $msg = 'Error'; if ($code === '1') { $msg = '請輸入內容'; } echo '<p class="error">' . $msg . '</p>'; } ``` --- ## 資料庫連線 ###### `conn.php` >[color=#c4a244]conn.php 有帳號密碼等重要資料,放在 git.ignore 不要上傳至 GitHub ```c $server_name='localhost'; // server 名稱 $user_name='ruofan'; // 帳號 $user_password='ruofan'; // 密碼 $db_name='ruofan'; // db 名稱 $conn = new mysqli($server_name ,$user_name, $user_password, $db_name); // 一切的起源就是 mysqli 這個 class // 內中的伺服器名稱 / 帳號 / 密碼 / 與資料庫名的排序是固定的 if ($conn->connect_error) { // connect_error 是內建的語法,表示連線Failed die('資料庫連線錯誤:' . $conn->connect_error);// die = 印出括號內文字 + 阻止底下程式執行 } $conn->query('SET NAMES UTF8'); // 加上編碼,顯示中文才不會有問題 $conn->query('SET time_zone = "+8:00"'); // 設定為台灣時區 ``` ##### 讀取資料 ```c <?php require_once('conn.php'); // 連線到資料庫 // 將 SQL 撈出的資料存在 $result 這個變數中 // select * 會撈取全部資料,意指全部的資料會放在 𝑟𝑒𝑠𝑢𝑙𝑡 // 檢查 SQL query 是否使用成功 $result = $conn->query("SELECT * FROM users"); if (!$result) { die($conn->error); // 中斷後面程序並顯示內容,() 內可以輸入訊息字串 } while ($row = $result->fetch_assoc()) { // 把 𝑟𝑒𝑠𝑢𝑙𝑡中的資料,一筆一筆抓出來給row // 用一個 while 迴圈,把資料一筆一筆印出 // row 每一次只會顯示 $result 中的一筆資料 echo "id:" . $row['id'] . '<br>'; echo "username:" . $row['username'] . '<br>'; } ?> ``` ##### 新增資料 ```c <?php require_once('conn.php'); // 連線到資料庫 // $_POST['key-name'] 取得輸入的資料 // empty() 判斷值是否為 null if (empty($_POST['username'])) { // // 中斷後面程序並顯示內容,() 內可以輸入訊息字串 die('請輸入 username'); } $username = $_POST['username']; // sprintf() 裡面可以放入替代字元 $sql = sprintf( // 插入新欄位 "insert into users(username) values('%s')", // %s 代表字串 $username ); // 執行結果存在 $result 這個變數中 $result = $conn->query($sql); if (!$result) { die($conn->error); } header("Location: index.php"); // 自動跳轉回 index.php ?> ``` ##### 刪除資料 ```c <?php require_once('conn.php'); // 連線到資料庫 if (empty($_GET['id'])) { die('請輸入 id'); } $id = $_GET['id']; $sql = sprintf( "delete from users where id = %d", $id ); echo $sql . '<br>'; $result = $conn->query($sql); if (!$result) { die($conn->error); } if ($conn->affected_rows >= 1) { // 判斷影響 1 列以上資料 echo '刪除成功'; } else { echo '查無資料'; } // header("Location: index.php"); ?> ``` ##### 編輯資料 ```c <?php require_once('conn.php'); if (empty($_POST['id']) || empty($_POST['username'])) { die('請輸入 id 與 username'); } $id = $_POST['id']; $username = $_POST['username']; $sql = sprintf( "update users set username='%s' where id=%d", $username, $id ); echo $sql . '<br>'; $result = $conn->query($sql); if (!$result) { die($conn->error); } header("Location: index.php"); ?> ``` --- ## 用 `while` 迴圈拿取 `table` 內所有 `row` 的資料 ```c <?php while ($row = $result-> fetch_assoc()) { ?> <div class="comment"> <div class="avatar"></div> <div class="text"> <div class="info"> <h3 class="nickname"><?php echo escape($row['nickname']) ?></h3> <h3 class="time"><?php echo escape($row['created_at']) ?></h3> </div> <div class="content"><?php echo htmlspecialchars_decode($row['content']) ?></div> </div> </div> <?php } ?> ``` --- ## 如何使用 `Session` #### 存取 `session` ```c //要使用 Session,都要在開頭使用 session_start() session_start(); $username = htmlspecialchars($_POST['username']); //把資料存在 Session 對應的 key 裡面 $_SEESION['username'] = $username; ``` #### 取用 `session` ```c session_start(); //如果 session 內有存過 username, //則宣告變數 $username 為剛才存的 $_SESSION['username'] if(isset($_SESSION['username'])) { $username = $_SESSION['username']; } ``` #### 比對資料是否存在於資料庫 >[color=#db1a4a]用 `num_rows` 來達成 ```c //如果有找到對應的資料,就把 username 存在 session 裡,導回 index.php if ($result->num_rows) { $_SESSION['username'] = $username; header("Location: index.php"); //若是失敗,導回 index.php,顯示出錯誤 } else { header('Location: login.php?errCode=2'); } ``` --- ## 用 `htmlspecialchars()` 防止 `input` 的內容被放上程式碼後跑版 ###### 建立函式 ```c function escape($str) { return htmlspecialchars($str, ENT_QUOTES); //ENT_QUOTES可以轉換單雙引號 } ``` ###### `使用 htmlspecialchars_decode 來把資料庫內的 unicode 解析成特殊符號` ```c <h3 class="time"><?php echo escape($row['created_at']) ?></h3> <div class="content"><?php echo htmlspecialchars_decode($row['content']) ?></div> ``` --- ## 在函式內使用全域變數 ###### `使用 global ` ```c function getUserFromUsername($username) { global $conn; $sql = "SELECT * FROM nicolakacha_users WHERE username='$username'"; $result = $conn->query($sql); $row = $result->fetch_assoc(); return $row; } ``` --- ## 資料庫欄位型態 `VARCHAR` 跟 `TEXT` 的差別是什麼 >[參考資料](https://hsiangfeng.github.io/php/20190904/1799668484/) 從基礎學習 ThinkPHP-基礎 MySQL 學習-資料表篇 >[參考資料](https://ithelp.ithome.com.tw/articles/10203456?sc=iThelpR) 常用的資料庫資料型態 >[參考資料](http://n.sfs.tw/content/index/10266) [Mysql] 資料型態 ``` c * char : 長度為 0 ~ 255,當儲存字串不夠 255 的長度時,會用空格補齊剩餘的空間,因此讀取時必須把後面空格去除。 * varchar: 可以設定最大長度,適合用在文字量少的欄位,可以有預設值。 * text: 不可設定長度,適合用在文字量多的欄位,最大长度为 2 ^ 31 - 1 個字符,不可以有預設值。 ``` ##### 查詢速度: ```c * char 最快, varchar 次之,text 最慢。 * 由于 varchar 查询速度更快,所以能用 varchar 的时候就不用 text。 ``` --- ## 使用隨機函數,讓圖片可以隨機呈現 >[參考資料](https://pjchender.blogspot.com/2015/03/php-mysql_6.html) 隨機函數 #### 新建一個資料夾,把圖片放進去 ![](https://i.imgur.com/DVWxcw2.png) ```c * num則是變數名稱,而這個變數是由1~15組成的隨機數字 * rand() 函數返回隨機整數。 ``` ###### `index.php` ```c <div class="avatar"> <?php $num = rand(1,15); ?> <img class="avatar_img" src="img/<?php echo $num ?>.png""> </div> ```

Import from clipboard

Advanced permission required

Your current role can only read. Ask the system administrator to acquire write and comment permission.

This team is disabled

Sorry, this team is disabled. You can't edit this note.

This note is locked

Sorry, only owner can edit this note.

Reach the limit

Sorry, you've reached the max length this note can be.
Please reduce the content or divide it to more notes, thank you!

Import from Gist

Import from Snippet

or

Export to Snippet

Are you sure?

Do you really want to delete this note?
All users will lose their connection.

Create a note from template

Create a note from template

Oops...
This template is not available.
Upgrade
All
  • All
  • Team
No template found.

Create custom template

Upgrade

Delete template

Do you really want to delete this template?
Turn this template into a regular note and keep its content, versions, and comments.

This page need refresh

You have an incompatible client version.
Refresh to update.
New version available!
See releases notes here
Refresh to enjoy new features.
Your user state has changed.
Refresh to load new user state.

Sign in

Forgot password

or

By clicking below, you agree to our terms of service.

Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
Wallet ( )
Connect another wallet

New to HackMD? Sign up

Help

  • English
  • 中文
  • Français
  • Deutsch
  • 日本語
  • Español
  • Català
  • Ελληνικά
  • Português
  • italiano
  • Türkçe
  • Русский
  • Nederlands
  • hrvatski jezik
  • język polski
  • Українська
  • हिन्दी
  • svenska
  • Esperanto
  • dansk

Documents

Help & Tutorial

How to use Book mode

How to use Slide mode

API Docs

Edit in VSCode

Install browser extension

Get in Touch

Feedback

Discord

Send us email

Resources

Releases

Pricing

Blog

Policy

Terms

Privacy

Cheatsheet

Syntax Example Reference
# Header Header 基本排版
- Unordered List
  • Unordered List
1. Ordered List
  1. Ordered List
- [ ] Todo List
  • Todo List
> Blockquote
Blockquote
**Bold font** Bold font
*Italics font* Italics font
~~Strikethrough~~ Strikethrough
19^th^ 19th
H~2~O H2O
++Inserted text++ Inserted text
==Marked text== Marked text
[link text](https:// "title") Link
![image alt](https:// "title") Image
`Code` Code 在筆記中貼入程式碼
```javascript
var i = 0;
```
var i = 0;
:smile: :smile: Emoji list
{%youtube youtube_id %} Externals
$L^aT_eX$ LaTeX
:::info
This is a alert area.
:::

This is a alert area.

Versions and GitHub Sync
Upgrade to Prime Plan

  • Edit version name
  • Delete

revision author avatar     named on  

More Less

No updates to save
Compare
    Choose a version
    No search result
    Version not found
Sign in to link this note to GitHub
Learn more
This note is not linked with GitHub
 

Feedback

Submission failed, please try again

Thanks for your support.

On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

Please give us some advice and help us improve HackMD.

 

Thanks for your feedback

Remove version name

Do you want to remove this version name and description?

Transfer ownership

Transfer to
    Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

      Link with GitHub

      Please authorize HackMD on GitHub
      • Please sign in to GitHub and install the HackMD app on your GitHub repo.
      • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
      Learn more  Sign in to GitHub

      Push the note to GitHub Push to GitHub Pull a file from GitHub

        Authorize again
       

      Choose which file to push to

      Select repo
      Refresh Authorize more repos
      Select branch
      Select file
      Select branch
      Choose version(s) to push
      • Save a new version and push
      • Choose from existing versions
      Include title and tags
      Available push count

      Upgrade

      Pull from GitHub

       
      File from GitHub
      File from HackMD

      GitHub Link Settings

      File linked

      Linked by
      File path
      Last synced branch
      Available push count

      Upgrade

      Danger Zone

      Unlink
      You will no longer receive notification when GitHub file changes after unlink.

      Syncing

      Push failed

      Push successfully