F3-fatfree小型php框架教程(六)數據庫篇

既然是講數據庫的,那首先天然是鏈接數據庫了。php

這裏舉兩個例子,mysql數據庫:mysql

$db=new DB\SQL(
    'mysql:host=localhost;port=3306;dbname=mysqldb',
    'admin',
    'p455w0rD');

sqlite數據庫: web

$db=new DB\SQL('sqlite:/absolute/path/to/your/database.sqlite'));



數據庫查詢sql

很簡單的,fatfree的數據庫是不用配置的,不少東西都是內置的,當你須要改再去改就行,咱們首先學習查詢,就一步:數據庫

$f3->set('result',$db->exec('SELECT brandName FROM wherever'));

這樣就好了,select 和 from是數據庫語言,咱們這就把數據庫中符合條件的變量放到了result數組裏面了。 數組

而後咱們用以前學的repeat調用試試看:安全

<repeat group="{{ @result }}" value="{{ @item }}">
    <span>{{ @item.brandName  }}</span></repeat>

最後再echo一下就能夠了。注意一下,這裏實際上是個二維數組,結構大概是result ->  brandName  -> value。能夠用以前學過的嵌入repeat,可是這裏既然brandName只有一個,那麼就用 .  符號就能夠解決問題了。 app


深造:框架

若是要執行一組命令怎麼辦?兩種方法:函數

$db->exec(
    array(
        'DELETE FROM diet WHERE food="cola"',
        'INSERT INTO diet (food) VALUES ("carrot")',
        'SELECT * FROM diet'
    ));

還有

$db->begin();$db->exec('DELETE FROM diet WHERE food="cola"');$db->exec('INSERT INTO diet (food) VALUES ("carrot")');$db->exec('SELECT * FROM diet');$db->commit();

固然,若是指令出錯的話,調用就會回捲,咱們能夠經過調用:

echo $db->log();

來查看指令的調用情況。


數據庫安全:

爲了方式用戶惡意修改數據庫,咱們應該用下面這個方法代替上面的代碼:

$db->exec(
    array(
        'DELETE FROM diet WHERE food=:name',
        'INSERT INTO diet (food) VALUES (?)',
        'SELECT * FROM diet'
    ),
    array(
        array(':name'=>'cola'),
        array(1=>'carrot'),
        NULL
    ));


數據庫的增刪查改:

首先數據庫文件的大概形式是這樣的:

CREATE TABLE users (
    userID VARCHAR(30),
    password VARCHAR(30),
    visits INT,
    PRIMARY KEY(userID)
);

好,首先咱們一步一步來,鏈接數據庫

$db=new DB\SQL(
    'mysql:host=localhost;port=3306;dbname=mysqldb',
    'admin',
    'wh4t3v3r');

而後

$user=new DB\SQL\Mapper($db,'users');$user->load(array('userID=?','tarzan'));

上面的這個$user是咱們創建的一個‘users’屬性的結構對象(也就是上面那個數據庫文件的形式),裏面是空的。

第二行就是把userID = tarzan 的給讀出來的,附屬的信息都一塊兒讀出來了。


數據庫的插入修改

繼續上面的那個例子,若是我要修改這個類裏面的訪問量visits怎麼辦呢?

$user->visits++;$user->save();

這樣就能夠了。

若是要增長一個新的記錄呢:

$user=new DB\SQL\Mapper($db,'users');// or $user=new DB\Mongo\Mapper($db,'users');// or $user=new DB\Jig\Mapper($db,'users');$user->userID='jane';$user->password=md5('secret');$user->visits=0;$user->save();

有沒有發現咱們一直都在用save函數,由於若是不save的話這裏修改的值就會在腳本運行結束的時候恢復回去的。

fatfree框架是很自動的,若是這裏增長的userID是已經存在的用戶,這裏的增長就會自動變成修改操做,畢竟咱們文件裏最重要的那句

PRIMARY KEY(userID)

不是白白加上去的,這句話既是監控key值的做用(知道究竟是插入仍是修改操做)又是映射變量的做用。

固然,還有一點要注意的,若是你要連續修改(插入)須要reset一下:

$user->reset();$user->userID='cheetah';$user->password=md5('unknown');$user->save();

原理說一下,由於若是是進行了操做的話,映射類裏面就會包含這個最新的操做,咱們這個save就是把映射類裏面的操做commit到數據庫裏面,可是若是你要繼續下一個操做就要從新clear一下映射類,因此咱們須要reset一下。養成良好習慣就是每當操做前reset一下,操做後save一下。


刪除用戶

$user=new DB\SQL\Mapper($db,'users');$user->load(array('userID=? AND password=?','cheetah','ch1mp'));$user->erase();

很簡單,首先load該用戶,而後erase就好了。用?是爲了保護數據庫不被看到。


POST變量與數據庫傳遞

POST跟GET同樣是全局變量,都是被set過的,能夠近似地看做一個tmp,不過POST是不對用戶公開的,因此經常使用語數據庫。

從POST讀取到新變量user裏面:

$f3->set('user',new DB\SQL\Mapper($db,'users'));$f3->get('user')->copyFrom('POST');$f3->get('user')->save();

把user裏面的東西給POST:

$f3->set('user',new DB\SQL\Mapper($db,'users'));$f3->get('user')->load(array('userID=?','jane'));$f3->get('user')->copyTo('POST');

這裏就是讀取了jane的相關信息給了post。別忘了在php裏面調用post是$_post,在fatfree裏面就只要@POST就行。

