Laravel 数据库实例教程 —— 使用DB门面操作数据库

Laravel支持多种数据库,包括MySQL、Postgres、SQLite和SQL Server,在Laravel中连接数据库和查询数据库都非常简单,我们可以使用多种方式与数据库进行交互,包括原生SQL语句、查询构建器以及Eloquent ORM。本节我们先演示如何使用原生SQL在Laravel应用中对数据库进行增删改查

1、连接数据库

Laravel中数据库配置文件为config/database.php,打开该文件,默认内容如下:

<?php

return [
    //默认返回结果集为PHP对象实例
    'fetch' => PDO::FETCH_CLASS,
    //默认数据库连接为mysql,可以在.env文件中修改DB_CONNECTION的值
    'default' => env('DB_CONNECTION', 'mysql'),

    'connections' => [
        //sqlite数据库相关配置
        'sqlite' => [
            'driver' => 'sqlite',
            'database' => storage_path('database.sqlite'),
            'prefix' => '',
        ],
        //mysql数据库相关配置
        'mysql' => [
            'driver' => 'mysql',
            'host' => env('DB_HOST', 'localhost'),
            'database' => env('DB_DATABASE', 'forge'),
            'username' => env('DB_USERNAME', 'forge'),
            'password' => env('DB_PASSWORD', ''),
            'charset' => 'utf8',
            'collation' => 'utf8_unicode_ci',
            'prefix' => '',
            'strict' => false,
        ],
        //Postgres数据库相关配置
        'pgsql' => [
            'driver' => 'pgsql',
            'host' => env('DB_HOST', 'localhost'),
            'database' => env('DB_DATABASE', 'forge'),
            'username' => env('DB_USERNAME', 'forge'),
            'password' => env('DB_PASSWORD', ''),
            'charset' => 'utf8',
            'prefix' => '',
            'schema' => 'public',
        ],
        //SQL Server数据库相关配置
        'sqlsrv' => [
            'driver' => 'sqlsrv',
            'host' => env('DB_HOST', 'localhost'),
            'database' => env('DB_DATABASE', 'forge'),
            'username' => env('DB_USERNAME', 'forge'),
            'password' => env('DB_PASSWORD', ''),
            'charset' => 'utf8',
            'prefix' => '',
        ],

    ],
    //迁移表名称
    'migrations' => 'migrations',
    //Redis数据库相关配置
    'redis' => [

        'cluster' => false,

        'default' => [
            'host' => '127.0.0.1',
            'port' => 6379,
            'database' => 0,
        ],
 
    ],

];

如果要修改数据库配置信息,去修改.env对应值即可。我们实例教程使用的Homestead开发环境默认配置,不做修改。如果你没有使用Homestead,则需要根据本地配置修改相应配置值。

我们在讲Windows上安装Homestead的时候,已经演示过数据库连接测试,以及如何在本地使用Navicat连接Homestead的数据库,这里不再赘述,下面直接进入如何使用数据库进行增删改查。

2、数据库初始化

我们在项目根目录使用Artisan命令运行Laravel自带的迁移生成users表和password_reset表:

php artisan migrate

对应在数据库中生成三张表:

运行迁移生成users表

3、使用DB门面进行增删改查

3.1 插入数据

我们使用DB门面执行原生SQL语句,插入操作使用DB门面的insert方法,代码如下:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

use App\Http\Requests;
use App\Http\Controllers\Controller;

use DB;

class TestController extends Controller
{

/**
* Display a listing of the resource.
*
* @return Response
*/
public function index()
{

    DB::insert('insert into users (id, name, email, password) values (?, ?, ? , ? )',
        [1, 'Laravel','laravel@test.com','123']);
    DB::insert('insert into users (id, name, email, password) values (?, ?, ?, ? )',
        [2, 'Academy','academy@test.com','123']);

    }
}

在浏览器中输入http://laravel.app:8000/test,执行成功后在数据库中插入两条记录:

db-insert-data

3.2 查询语句

查询操作使用DB门面的select方法,代码如下:

$user = DB::select('select * from users where id = ?', [1]);
dd($user);

在浏览器地址栏输入http://laravel.app:8000/test,输出内容如下:

db-select-data

可以看到select查询返回的结果是数组。而数组中的每一个元素都是PHP对象。

我们还 可以看到在执行查询的时候使用了参数绑定,以避免SQL注入。除此之外还可以使用命名绑定:

$user = DB::select('select * from users where id = :id', [':id'=>1]);

效果一样。

3.3 更新语句

更新表记录可以使用DB门面的update方法,该方法返回受影响的行数:

$affected = DB::update('update users set name="LaravelAcademy" where name = ?', ['Academy']);
echo $affected;

打印结果为1,如果没有更新任何记录则返回0。

3.4 删除语句

删除表记录使用DB门面的delete方法,和update类似,该方法返回被删除的行数:

$deleted = DB::delete('delete from users');
echo $deleted;

打印结果为2,表数据都被我们删除了。

3.5 通用语句

除了上述这些DML(insert/update/delete)和DQL(select)语句,SQL语句还包括DCL(create/drop等)和DDL(grant等),要运行后者,我们可以调用DB门面的statement方法:

