7. 從數據庫獲取數據- 從零開始學Laravel

從零開始學Laravel教程目錄php

路由,控制器,視圖咱們都學了一點了,從這裏開始,咱們先看下如何用migration建立數據表,而後經過查詢構建器(query builder)和Elequent去獲取數據。html

咱們以獲取全部的博客的帖子爲例,先寫一條路由:mysql

Route::get('posts', 'PostsController@index');

進入終端生成PostsController控制器類laravel

➜ php artisan make:controller PostsController
Controller created successfully.

控制器中PostsController寫上index方法redis

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Http\Requests;

class PostsController extends Controller
{
    public function index()
    {
        return view('posts.index');
    }
}

resources/views/下 創建posts/index.balde.php的視圖文件,讓其繼承layout.balde.php.sql

@extends('layout')

@section('content')
    <h1>全部的帖子</h1>
@stop

開啓php artisan serve服務, 瀏覽器輸入http://localhost:8000/posts 測試咱們從路由->控制器->視圖 這個流程是能跑通的了。數據庫

下面咱們先進入到config/database.php文件中,config文件夾內的文件都是一些配置文件,像數據庫,緩存,郵件,隊列等的配置都在這裏,或者你本身之後新建的配置文件也能夠放在這個文件夾內。 數組

咱們打開database.php,該文件就是返回一個數組:瀏覽器

<?php

return [
    'fetch' => PDO::FETCH_CLASS,

    'default' => env('DB_CONNECTION', 'mysql'),

    'connections' => [

        'sqlite' => [
            'driver' => 'sqlite',
            'database' => env('DB_DATABASE', database_path('database.sqlite')),
            'prefix' => '',
        ],

        'mysql' => [
            'driver' => 'mysql',
            'host' => env('DB_HOST', 'localhost'),
            'port' => env('DB_PORT', '3306'),
            'database' => env('DB_DATABASE', 'forge'),
            'username' => env('DB_USERNAME', 'forge'),
            'password' => env('DB_PASSWORD', ''),
            'charset' => 'utf8',
            'collation' => 'utf8_unicode_ci',
            'prefix' => '',
            'strict' => false,
            'engine' => null,
        ],

        'pgsql' => [
            'driver' => 'pgsql',
            'host' => env('DB_HOST', 'localhost'),
            'port' => env('DB_PORT', '5432'),
            'database' => env('DB_DATABASE', 'forge'),
            'username' => env('DB_USERNAME', 'forge'),
            'password' => env('DB_PASSWORD', ''),
            'charset' => 'utf8',
            'prefix' => '',
            'schema' => 'public',
        ],

    ],

    'migrations' => 'migrations',

    'redis' => [

        'cluster' => false,

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

    ],

];

laravel默認支持了以上幾種數據庫,你但願使用哪一種數據庫,在'default' => env('DB_CONNECTION', 'mysql'),
將env()的函數的第二個參數設置成爲你要使用的,好比說咱們如今用sqlite緩存

'default' => env('DB_CONNECTION', 'sqlite'),

上面的sqlite對應的配置文件是:

'sqlite' => [
    'driver' => 'sqlite',
    'database' => env('DB_DATABASE', database_path('database.sqlite')),
    'prefix' => '',
],

上面的database_path()是laravel自帶的一個幫助函數,意思是獲取應用數據庫目錄的完整路徑,如個人是:"/usr/local/var/www/Laravel52/database", ok, 咱們在database目錄下創建database.sqlite文件

傳統方法上,咱們可能會用Sequel Pro寫出原生的sql語句執行,或者使用mysql workbench創建ER圖模型,而後導入到數據庫中,這些方法均可以用,可是在多人開發的時候,維護本地的數據庫以及當添加了新表或者修改了表字段,變的很麻煩,好比你修改了表的字段,這時候你得告訴你的同事,我修改了哪些字段,而Laravel自帶的migration很好的解決了這個問題,migration能夠當作是數據庫的版本控制,你不管是添加了表,仍是修改了字段,你的同事只須要執行php artisan migrate就能夠保證他的數據庫和你同樣了,這對於數據庫的線上部署也很是的方便。這個東西剛開始用的時候會有點不習慣,可是若是你一直堅持用下去,你會發現這的確是個好東西,千萬不要放棄它。

