8天学会PHP之day6 数据库应用

这一章主要讲解PHP操作数据库的应用。需要具备一些数据库前置知识,至少掌握mysql和redis的crud操作。就算不懂数据库的知识也无所谓,数据库语言都非常简单,从字面意义就能明白是在做什么。

 

一、PDO

PHP连接数据库的方式有2种:

  • MySQLi extension ("i" 意为 improved)

  • PDO (PHP Data Objects)

两者的区别在于MySQLi只支持mysql,而PDO支持12种数据库。

为了方便,我们只学习PDO的使用即可。因为我们不能只会连接MySQL。这样会让我们投入的时间性价比更高。

PDO和go的go-sql-driver,Java的JDBC作用是一样的,连使用方法几乎都非常一致。做法都是创建一个连接实例,通过连接实例执行sql。

查看PDO是否受支持

PHP7之后,php自动具备了PDO,可以使用phpinfo函数查看是否开启了PDO。

利用上一章学习到的路由和控制器知识,写一个RESTfulAPI来查看php环境。

创建路由

Route::get('phpinfo', 'EnvironmentController');

创建控制器

class EnvironmentController extends Controller
{
    public function __invoke()
    {
        // 注意需要连接一个空字符串,因为phpinfo没有toString
        return phpinfo() . '';
    }
}

然后在浏览器访问http://homestead.test/api/v1/phpinfo。你应该会看到非常多的数据,可以直接搜索PDO关键字,看到如下内容就表示当前运行环境的PDO是支持的。

连接数据库

创建一个PDO实例,传入3个构造参数。第1个是数据库连接,第2个是用户名,第3个是用户密码。

function connDB($dbname = 'test')
{
    $servername = "localhost";
    $username = "homestead";
    $password = "secret";
    try {
        $conn = new PDO("mysql:host=$servername;dbname=$dbname", $username, $password);
    } catch (PDOException $e) {
        return $e->getMessage();
    }
}

创建数据库

使用创建出来的PDO实例conn来调用query方法,传入要执行的sql作为参数。

query方法返回bool值,成功为true,失败为false。

失败时还可以通过conn访问errorCode和errorInfo来获取错误信息。

$sql = "CREATE DATABASE test";
if ($conn->query($sql) == true) {
    return "数据库创建成功";
} else {
    return [
        'errorCode' => $conn->errorCode(),
        'errorInfo:' => $conn->errorInfo()
    ];
}

创建表

创建表和创建数据库的操作一样,只是执行的sql不同。

操作数据(CRUD)

插入insert、查询select、修改update、删除delete四种操作都可以使用exec方法来执行,但是这个方法不返回任何值。只能通过try/catch来捕获异常来验证是否成功。

$conn->exec($sql);

设置错误模式

设置错误模式,用于抛出异常。如果不设置,sql执行失败也不会抛出异常。

$conn->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

事务

开启事务$conn->beginTransaction();

提交事务$conn->commit();

回滚事务$conn->rollback();

开启事务后开始执行sql语句,执行完毕提交事务。开启异常捕获,如果出现异常,执行回滚操作。

预处理语句/SQL模板

预处理语句就是定义模板,预留?标记。例如:

insert into user (name, age, email) VALUES(?, ?, ?)

使用方法:

1.使用conn的prepare方法创建模板并返回一个对象stmt。其中字符串模板的填充字段用:前缀来修饰。

2.调用stmt的bindParam方法来绑定字段和值。接受2个参数,第1个参数是字段,第2个参数是值的变量名。

3.绑定后,执行stmt的方法execute来执行模板sql。

4.之后再次修改值时,直接修改变量的值,再次执行stmt的方法execute即可。

try {
            $stmt = $conn->prepare("insert into user (name, age, email, gender) VALUES(:name, :age, :email, :gender)");
​
            $name = "张三";
            $age = 134;
            $email = "@@@.@";
            $gender = "男";
​
            $stmt->bindParam(':name', $name);
            $stmt->bindParam(':age', $age);
            $stmt->bindParam(':email', $email);
            $stmt->bindParam(':gender', $gender);
​
            $stmt->execute();
​
            // 再次插入行
            $name = "李四";
            $age = 22;
            $email = "[email protected]";
            $stmt->execute();
            return "插入成功";
        } catch (PDOException $e) {
            return $e->getMessage();
        }

 