繼續,這裏讀取了jane的相關信息後,能夠經過@POST.userID來調用信息。

例子:

<input type="text" name="userID" value="{{ @POST.userID }}">

這裏的input類型是text文本輸入,輸入的信息存儲到userID變量裏,然後面那個value則是會在空格里顯示的默認數據,就像咱們登錄qq那樣記錄上一次登錄的用戶名,用的就是上面這種方法。


條件篩選

$user=new DB\SQL\Mapper($db,'users');$user->load('visits>3');// Rewritten as a parameterized query$user->load(array('visits>?',3));// For MongoDB users:// $user=new DB\Mongo\Mapper($db,'users');// $user->load(array('visits'=>array('$gt'=>3)));// If you prefer Jig:// $user=new DB\Jig\Mapper($db,'users');// $user->load('@visits>?',3);// Display the userID of the first record that matches the criteriaecho $user->userID;// Go to the next record that matches the same criteria$user->skip(); // Same as $user->skip(1);// Back to the first record$user->skip(-1);// Move three records forward$user->skip(3);

例子就說明得很清楚了,首先篩選出visits > 3 的user 而後再skip,其實skip就至關因而next,你要跳幾步就skip幾個,若是要回跳就skip(-1)。

能夠用dry()函數來檢驗是否越界,若是在第一個skip(-1)或者在最後一個next,那麼dry()都會返回一個true來表示已經越界了。


固然load函數還有一個特別的讀取形式,相似於重載過同樣:

$user->load(
    array('visits>?',3),
    array(
        'order'=>'userID DESC'
        'offset'=>5,
        'limit'=>3
    ));

這句話的意思就至關於數據庫語言裏的:

SELECT * FROM users
WHERE visits>3
ORDER BY userID DESC
LIMIT 3 OFFSET 5;

還有個更簡單的寫法:

$page=$user->paginate(2,5,array('visits>?',3));

那個2跟5就是從第2個開始數5個


虛領域

首先給個表單:

CREATE TABLE products (
    productID VARCHAR(30),
    description VARCHAR(255),
    supplierID VARCHAR(30),
    unitprice DECIMAL(10,2),
    quantity INT,
    PRIMARY KEY(productID)
);

所謂的虛領域就是本身設定規則,舉個例子:

$item=new DB\SQL\Mapper($db,'products');$item->totalprice='unitprice*quantity';$item->load(array('productID=:pid',':pid'=>'apple'));echo $item->totalprice;

這裏設定的totalprice就是虛領域,默認等於unitprice * quantity 這個虛領域設定了以後其實就至關於裏面的一個元素了,能夠直接經過 -》 來調用。接着讀取productID等於apple的元素而後返回這個虛領域也就是他們兩個的乘積。

固然了,除了讀取單個元素以外虛領域還能夠在宏觀上一些操做,例如取最大的數量:

$item->mostNumber='MAX(quantity)';$item->load();echo $item->mostNumber;

注意這裏的load沒有涉及任何變量,表示直接在全局裏面load,而後就能夠輸出最大數字的元素了。

固然了,有時候你沒法用一些現有的函數來表達你想要的東西,咱們就能夠經過數據庫的語言來本身設立篩選條件:

$item->supplierName=
    'SELECT name FROM suppliers '.
    'WHERE products.supplierID=suppliers.supplierID';$item->load();echo $item->supplierName;

這裏本身設定了篩選條件,就是把同名的找出來(通常若是有多個就默認第一個)


數據庫查找

數據庫查找要用到find函數:

$frequentUsers=$user->find(array('visits>?',3),array('order'=>'userID'));

要注意,load跟find是徹底不同的,看名字就知道用途了,load是找出全部符合要求的而後我要對它進行操做或者運算,而find函數只要find到了就完事了,就只要看結果,不操做。並且還有一點不一樣,find由於工做是查找,因此會把找到的東西存起來,存到一個定義好的數組裏面(後面會說)。也就是說哪些用於操做的skip,虛領域什麼的都不能經過find實現。

咱們來看看find函數的定義:

find(
    $criteria,
    array(
        'group'=>'foo',
        'order'=>'foo,bar',
        'limit'=>5,
        'offset'=>0
    ));

第一個是基本條件,做爲第一步篩選,而後下面的都是額外篩選的條件,放在一個數組裏面。

$place=new DB\SQL\Mapper($db,'places');$list=$place->find('state="New York"');foreach ($list as $obj)
    echo $obj->city.', '.$obj->country;

這裏假設定義好了一個城市的表,而後這裏吧state = NEW York 的全部符合條件的映射都存到list數組裏面了,而後下面經過foreach來調用查看結果。

接着上面的定義,若是咱們不要篩選條件,要整個表搬走,能夠用上cast()

$array=$place->cast();echo $array['city'].', '.$array['country'];

還有一個特別好用的函數count:

if (!$user->count(array('visits>?',10)))
    echo 'We need a better ad campaign!';

這裏是若是連一個訪問量大於10的用戶都沒有,那咱們就確實須要投廣告了。。。

還有能夠經過select來作一些比find更復雜的篩選,看看select的定義:

select(
    'foo, bar, MIN(baz) AS lowest',
    'foo > ?',
    array(
        'group'=>'foo, bar',
        'order'=>'baz ASC',
        'limit'=>5,
        'offset'=>3
    ));
相關文章
相關標籤/搜索