成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

Laravel學(xué)習(xí)筆記之Schema Builder 和 Migration System(上)

nevermind / 678人閱讀

摘要:看下兩個(gè)方法的源碼同樣是使用了對(duì)象來添加命令和。

說明:本文主要學(xué)習(xí)Schema Builder和Migration System的使用及相關(guān)原理。傳統(tǒng)上在設(shè)計(jì)database時(shí)需要寫大量的SQL語句,但Laravel提供了Schema Builder這個(gè)神器使得在設(shè)計(jì)database時(shí)使用面向?qū)ο蠓椒▉碜?,不需要寫一行SQL,并且還提供了另一個(gè)神器Migration System,可以對(duì)database做版本控制,包括回滾上一次的遷移操作。本小系列主要分為上中下三篇。本篇主要學(xué)習(xí)使用Schema Builder來creating,dropping,updating tables;adding,removing,renaming columns;simple index,unique index,foreign keys,同時(shí)也會(huì)學(xué)習(xí)相關(guān)源碼來進(jìn)一步了解Schema Builder。

開發(fā)環(huán)境: Laravel5.3 + PHP7

表的操作-tables

在設(shè)計(jì)database時(shí)需要?jiǎng)?chuàng)建、刪除和更新表,Schema Builder類提供了一些methods來面向?qū)ο蟮膱?zhí)行這些操作,而不需要寫一行SQL。在寫Laravel程序時(shí),也經(jīng)常使用類似命令php artisan make:migration create_accounts_table --create=accounts來做一個(gè)遷移類創(chuàng)建數(shù)據(jù)表,會(huì)在database/migrations文件夾下得到類似如下的代碼類:

use IlluminateSupportFacadesSchema;
use IlluminateDatabaseSchemaBlueprint;
use IlluminateDatabaseMigrationsMigration;

class CreateAccountsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create("accounts", function (Blueprint $table) {
            $table->increments("id");
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists("accounts");
    }
}
(1)creating tables

在執(zhí)行php artisan migrate命令時(shí)操作的是up()方法中語句。在創(chuàng)建的遷移類CreateAccountsTable中,Schema::create()就是創(chuàng)建表的語句,并且第一個(gè)參數(shù)就是表的名字,第二個(gè)參數(shù)是個(gè)閉包,是操作columns的語句,并且參數(shù)是個(gè)Blueprint對(duì)象。為什么有這么奇怪的寫法呢?

看下Schema Facade中getFacadeAccessor的源碼:

    /**
     * Get a schema builder instance for the default connection.
     *
     * @return IlluminateDatabaseSchemaBuilder
     */
    protected static function getFacadeAccessor()
    {
        // 這里"db"服務(wù)是在DatabaseServiceProvider中定義的,是DatabaseManager對(duì)象,且laravel默認(rèn)connection是mysql
        // 則返回的是MysqlBuilder,也就是IlluminateDatabaseSchemaBuilder的子類
        return static::$app["db"]->connection()->getSchemaBuilder();
    }

根據(jù)注釋就知道Schema::create就是等同于MysqlBuilder::create(),看下源碼:

    // IlluminateDatabaseSchemaBuilder
    /**
     * Create a new table on the schema.
     *
     * @param  string    $table
     * @param  Closure  $callback
     * @return IlluminateDatabaseSchemaBlueprint
     */
    public function create($table, Closure $callback)
    {
        /** @var IlluminateDatabaseSchemaBlueprint $blueprint */
        $blueprint = $this->createBlueprint($table);

        // 添加"create"命令
        $blueprint->create();

        // 執(zhí)行閉包里的操作,也就是操作columns
        $callback($blueprint);

        $this->build($blueprint);
    }
    
    protected function createBlueprint($table, Closure $callback = null)
    {
        if (isset($this->resolver)) {
            return call_user_func($this->resolver, $table, $callback);
        }

        return new Blueprint($table, $callback);
    }
    
    // IlluminateDatabaseSchemaBlueprint
    public function create()
    {
        return $this->addCommand("create");
    }
    
    protected function build(Blueprint $blueprint)
    {
        $blueprint->build($this->connection, $this->grammar);
    }

create()中的$callback($blueprint);語句執(zhí)行了閉包操作,并且閉包參數(shù)還是個(gè)Blueprint對(duì)象。最關(guān)鍵的方法時(shí)Blueprint對(duì)象的build()方法,下文再聊具體細(xì)節(jié)。

當(dāng)然,Schema Builder是可以在任意模塊中使用的,如在路由中使用,執(zhí)行https://localhost:8888/create_accounts就可以創(chuàng)建一個(gè)accounts表了:

Route::get("create_accounts", function () {
    IlluminateSupportFacadesSchema::create("accounts", function(IlluminateDatabaseSchemaBlueprint $table)
    {
        $table->increments("id");
        $table->string("name");
        $table->string("number");
        $table->tinyInteger("status");
        $table->enum("source", ["bank account", "credit card", "investment account"]);
        $table->timestamps();
    });
});
(2)dropping tables

