PHP 與 MySQL 的連線
(這段程式碼太好用了所以先置頂)
- 可以以兩個 php 檔來處理連線工作
- DB_config.php : 放 server & user & db 資料
- DB_conn.php : 連線、取資料等初始化動作
DB_config.php
<?php
$servername = 'localhost';
$user = 'root';
$password = '';
$dbname = 'jobs';
?>
DB_conn.php
<?php
require_once('./DB_config.php');
class Db {
public function __construct($servername, $user, $password, $dbname) {
$this->server = $servername;
$this->user = $user;
$this->pass = $password;
$this->db = $dbname;
$this->init();
}
private function init() {
$this->conn = mysqli_connect($this->server, $this->user, $this->pass, $this->db);
if ($this->conn->connect_error) {
die('Failed: ' . $this->conn->connect_error);
}
mysqli_query($this->conn, "SET NAMES utf8");
mysqli_query($this->conn, 'SET time_zone = "+8:00"');
}
public function query($str) {
$this->result = mysqli_query($this->conn, $str);
}
// 拿到所有資料
public function fetch_array() {
while ($row = mysqli_fetch_array($this->result, MYSQLI_ASSOC)) {
printf("ID: %s title: %s", $row["id"], $row["title"] . " <br>");
}
}
}
$db = new Db($servername, $user, $password, $dbname);
?>
使用資料時,new 出一個 DB Class
<?php
require_once('./DB_config.php');
require_once('./DB_conn.php');
$sql = "SELECT * FROM jobs";
$db->query($sql);
echo $db->fetch_array(); // 印出所有 id & title
?>
(以下 正片 開始)
物件導向概念
- 物件導向應用在軟體設計的發展,著重在物件的 分解 與 相互作用
- 一個完整的物件會包含:
- 屬性(Attribult):物件的
靜態
外觀描述,例如 class 中的 member data - 方法(method):物件的
動態
回應方式,例如 class 中的 member method - 事件(event):物件針對
外部事件
做出的反應
- 屬性(Attribult):物件的
命名規範
- 類別和介面:第一個字母為大寫,ex. Student, StudentName
- 成員變數和成員方法:駝峰式命名,ex. setColor
- 套件:全部小寫,ex. java.io java.lang.math
- 常數:全部大寫並用 _ 連接,ex. PI MAX_VALUE
類別 class
- 類別是用來具體描述物件狀態與行為的資料型態
- 「類別」與「物件」之間的關係就像「設計圖」與「建築物」
- 「類別」只是個架構
- 「物件」是實際存在的實體
- 把「類別」實際製作後的成品就是「物件」,這個動作就叫做「實作」
實作:將設計圖變成建築物
- 物件實作宣告方式:
<物件名稱> = new <類別名稱>
class 命名時開頭字母要大寫
底下範例可以看到,
- name 是物件的「實體變數」
- setName, getName 是物件的 「方法」
this 指的是當下的這個 「實體物件」instance
- 如果是 let dog1 = new Dog() ,this 指的就是 dog1
- 如果是 let dog2 = new Dog() ,this 指的就是 dog2
function 在物件外面是 function,在物件裡面是 method
JavaScript
class Dog {
setName(name) {
this.name = name;
};
getName() {
return this.name;
}
}
let dog1 = new Dog();
dog1.setName("Halu");
console.log(dog1.getName()); // Halu
PHP
<?php
class Dog {
public function setName($name) {
$this->name = $name;
}
public funtion getName() {
return $this->name;
}
}
$dog1 = new Dog()
$dog1.setName("Halu");
echo $dog1.getName();
?>
存取層級 & 修飾字
- 存取層級,設定誰可以使用此內容
- public:代表所有的類別都可以使用
- private:代表只有此類別本身才能使用
- protected:代表只有該類別的衍生類別或在相同套件裡的類別才能用
封裝 Encapsulation
- 意思是說把細節藏起來,所以對外圍可以使用的接口,會變得非常單純。所以是說把常用的方法打開,但方法底層是怎麼實作的,使用者不需要關心。
<?
Class Dog {
public function hello() {
echo $this->getHelloSentence(); // => 對外接口
}
private function getHelloSentence() { // => 藏起來的細節
return 'hello, I am a dog.';
}
}
$dog = new Dog();
$dog->hello();
?>
getter & setter
- 用於設定及取得「實體變數」
- 可於存取的時候設置條件,來確保資料資料在不如預期的時候就把它擋住、不能存取。
<?php
Class Dog {
private $name = 'default';
public function hello() {
echo $this->getHelloSentence();
}
private function getHelloSentence() {
return 'hello, I am '. $this->name . '<br>';
}
// setter
public function setName($name) {
if ($name === 'Fuck') return // => 如果是髒話就不能設置
$this->name = $name;
}
// getter
public function getName() {
return $this->name;
}
}
?>
Constructor 建構子
- 除了利用 setter 設定「實體變數」,我們可以利用 Constructor,在一開始 new 一個新的物件的時候直接設定變數
- 也可以利用 Constructor,建立 init() 初始化設定。
JavaScript
class Dog {
constructor(id, name, age) {
this.id = id;
this.name = name;
this.age = age;
}
}
let dog1 = new Dog(1, "Halu", 3)
// 如此一來不用一個一個設定, dog1.setName("Halu"); dog1.setId(1); dog1.setAge(3);
PHP
<?php
class Dog {
public function __construct($id, $name, $age) {
$this->id = $id;
$this->name = $name;
$this->age = $age;
$this->init();
}
private function init() {
echo $this->say();
}
private function say() {
return $this->id . $this->name . "<br>";
}
public function speak($str) {
echo $str;
}
}
$go = new Test(1, "Halu", 3); // 1Halu
$go->speak("what") // what
?>
mysqli_fetch_array 存取欄位陣列
- MYSQLI_ASSOC 用欄位名稱選擇( $row['id'], $row['title'] )
- MYSQL_NUM 用陣列位置選擇 ( $row[0], $row[1] )
- 如果沒有輸入選擇方式的話,預設是選擇 MYSQL_BOTH
- 兩者皆可用( $row[0], $row['id'] )
繼承 Inheritance
- extends 繼承自另一個 Class
某一個 class 如果跟新的 class 很像,可以用 extends 去取得父物件的屬性。
super 改變父 Class 的方法
可以基於父 Class 的方法做一些改變與微調。
其他程式語言應該都是用 super 這個關鍵字,但在 PHP 是用 parent::
<method>
語法
JavaScript
Class Calculator {
constructor() {
this.text = '';
}
input(str) {
this.text = str;
}
getResult() {
return eval(this.text);
}
}
Class chineseCalculator extends Calculator {
input(str) {
if (str === '三') {
super.input(3); // => super 語法
} else {
super.input(str);
}
}
}
PHP
<?php
Class Animal {
private $name = 'default';
// 初始化
public function __construct($name) {
$this->name = $name;
}
public function hello() {
echo $this->getHelloSentence();
}
private function getHelloSentence() {
return 'hello, I am '. $this->name . '<br>';
}
}
Class Dog extends Animal { // => 繼承
public function run() {
echo $this->name . 'is running';
}
public function sayYoAndHello() {
echo 'Yo';
parent::hello(); // => 執行 Animal 的 hello 函式
}
// public function hello() { // => overwrite
// ...
// }
}
$dog1 = new Dog('Leo');
$dog1->hello(); // => hello, I am Leo
$dog2 = new Dog('Amy');
$dog2->hello(); // => hello, I am Amy
?>
Static 靜態方法
- 上面說過在 class 中的 function 叫做 method
- 有些 class 中的 function 是要給「實體物件」用的
- 像是:
public function setName($name)
是要給外面存取的 - 利用「實體物件」來呼叫:
$dog1->setName("Halu")
- 像是:
- 有些 class 中的 function 是只有 class 自己要用的
- 像是:
private static function caculate()
- 要利用 class 自己來呼叫:
Dog::caculate()
- 像是:
- static 這個方法不一定只能使用在 function
- 也可以利用相同的概念,設定一個只給 class 使用的變數
- 像是:
static $number = 1
- 也是讓 class 自己來呼叫:
Dog::$number
- 由於 static 的方法或變數,是給 class 自己用的,所以不論這個 class 被 new 多少次,這個 static 的方法或變數都只會有一個
- 我們會說
Dog::$number
,其中的 $number 只有一個
- 我們會說
- 但是非 static 的方法會變數,每一次被 new 成新的「物件」,就會產生對應的新方法及變數
$dog1->setName("Halu")
及$dog2->setName("Alu")
是兩個不同 instance 底下的方法,所以我們可以說有兩個 setName()
實作技巧
- 要實作一個 class 你可以先思考,你要如何讓別人來使用這個 class
- 舉例:要實作一個 XMLHttpRequest 的 class
class XMLHttpRequest {
// 我先什麼都不寫
}
// 開始思考希望別人能怎麼用這個 class
const request = new XMLHttpRequest();
request.open(method, url, true) // 讓別人可以傳 method, url, 設定同步異步
request.onload = () => { } // 讓別人可以設訂 callback function
request.onerror = () => { } // 讓別人可以除錯
request.send() // 讓別人可以發送 request
//如此一來,這些 method 就要設定成 public,成為可以對外使用的接口
//我再來設計 class 的內容