二、使用框架操作Mysql

这部分其实没什么可讲的东西,框架做的事,无非就是在PDO或mysqli基础上进行封装,简化我们的操作而已。如果你是一直读过来的同学,应该发现了一个问题。从学框架应用开始,讲的内容越来越含糊了。其实,这些框架的API我并不是死记硬背的。大多数情况下,我都是先读一遍官方文档,然后针对常用的API写一些Demo测试。之后就是实战了。在实战中,如果发现有些需求处理的不够优雅,就会在去官方文档和社区寻找对应的更优解决方案。对我来讲,学习框架的各种API是一件吃力不讨好的事。

Laravel 能使用原生 SQL、流畅的查询构造器Eloquent ORM 在各种数据库后台与数据库进行非常简单的交互。

运行原生查询

使用DBuse Illuminate\Support\Facades\DB;.

执行查询DB::select('select * from users where active = ?', [1]);,返回值始终是数组。

执行插入DB::insert('insert into users (id, name) values (?, ?)', [1, 'Dayle']);

执行更新$affected = DB::update('update users set votes = 100 where name = ?', ['John']);,返回更新的行数。

执行删除$deleted = DB::delete('delete from users');,返回删除的行数。

运行普通语句DB::statement('drop table users');无返回值。

事务

使用db的transaction方法,参数是个函数,在里面执行sql。

DB::transaction(function () {
    DB::table('users')->update(['votes' => 1]);
​   // 这里写sql
    DB::table('posts')->delete();
});

看到这里,你应该发现,我们用框架做的事,和前面学的PDO做的事基本上是一样的,区别只是写法不同。

那为什么还要再学一遍呢?因为我们要使用框架,框架帮助我们处理了很多异常问题和边界问题,简化我们的操作。

这里我不想再讲下去了,因为我没必要把官方文档的API挨个演示一遍。至于更高级的操作,如构造器和eloquent ORM,如果感兴趣,建议你去中文社区进行学习这一部分的内容。https://learnku.com/docs/laravel/5.8/database/3925

 

三、使用框架操作Redis

其实在我们目前的项目中,关于redis的使用很有限。这里不说redis集群的使用方式,只说下redis的单机应用。

这里假设你已经在本机安装好redis。

关于redis的可视化管理工具,推荐 Redis Desktop Manager

首先在项目中安装predis包

composer require predis/predis

安装predis的过程中可能会遇到一个异常信息:

the requested PHP extension fileinfo is missing from your system

意思是没有开启fileinfo扩展,需要在你PHP环境的php.ini文件中修改一行配置,如果没有这行配置那么就添加上。

extension=php_fileinfo.dll

如果你的redis默认配置没有修改,那么项目中的配置也都不需要修改。

如果你的redis不是本机的,或者修改了端口等,需要在项目中的config/database.php和.env文件中分别修改配置。

database.php相关配置

'redis' => [

       'client' => env('REDIS_CLIENT', 'predis'),

       'options' => [
           'cluster' => env('REDIS_CLUSTER', 'predis'),
           'prefix' => Str::slug(env('APP_NAME', 'laravel'), '_').'_database_',
      ],

       'default' => [
           'host' => env('REDIS_HOST', '127.0.0.1'),
           'password' => env('REDIS_PASSWORD', null),
           'port' => env('REDIS_PORT', 6379),
           'database' => env('REDIS_DB', 0),
      ],

       'cache' => [
           'host' => env('REDIS_HOST', '127.0.0.1'),
           'password' => env('REDIS_PASSWORD', null),
           'port' => env('REDIS_PORT', 6379),
           'database' => env('REDIS_CACHE_DB', 1),
      ],

  ],

.evn相关配置。

REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379

predis的相关操作还是非常简单的,基本上都和redis的原生操作一致。

存值Redis::set('key', 'value');

取值Redis::get('key');

检测某值是否存在Redis::exists('user_key')

设置过期时间Redis::setex('str', 10, 'bar');

删除Redis::del('key');

redis的操作多达十几种,这里就不再继续罗列,更多操作可查阅:https://packagist.org/packages/predis/predis

 

四、总结

这一章学习了在原生PHP和框架中操作mysql和redis的方式

猜你喜欢

转载自www.cnblogs.com/luzhenqian/p/11437616.html