Schema Builder提供了兩個(gè)方法來刪除表:drop(string $table)dropIfExists(string $table),參數(shù)是表名,dropIfExists()表示只有在表存在才刪除,所以dropIfExists()drop()更優(yōu)雅。看下兩個(gè)方法的源碼:

    /**
     * Drop a table from the schema.
     *
     * @param  string  $table
     * @return IlluminateDatabaseSchemaBlueprint
     */
    public function drop($table)
    {
        $blueprint = $this->createBlueprint($table);

        $blueprint->drop();

        $this->build($blueprint);
    }

    /**
     * Drop a table from the schema if it exists.
     *
     * @param  string  $table
     * @return IlluminateDatabaseSchemaBlueprint
     */
    public function dropIfExists($table)
    {
        $blueprint = $this->createBlueprint($table);

        $blueprint->dropIfExists();

        $this->build($blueprint);
    }
    
    // IlluminateDatabaseSchemaBlueprint
    public function drop()
    {
        return $this->addCommand("drop");
    }
    public function dropIfExists()
    {
        return $this->addCommand("dropIfExists");
    }

同樣是使用了Blueprint對(duì)象來添加命令dropdropIfExists。在路由中刪除accounts表:

Route::get("delete_accounts", function () {
    IlluminateSupportFacadesSchema::dropIfExists("accounts");
//    IlluminateSupportFacadesSchema::drop("accounts");
});
(3)updating tables

更新表的操作包括更新表名和更新表字段。

使用Schema::rename($from, $to)方法來更新表名:

Route::get("rename_bank_accounts", function () {
    IlluminateSupportFacadesSchema::rename("accounts", "bank_accounts");
});

看下Schema的rename()源碼,同樣是使用Blueprint對(duì)象添加rename命令:

    public function rename($from, $to)
    {
        $blueprint = $this->createBlueprint($from);

        $blueprint->rename($to);

        $this->build($blueprint);
    }
    
    
    // IlluminateDatabaseSchemaBlueprint
    public function rename($to)
    {
        return $this->addCommand("rename", compact("to"));
    }

使用Schema::table()方法來更新表字段值,如更新accountsnumber字段,,不過如果該表中有字段類型為enum就不支持修改:

Route::get("update_accounts", function () {
    IlluminateSupportFacadesSchema::table("accounts", function(IlluminateDatabaseSchemaBlueprint $table)
    {
        $table->string("number", 50)->change();
    });
});

同時(shí),Schema還提供了幾個(gè)有用的方法,如hasTable($table),hasColumn($table, $column),hasColumns($table, array $column),getColumnListing($table):

Route::get("get_column_listing", function () {
//    if (IlluminateSupportFacadesSchema::hasTable("accounts"))
//    if (IlluminateSupportFacadesSchema::hasColumn("accounts", "name"))
    if (IlluminateSupportFacadesSchema::hasColumns("accounts", ["name"]))
    {
        // ["id", "name", "number", "status", "source", "created_at", "updated_at"]
        return IlluminateSupportFacadesSchema::getColumnListing("accounts");
    }
});
字段的操作-column (1)adding columns

設(shè)計(jì)database時(shí)需要添加columns,上文說過這段邏輯是在Schema::create(),Schema::table()的閉包里執(zhí)行的,利用Blueprint對(duì)象來依次添加每一個(gè)column字段屬性和Mysql中數(shù)據(jù)類型對(duì)應(yīng),如:

IlluminateSupportFacadesSchema::create("accounts", function(IlluminateDatabaseSchemaBlueprint $table)
    {
        $table->string("name"); // => $this->addColumn("string", $column, compact("length"));
    });

常用的Schema字段類型函數(shù)表如下:

Schema Column Type MySQL Column Type
bigIncrements("id") id UNSIGNED BIGINT
bigInteger("number") number BIGINT
binary("data") data BLOB
boolean("is_viewed") is_viewed BOOLEAN
char("title", 50) title CHAR(50)
date("created_at") created_at DATE
dateTime("updated_at") updated_at DATETIME
decimal("amount", 2, 2) amount DECIMAL(2,2)
double("length", 10, 10) length DOUBLE(10, 10)
enum("source", ["fund", "equity"]) source ENUM("fund", "equity")
float("width", 5, 5) width FLOAT(5, 5)
json("options") options JSON
string("content") content VARCHAR(255)
text("description") description TEXT
... ...

``

(2)removing columns

Schema提供了dropColumn()方法來刪除表中字段:

Route::get("drop_column", function () {
    IlluminateSupportFacadesSchema::table("accounts", function(IlluminateDatabaseSchemaBlueprint $table)
    {
        $table->dropColumn(["number", "status"]);
    });
});
(3)renaming columns

Schema提供了renameColumn()來修改column名稱,不過如果該表中有字段類型為enum就不支持修改:

Route::get("rename_column", function () {
    IlluminateSupportFacadesSchema::table("accounts", function(IlluminateDatabaseSchemaBlueprint $table)
    {
        $table->renameColumn("name", "title");
    });
});
索引操作-index (1)simple index

Schema提供了index()方法來給column加索引,且索引名稱約定為table-name_column-name_index-type:

Route::get("index_column", function () {
    IlluminateSupportFacadesSchema::table("accounts", function(IlluminateDatabaseSchemaBlueprint $table)
    {
        $table->index("name");
    });
});

同時(shí),Schema提供了dropIndex("table-name_column-name_index")來刪除simple index。

(2)unique index

Schema提供了unique()方法來給column加索引,且索引名稱約定為table-name_column-name_index-type:

Route::get("unique_column", function () {
    IlluminateSupportFacadesSchema::table("accounts", function(IlluminateDatabaseSchemaBlueprint $table)
    {
        $table->unique(["title"]);
    });
});

同時(shí),Schema提供了dropUnique("table-name_column-name_unique")來刪除unique index。

(3)foreign key

Schema提供了foreign()->reference()->on() fluent api來設(shè)計(jì)foreign key,且索引名稱約定為table-name_column-name_index-type:

Route::get("foreign_key_column", function () {
    IlluminateSupportFacadesSchema::create("bills", function(IlluminateDatabaseSchemaBlueprint $table)
    {
        $table->increments("id");
        $table->unsignedInteger("account_id");
        $table->float("amount", 5, 5);

        $table->foreign("account_id")
            ->references("id")
            ->on("accounts")
            ->onUpdate("CASCADE")
            ->onDelete("CASCADE");
    });
});

同時(shí),Schema提供了dropForeign("table-name_column-name_foreign")來刪除foreign index。

總結(jié):本篇主要學(xué)習(xí)下Laravel使用了Schema和Blueprint兩個(gè)類來設(shè)計(jì)database,中篇將以Schema::create()為例仔細(xì)研究下源碼是如何轉(zhuǎn)換為SQL并執(zhí)行SQL語句的,下篇聊下Migration System的使用及其原理。到時(shí)見。

RightCapital招聘Laravel DevOps

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/21962.html

相關(guān)文章

  • Laravel學(xué)習(xí)筆記Query Builder源碼解析()

    摘要:說明本文主要學(xué)習(xí)模塊的源碼。這里,就已經(jīng)得到了鏈接器實(shí)例了,該中還裝著一個(gè),下文在其使用時(shí)再聊下其具體連接邏輯。 說明:本文主要學(xué)習(xí)Laravel Database模塊的Query Builder源碼。實(shí)際上,Laravel通過Schema Builder來設(shè)計(jì)數(shù)據(jù)庫,通過Query Builder來CURD數(shù)據(jù)庫。Query Builder并不復(fù)雜或神秘,只是在PDO擴(kuò)展的基礎(chǔ)上又開...

    Steve_Wang_ 評(píng)論0 收藏0
  • Laravel學(xué)習(xí)筆記Seeder填充數(shù)據(jù)小技巧

    摘要:而且,與是一對(duì)多關(guān)系一個(gè)分類下有很多,一個(gè)只能歸屬于一個(gè)與是一對(duì)多關(guān)系一篇博客下有很多,一條只能歸屬于一篇與是多對(duì)多關(guān)系一篇有很多,一個(gè)下有很多。 說明:本文主要聊一聊Laravel測(cè)試數(shù)據(jù)填充器Seeder的小技巧,同時(shí)介紹下Laravel開發(fā)插件三件套,這三個(gè)插件挺好用哦。同時(shí),作者會(huì)將開發(fā)過程中的一些截圖和代碼黏上去,提高閱讀效率。 備注:在設(shè)計(jì)個(gè)人博客軟件時(shí),總會(huì)碰到有分類Ca...

    cgspine 評(píng)論0 收藏0
  • Laravel學(xué)習(xí)筆記Demo2——用Ajax來做個(gè)ToDoList(待更新)

    摘要:抱歉,最近忙,本篇等有時(shí)間更新。引言本文基于框架做的一個(gè)生成和存儲(chǔ),主要目的是學(xué)習(xí)使用框架。書籍基于的,學(xué)習(xí)時(shí)使用框架開發(fā)。開發(fā)環(huán)境備注一直想把這本書的個(gè)作為系列分享出來,供初學(xué)者學(xué)習(xí)玩玩。 抱歉,最近忙,本篇等有時(shí)間更新。 引言 本文基于Laravel框架做的一個(gè)URL生成和存儲(chǔ)demo,主要目的是學(xué)習(xí)使用Laravel框架。內(nèi)容基于英文書籍《Packt.Laravel.Applic...

    luck 評(píng)論0 收藏0
  • Laravel學(xué)習(xí)筆記Redis保存頁面瀏覽量

    摘要:說明本文主要講述使用作為緩存加快頁面訪問速度。何不用來做緩存,等到該達(dá)到一定瀏覽頁面后再刷新下,效率也很高??勺骶彺嫦到y(tǒng)隊(duì)列系統(tǒng)。 說明:本文主要講述使用Redis作為緩存加快頁面訪問速度。同時(shí),作者會(huì)將開發(fā)過程中的一些截圖和代碼黏上去,提高閱讀效率。 備注:作者最近在學(xué)習(xí)github上別人的源碼時(shí),發(fā)現(xiàn)好多在計(jì)算一篇博客頁面訪問量view_count時(shí)都是這么做的:利用Laravel...

    z2xy 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<