DB::statement('drop table users');

执行完该语句后,数据表users会被删除。

4、监听查询事件

除此之外,我们还可以通过DB门面的listen方法监听查询事件,比如我们在记录日志和调试的时候这会给我们确定问题提供便利,可以在服务提供者的boot方法中注册该监听器,例如我们在AppServiceProviderboot方法中定义监听器如下:

/**
* 启动所有应用服务
*
* @return void
*/
public function boot()
{
    DB::listen(function($sql, $bindings, $time) {
        echo 'SQL语句执行:'.$sql.',参数:'.json_encode($bindings).',耗时:'.$time.'ms';
    });
}

这样我们运行如下SQL语句:

DB::insert('insert into users (id, name, email, password) values (?, ?, ? , ? )',
    [3, 'LaravelAcademy','laravel-academy@test.com','123']);

则浏览器会输出如下内容:

SQL语句执行:insert into users (id, name, email, password) values (?, ?, ? , ? ),参数:[3,"LaravelAcademy","laravel-academy@test.com","123"],耗时:1.26ms

5、数据库事务

很多时候,我们需要执行一连串操作,而其中任何一个操作出错则整个流程失败,需要回退重来,这个时候我们就要用到数据库事务。

DB门面提供两种方式支持数据库事务,一种是调用transaction方法然后传入闭包作为参数,我们将需要进行事务操作的逻辑放到闭包函数内:

DB::transaction(function () {
    DB::table('users')->update(['id' => 1]);
    DB::table('posts')->delete();
});

另一种是 beginTransactionrollBackcommit三个方法一起使用从而构建一个完整的事务操作:

DB::beginTransaction();
if($somethingIsFailed){
    DB::rollback();
    return false;
}
DB::commit();

此外,使用DB门面提供的事务还支持查询构建器和Eloquent ORM数据库操作。

学院君 has written 682 articles

资深PHP工程师,Laravel学院院长

18 thoughts on “Laravel 数据库实例教程 —— 使用DB门面操作数据库

  1. yyjia says:

    DB::listen(function($sql, $bindings, $time) {
    echo ‘SQL语句执行:’.$sql.’,参数:’.json_encode($bindings).’,耗时:’.$time.’ms’;
    });

    提示缺少一个参数, 学院君,该如何改?

    1. talen says:

      5.4版是改成$query
      DB::listen(function ($query) {
      dd(‘SQL语句执行:’.$query->sql.’,参数:’.json_encode($query->bindings).’,耗时:’.$query->time.’ms’);
      });

  2. 生來彷徨 says:

    DB::listen(function($sql) {// echo ‘SQL语句执行:’.$sql.’,参数:’.json_encode($bindings).’,耗时:’.$time.’ms’;// echo ‘SQL语句执行:’.$sql->sql.’,参数:’.$sql->bindings.’,耗时:’.$sql->time.’ms’; var_dump($sql->sql); var_dump($sql->bindings); var_dump($sql->time); });

      1. Lock says:

        DB::listen(function($params){ //$params->sql;});$params instanceof IlluminateDatabaseEventsQueryExecuted; //true +sql: “select * from users where id = ?” +bindings: array +time: 0.41 +connection: MySqlConnection +connectionName: “mysql”

  3. sfq_a says:

    AppServiceProvider的boot方法中定义监听器。按照你的方法数据库可以改变,浏览器没有输出结果。还有视图共享数据时,也是不能共享,不知道原因。

      1. 矮子杨 says:

        public function up()
        {
        Schema::create(‘goods’,function(Blueprint $table){
        $table->engine = ‘InnoDB’;
        $table->increments(‘id’)->comment(‘goods表主键’);
        $table->string(‘name’,20)->comment(‘物品名称’)->nullable()->unique();
        $table->integer(‘cat_id’)->comment(‘类别id’)->nullable();
        $table->float(‘shop_price’)->comment(‘商店售价’)->nullable()->default(0);
        $table->float(‘market_price’)->comment(‘批发价格’)->nullable()->default(0);
        $table->integer(‘click_count’)->comment(‘点击次数’);
        $table->integer(‘number’)->comment(‘商品数量’);
        $table->rememberToken();
        $table->timestamps();
        });
        }

        1. 矮子杨 says:

          +——–+—————–+
          | cat_id | avg(shop_price) |
          +——–+—————–+
          | 2 | 823.330000 |
          | 3 | 1680.307692 |
          | 4 | 2297.000000 |
          | 5 | 3700.000000 |
          | 7 | 1702.500000 |
          | 8 | 75.333333 |
          | 11 | 31.000000 |
          | 13 | 33.500000 |
          | 14 | 67.500000 |
          | 15 | 70.000000 |
          +——–+—————–+
          这是原生语句输出的结构 怎么能在laravel里得到这个结果呢

      2. 矮子杨 says:

        还有一个问题问一下 原生语句select cat_id,avg(shop_price) from goods group by cat_id;(这句话的意思是查找各类别的商品的平均值)
        在laravel怎么写呢,我想直接得到数组,cat_id 和 shop_price的平均值,真心不会写

发表评论

标记为*的字段是必填项(邮箱地址不会被公开)

你可以使用这些HTML 标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>