咱們打開database/migrations目錄,裏面已經存在了兩個migration文件,一個是用來建立用戶users表的,另外一個是用來建立密碼重置password_resets表的。咱們打開2014_10_12_000000_create_users_table.php這個文件:

<?php

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateUsersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name');
            $table->string('email')->unique();
            $table->string('password');
            $table->rememberToken();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::drop('users');
    }
}

上面的文件包含了up()down()兩個函數,up()中的內容是建立users表及其字段,而down()函數是刪除users表。

咱們暫時不用這兩個文件,咱們先刪除它們,而後咱們來建立咱們的posts表.

咱們到項目的根目錄執行php artisan, 裏面有一個php artisan make:migration的命令,其做用就是建立一個migration文件,若是你想看下這個命令的詳細信息和用法,能夠執行 php artisan -h make:migration ,咱們來試一下,進入終端,執行:

➜ php artisan make:migration create_posts_table --create=posts

# 輸出下面的信息
Created Migration: 2016_11_14_062612_create_posts_table

對於migration文件的命名,一般若是是建立一個表,那麼咱們能夠寫create_xxx的複數形式_table,後面跟上--create=表名, 那若是是添加表的一個字段呢,咱們能夠寫add_字段名_to_表名_table,後面跟上指定的表名--table=表名,其實就是寫成一句通順的英文句子,這在團隊開發的時候是很是必要的。

再回頭打開在database/migrations下建立的2016_11_14_062612_create_posts_table.php文件,主要看up()函數:

public function up()
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->increments('id');
            $table->timestamps();
        });
    }

這裏是調用了Schema類的create方法,咱們要添加的表字段都會放在這個方法的閉包函數中,好比咱們的帖子須要一個字符串類型的標題,那麼只要這麼寫:

$table->string('title');

經過這句代碼的字面意思,你們就可以看懂,若是還想添加別的類型,查詢下laravel文檔

這裏咱們還要來看下$table->timestamps();這句話,這句話能夠替咱們的表自動生成created_atupdated_at字段,而且laravel會自動維護它,好比咱們建立一篇帖子,咱們不用手動的寫明建立時間,laravel會自動的幫咱們填上建立時間,這很是有用,除了一些字典表外,別的表我建議你們均可以保留它。

好了,咱們在編輯下2016_11_14_062612_create_posts_table.php的up()函數,最終以下:

public function up()
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->increments('id');
            $table->string('title');
            $table->text('content')->nullable();
            $table->timestamps();
        });
    }

migration文件咱們建立好了,下面咱們若是將該表生成到數據庫中呢,在終端進入項目根目錄,執行php artisan migrate便可。

php artisan migrate
# 輸出下面信息
Migration table created successfully.
Migrated: 2016_11_14_062612_create_posts_table

注意:如今咱們尚未講到.env文件的使用,你們執行上面的命令前,先把根目錄下的.env文件中的下面代碼註釋掉,用英文的#註釋:

# DB_CONNECTION=mysql
# DB_HOST=127.0.0.1
# DB_PORT=3306
# DB_DATABASE=homestead
# DB_USERNAME=homestead
# DB_PASSWORD=secret

下面咱們寫一些測試代碼看看數據庫的使用,對於一些簡單的測試代碼,咱們可使用php artisan tinker工具,在終端進入這個工具,咱們能夠直接編寫咱們的php代碼,如:

php artisan tinker

和上面的方法同樣,你們用tinker工具,在插入一條數據,而後經過代碼DB::table('posts')->get(); 查看咱們如今posts表中的全部數據以下:

=> [
     {#626
       +"id": "1",
       +"title": "My New Post Title",
       +"content": "new post content",
       +"created_at": "2016-11-14 07:22:32",
       +"updated_at": "2016-11-14 07:22:32",
     },
     {#627
       +"id": "2",
       +"title": "My Second  Post Title",
       +"content": "Second post content",
       +"created_at": "2016-11-14 07:27:50",
       +"updated_at": "2016-11-14 07:27:50",
     },

測試沒有問題後,咱們將上面的代碼寫到咱們的控制器類中去,打開PagesController類,更改下index()函數以下:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Http\Requests;
use DB;  // 使用DB命名空間

class PostsController extends Controller
{
    public function index()
    {
        // 這裏使用了DB類,頭部須要引入DB的命名空間
        $posts = DB::table('posts')->get();

        return view('posts.index', compact('posts'));
    }
}

下面打開posts/index.balde.php視圖文件,修改以下:

@extends('layout')

@section('content')
    <h1>全部的帖子</h1>

    @foreach ($posts as $post)
        <h2>{{ $post->title }}</h2>
        <p>{{ $post->content }}</p>
    @endforeach
@stop

開啓serve, 瀏覽器http://localhost:8000/posts 就能正確顯示了。

Laravel提供了另外一個很是強大的ORM Elequent, 若是是第一次接觸Elequent,不少人會去查一下它的意思是什麼,查查能夠,可是不用去糾結,它就是一個名字而已,就像artisan也就是個名字,咱們不用過多的關心它的意思,咱們只要知道它能幹什麼就好了,用的多了,之後聽到這個詞,你就會知道它是個ORM,會聯想到它的一些用法和它的強大。咱們先簡單的看看這個Elequent, 還在終端,在項目的根目錄下,咱們執行:

➜ php artisan make:model Post                                 
Model created successfully.

注意:模型 Model名通常都是表名的單數形式,好比表名叫posts, Model名則是Post, 表名叫users, 則Model名就是User, 這樣寫的好處是,Laravel能經過Model名自動找到對應的表名。

咱們在app/目錄下打開,Post.php文件:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    //
}

ok, 如今更改下PagesController.php中的代碼:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Http\Requests;
use App\Post;

class PostsController extends Controller
{
    public function index()
    {
        $posts = Post::all();

        return view('posts.index', compact('posts'));
    }
}

在瀏覽器在訪問下,仍是獲得相同的輸出。是否是代碼更清晰了。

咱們在來作一個小功能,咱們給帖子列表上的每一個帖子標題添加一個連接,讓其跳轉到具體的帖子頁面,咱們的流程固然仍是,路由-》控制器-》視圖層

route.php添加一條路由:

Route::get('posts/{post}', 'PostsController@show');

一般咱們訪問一個帖子的路由通常是:posts/1相似這種,咱們上面的{post},接受的其實就是帖子的id, 咱們這裏爲何寫{post},而不寫{id}呢? 這個問題先放放,咱們接着往下走。

咱們而後進入PostsController.php, 編寫show()函數,以下:

// 這裏的$post變量接受路由{post}傳遞來的數值
    public function show($post)
    {
        return $post;
    }

咱們訪問:http://localhost:8000/posts/1, 頁面返回的數據是1.咱們要獲取帖子id爲1的數據呢,咱們再改下show()函數:

public function show($postId)
    {
        $post = Post::find($postId);

        return $post;
    }

咱們訪問:http://localhost:8000/posts/1

顯示具體帖子頁面

上面代碼的修改,咱們獲得了咱們想要的數據,不過這樣作,代碼有點多餘,咱們寫代碼在易讀的基礎上固然是越少越好,Laravel提供了路由模型綁定的功能(其實就是依賴注入),咱們再來更改下show()函數:

public function show(Post $post)
    {
        return $post;
    }

咱們將$post指名爲Post的一個對象,當laravel執行到show()函數時,會自動實例話$post對象,這時候咱們返回$post,就能夠獲得一個具體的對象了。

咱們試下: http://localhost:8000/posts/2

路由模型綁定

注意:使用上面的路由模型綁定功能,必定要注意路由中的{post}與對應控制器中的$post這兩個變量名必定要如出一轍,若是你路由中的變量寫成{postId}, 而控制器的中對應的變量使用$post, 那麼路由模型綁定就不會成功了。

上面的show()函數對應的show.balde.php咱們沒有寫,這個你們本身去補上吧!

相關文章
相關標籤/搜索