首页 > 代码库 > F3-fatfree小型php框架教程(六)数据库篇

F3-fatfree小型php框架教程(六)数据库篇

既然是讲数据库的,那首先自然是连接数据库了。

这里举两个例子,mysql数据库:

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

sqlite数据库:

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



数据库查询

很简单的,fatfree的数据库是不用配置的,很多东西都是内置的,当你需要改再去改就行,我们首先学习查询,就一步:

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

这样就行了,select 和 from是数据库语言,我们这就把数据库中符合条件的变量放到了result数组里面了。

然后我们用之前学的repeat调用试试看:

<repeat group="{{ @result }}" value=http://www.mamicode.com/"{{ @item }}">> 

最后再echo一下就可以了。注意一下,这里其实是个二维数组,结构大概是result ->  brandName  -> value。可以用之前学过的嵌入repeat,但是这里既然brandName只有一个,那么就用 .  符号就可以解决问题了。


深造:

如果要执行一组命令怎么办?两种方法:

$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=http://www.mamicode.com/"{{ @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
    ));


F3-fatfree小型php框架教程(六)数据库篇