Laravel源碼--Facade門面

文章簡單介紹了 Facade 門面寸癌,總結(jié)了其工作原理,并介紹了 Facade 的使用方法弱贼。

介紹

Facade 為應用服務容器中綁定的類提供了一個“靜態(tài)”接口蒸苇。Laravel 內(nèi)置了很多 Facade,幾乎可以用來訪問 Laravel 中所有的服務哮洽。Laravel 的 Facade 作為服務容器中底層類的“靜態(tài)代理”填渠,相比于傳統(tǒng)靜態(tài)方法,F(xiàn)acade 提供了簡潔且豐富的語法同時,還帶來了更好的可測試性和擴展性氛什。Laravel 的所有 Facade 都定義在 “Illuminate\Support\Facades”命名空間下莺葫,我們也可以自己定義新的 Facade。

Facade 加載原理

為了更好的理解 Facade 的工作原理枪眉,我們從以下幾個方面進行介紹:

  • Facade 配置文件
  • 加載 RegisterFacades 類
  • 注冊 Facade 服務
  • 解析 Facade 服務

Facade配置文件

Facade 的配置文件保存在 config/app.php 中捺檬,主要用來保存所有的 Facade 別名,也即是把 Facade 和別名的對應關系存放在 config/app.php文件中的 aliases 數(shù)組里贸铜。aliases 數(shù)組的形式如下:


    'aliases' => [

        'App' => Illuminate\Support\Facades\App::class,
        'Artisan' => Illuminate\Support\Facades\Artisan::class,
        'Auth' => Illuminate\Support\Facades\Auth::class,
        'Blade' => Illuminate\Support\Facades\Blade::class,
        'Broadcast' => Illuminate\Support\Facades\Broadcast::class,
        'Bus' => Illuminate\Support\Facades\Bus::class,
        'Cache' => Illuminate\Support\Facades\Cache::class,
        'Config' => Illuminate\Support\Facades\Config::class,
        'Cookie' => Illuminate\Support\Facades\Cookie::class,
        'Crypt' => Illuminate\Support\Facades\Crypt::class,
        'DB' => Illuminate\Support\Facades\DB::class,
        'Eloquent' => Illuminate\Database\Eloquent\Model::class,
        'Event' => Illuminate\Support\Facades\Event::class,
        'File' => Illuminate\Support\Facades\File::class,
        'Gate' => Illuminate\Support\Facades\Gate::class,
        'Hash' => Illuminate\Support\Facades\Hash::class,
        'Lang' => Illuminate\Support\Facades\Lang::class,
        'Log' => Illuminate\Support\Facades\Log::class,
        'Mail' => Illuminate\Support\Facades\Mail::class,
        'Notification' => Illuminate\Support\Facades\Notification::class,
        'Password' => Illuminate\Support\Facades\Password::class,
        'Queue' => Illuminate\Support\Facades\Queue::class,
        'Redirect' => Illuminate\Support\Facades\Redirect::class,
        'Redis' => Illuminate\Support\Facades\Redis::class,
        'Request' => Illuminate\Support\Facades\Request::class,
        'Response' => Illuminate\Support\Facades\Response::class,
        'Route' => Illuminate\Support\Facades\Route::class,
        'Schema' => Illuminate\Support\Facades\Schema::class,
        'Session' => Illuminate\Support\Facades\Session::class,
        'Storage' => Illuminate\Support\Facades\Storage::class,
        'URL' => Illuminate\Support\Facades\URL::class,
        'Validator' => Illuminate\Support\Facades\Validator::class,
        'View' => Illuminate\Support\Facades\View::class,

    ],

aliases 數(shù)組遵循(別名 => Facade 類)的數(shù)據(jù)格式堡纬,當接受一個 HTTP 請求時注冊 aliases 數(shù)組,但是并沒有實際的進行別名綁定蒿秦,只是通過 spl_autoload_register() 函數(shù)進行了注冊烤镐。只有在遇到尚未發(fā)現(xiàn)的別名時,才去真正綁定別名棍鳖,因此炮叶,別名綁定是“懶惰”加載,并不影響程序的性能渡处。

加載 RegisterFacades 類

Facade 服務的注冊工作由“Illuminate\Foundation\Bootstrap\RegisterFacades”類完成镜悉,RegisterFacades 類是在啟動應用程序的過程中加載的。因此医瘫,我們首先來看index.php文件

<?php
//public\index.php
/**
 * 記錄框架的啟動時間
 * microtime(get_as_float)函數(shù)返回當前Unix時間戳的微妙數(shù)
 * get_as_float為true時返回浮點數(shù)侣肄,為false時返回字符串,默認為false
 */
define('LARAVEL_START', microtime(true));

/**
 * Composer的自動加載文件
 */
require __DIR__.'/../vendor/autoload.php';

/**
 * bootstrap文件里創(chuàng)建了一個Application實例
 */
$app = require_once __DIR__.'/../bootstrap/app.php';

/**
 * 通過container服務容器獲得一個kernel類的實例醇份,(Illuminate\Contracts\Http\Kernel是一個接口稼锅,
 * 真正生成的實例是App\Http\Kernel類)
 */
$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);


/**
 * laravel中所有功能服務的注冊加載
 * 通過調(diào)用kernel的handle方法,返回一個response
 * Illuminate\Http\Request::capture():通過全局$_SERVER數(shù)組構(gòu)造一個Http請求的語句
 */
$response = $kernel->handle(
    $request = Illuminate\Http\Request::capture()
);

//把response內(nèi)容發(fā)到瀏覽器
$response->send();

//執(zhí)行請求生命周期中的后續(xù)操作
$kernel->terminate($request, $response);

RegisterFacades 類的加載是在 $response = $kernel->handle( $request = Illuminate\Http\Request::capture() ) 語句進行的僚纷。該語句主要用于 Laravel各個功能服務的注冊啟動缰贝。

$request = Illuminate\Http\Request::capture() 

該語句是 Laravel 通過全局 $_SERVER 數(shù)組構(gòu)造一個 HTTP 請求的語句,接下來會調(diào)用 HTTP 的內(nèi)核函數(shù) handle()畔濒,RegisterFacades 類的加載即是在內(nèi)核函數(shù) handle() 中進行剩晴。

//Illuminate\Foundation\Http\Kernel.php
    /**
     * Handle an incoming HTTP request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function handle($request)
    {
        try {
            //允許在表單中使用delete、put等類型的請求
            $request->enableHttpMethodParameterOverride();

            //將請求發(fā)給中間件侵状、路由處理
            $response = $this->sendRequestThroughRouter($request);
        } catch (Exception $e) {
            $this->reportException($e);

            $response = $this->renderException($request, $e);
        } catch (Throwable $e) {
            $this->reportException($e = new FatalThrowableError($e));

            $response = $this->renderException($request, $e);
        }

        $this->app['events']->dispatch(
            new Events\RequestHandled($request, $response)
        );

        return $response;
    }

接下來赞弥,我們查看 sendRequestThroughRouter() 函數(shù)俏险。

//Illuminate\Foundation\Http\Kernel.php
     /**
     * Send the given request through the middleware / router.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    protected function sendRequestThroughRouter($request)
    {
        //設置request請求的對象實例
        $this->app->instance('request', $request);

        //清楚'request'對應的服務對象實例
        Facade::clearResolvedInstance('request');

        /**
         * 依次執(zhí)行$bootstrappers中每一個bootstrapper的bootstrap()函數(shù),做了幾件準備事情:
         * 1. 配置加載 LoadConfiguration
         * 2.日志配置 ConfigureLogging
         * 3.異常處理 HandleException
         * 4.注冊Facades RegisterFacades
         * 5.注冊Providers RegisterProviders
         * 6.啟動Providers BootProviders
         */
        $this->bootstrap();

        return (new Pipeline($this->app))       //請求的分發(fā)
                    ->send($request)
                    ->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware)
                    ->then($this->dispatchToRouter());
    }

函數(shù)首先在 Laravel 容器中設置了 request 請求的對象實例柬批,并且清楚了 Facade 中 request 請求對應的服務對象實例痰腮。接下來我們來看 bootstrap() 函數(shù)

//Illuminate\Foundation\Http\Kernel.php
     /**
     * Bootstrap the application for HTTP requests.
     * 啟動引導(reauests驅(qū)動)
     *
     * @return void
     */
    public function bootstrap()
    {
        //判斷引導是否已經(jīng)被啟動
        if (! $this->app->hasBeenBootstrapped()) {
            /**
             * 使用Application類的bootstrapWith()函數(shù)啟動引導
             * 參數(shù):bootstrapers數(shù)組晒旅。
             */
            $this->app->bootstrapWith($this->bootstrappers());
        }
    }

     /**
     * The bootstrap classes for the application.
     * 引導類,起引導作用的類
     *
     * @var array
     */
    protected $bootstrappers = [
        //載入服務器環(huán)境變量(.env文件)
        \Illuminate\Foundation\Bootstrap\LoadEnvironmentVariables::class,
        //載入配置信息(config目錄)
        \Illuminate\Foundation\Bootstrap\LoadConfiguration::class,
        //配置異常處理
        \Illuminate\Foundation\Bootstrap\HandleExceptions::class,
        //注冊Facades
        \Illuminate\Foundation\Bootstrap\RegisterFacades::class,
        //注冊Providers
        \Illuminate\Foundation\Bootstrap\RegisterProviders::class,
        //啟動Providers
        \Illuminate\Foundation\Bootstrap\BootProviders::class,
    ];

bootstrap() 函數(shù)首先判斷引導類是否已經(jīng)啟動侣诺,如果沒有啟動抛人,則啟動引導類叹洲。引導類數(shù)組包含 RegisterFacades 類。啟動引導類是調(diào)用“Illuminate\Foundation\Application”類中的 bootstrapWith() 函數(shù)鲁纠。

//Illuminate\Foundation\Application
     /**
     * Run the given array of bootstrap classes.
     *
     * @param  array  $bootstrappers
     * @return void
     */
    public function bootstrapWith(array $bootstrappers)
    {
        $this->hasBeenBootstrapped = true;

        foreach ($bootstrappers as $bootstrapper) {
            /**
             * 告知將要啟動該bootstrapper
             * $this['events']:對應綁定的類為 Dispatcher類(Illuminate\Events\Dispatcher)
             * [$this]:數(shù)組总棵,只有一個Application類元素
             */
            $this['events']->fire('bootstrapping: '.$bootstrapper, [$this]);

            //解析每個 $bootstrapper,并調(diào)用他們自身的 bootstrap() 函數(shù)
            $this->make($bootstrapper)->bootstrap($this);

            $this['events']->fire('bootstrapped: '.$bootstrapper, [$this]);
        }
    }

bootstrapWith() 函數(shù)中的 $this->make($bootstrapper)->bootstrap($this) 語句即是解析出 $bootstrappers 數(shù)組中的每個類改含,并調(diào)用相應的 bootstrap() 函數(shù)情龄。因此,RegisterFacades 類也即是在此時調(diào)用捍壤。

注冊 Facade 服務

下面我們來看 RegisterFacades 類骤视。

//Illuminate\Foundation\Bootstrap\RegisterFacades.php
<?php

namespace Illuminate\Foundation\Bootstrap;

use Illuminate\Foundation\AliasLoader;
use Illuminate\Support\Facades\Facade;
use Illuminate\Foundation\PackageManifest;
use Illuminate\Contracts\Foundation\Application;

class RegisterFacades
{
    /**
     * Bootstrap the given application.
     *
     * @param  \Illuminate\Contracts\Foundation\Application  $app
     * @return void
     */
    public function bootstrap(Application $app)
    {
        //清除所有的門面對象服務實例
        Facade::clearResolvedInstances();

        //設置門面對象的Application實例
        Facade::setFacadeApplication($app);

        /**
         * 默認的別名配置是從 app 配置文件下的 aliases 讀取的,
         * PackageManifest 是 laravel 5.5 新增的 包自動發(fā)現(xiàn) 規(guī)則
         */
        AliasLoader::getInstance(array_merge(
            $app->make('config')->get('app.aliases', []),
            $app->make(PackageManifest::class)->aliases()
        ))->register();
    }
}

可以看出鹃觉,RegisterFacades 類只有一個 bootstrap() 函數(shù)专酗,該函數(shù)主要完成以下功能:

  • 清楚所有 Facade 對象服務實例
  • 設置門面對象的 Application 實例
  • 通過 AliasLoader 類為所有的 Facade 注冊別名

接下來我們查看 AliasLoader 類如何注冊別名。

//llluminate\Foundation\AliasLoader.php
     /**
     * Get or create the singleton alias loader instance.
     * 獲取或創(chuàng)建 AliasLoader 單例實例盗扇。
     *
     * @param  array  $aliases
     * @return \Illuminate\Foundation\AliasLoader
     */
    public static function getInstance(array $aliases = [])
    {
        if (is_null(static::$instance)) {
            return static::$instance = new static($aliases);
        }

        $aliases = array_merge(static::$instance->getAliases(), $aliases);

        static::$instance->setAliases($aliases);

        return static::$instance;
    }

     /**
     * Register the loader on the auto-loader stack.
     * 將加載器注冊到自動加載中
     *
     * @return void
     */
    public function register()
    {
        if (! $this->registered) {
            $this->prependToLoaderStack();

            $this->registered = true;
        }
    }

     /**
     * Prepend the load method to the auto-loader stack.
     * 設置自動加載方法
     *
     * @return void
     */
    protected function prependToLoaderStack()
    {
        // 把AliasLoader::load()放入自動加載函數(shù)隊列中笼裳,并置于隊列頭部
        spl_autoload_register([$this, 'load'], true, true);
    }

AliasLoader 類首先調(diào)用 getInstance() 函數(shù)獲得 AliasLoader 的單例實例,然后調(diào)用 register() 函數(shù)將 AliasLoader 類中的 load() 函數(shù)注冊到 SPL __autoload 函數(shù)隊列的頭部粱玲。

//llluminate\Foundation\AliasLoader.php
     /**
     * Load a class alias if it is registered.
     *
     * @param  string  $alias
     * @return bool|null
     */
    public function load($alias)
    {
        if (static::$facadeNamespace && strpos($alias, static::$facadeNamespace) === 0) {
            $this->loadFacade($alias);

            return true;
        }

        if (isset($this->aliases[$alias])) {
            //注冊別名
            return class_alias($this->aliases[$alias], $alias);
        }
    }

load() 函數(shù)的上半部分是 laravel5.4 版本新出的功能,叫做實時門面服務拜轨。下半部分是 class_alias() 函數(shù)利用別名映射數(shù)組將別名映射到真正的門面類中去抽减。例如,我們使用別名類 Cache 時橄碾,程序會通過 AliasLoader 類的 load() 函數(shù)為“Illuminate\Support\Facades\Cache::class”類創(chuàng)建一個別名 Cache卵沉,所以我們在程序里使用別名 Cache 就是使用“Illuminate\Support\Facades\Cache”類。

解析 Facade 服務

以 Cache 為例法牲,我們講一下 Facade 的使用史汗。我們首先來看一下 Cache Facade 類。

<?php
//Illuminate\Support\Facades\Cache.php

class Cache extends Facade
{
    /**
     * Get the registered name of the component.
     * 獲取組件注冊名稱
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return 'cache';
    }
}

該類內(nèi)部只有一個 getFacadeAccessor() 函數(shù)拒垃,該方法的功能是獲取已經(jīng)注冊組件的名稱停撞。其實每個門面類只是重寫了基類(Facade)的 getFacadeAccessor() 方法。

//Illuminate\Support\Facades\Facade.php
     /**
     * Handle dynamic, static calls to the object.
     * 動態(tài)綁定悼瓮,將門面的靜態(tài)方法調(diào)用綁定到門面對應的服務對象實例來執(zhí)行
     *
     * @param  string  $method
     * @param  array   $args
     * @return mixed
     *
     * @throws \RuntimeException
     */
    public static function __callStatic($method, $args)
    {
        //返回當前門面對應的服務對象實例
        $instance = static::getFacadeRoot();

        if (! $instance) {
            throw new RuntimeException('A facade root has not been set.');
        }

        //執(zhí)行服務對象實例相應的方法
        return $instance->$method(...$args);
    }

當運行 Cache::get() 函數(shù)時戈毒,門面類 Cache 類里并沒有 get() 函數(shù),此時 PHP 會自動調(diào)用魔術(shù)函數(shù) __callStatic()横堡。魔術(shù)函數(shù) __callStatic() 首先獲得 Facade 的服務對象實例埋市,然后調(diào)用對象的 get() 函數(shù)。下面我們來看如何獲得 Facade 的對象實例命贴。

//Illuminate\Support\Facades\Facade.php
     /**
     * Get the root object behind the facade.
     * 返回當前門面對應服務對象的實例
     *
     * @return mixed
     */
    public static function getFacadeRoot()
    {
        return static::resolveFacadeInstance(static::getFacadeAccessor());
    }

   /**
     * Get the registered name of the component.
     * 獲取組件注冊名稱道宅,子類重寫該函數(shù)
     *
     * @return string
     *
     * @throws \RuntimeException
     */
    protected static function getFacadeAccessor()
    {
        throw new RuntimeException('Facade does not implement getFacadeAccessor method.');
    }

     /**
     * Resolve the facade root instance from the container.
     * 創(chuàng)建并返回 $name 對應的對象實例
     *
     * @param  string|object  $name
     * @return mixed
     */
    protected static function resolveFacadeInstance($name)
    {
        //如果是對象食听,則直接返回
        if (is_object($name)) {
            return $name;
        }

        //$resolvedInstance數(shù)組中 $name 對應的對象實例是否存在,如果存在污茵,直接返回
        if (isset(static::$resolvedInstance[$name])) {
            return static::$resolvedInstance[$name];
        }

        /**
         * 具體的創(chuàng)建工作由Application類對象進行樱报,所以$name需要在Application中進行過綁定
         */
        return static::$resolvedInstance[$name] = static::$app[$name];
    }

基類中的 getFacadeRoot() 函數(shù)首先調(diào)用了 getFacadeAccessor() 函數(shù),也即是 Cache 類重寫的 getFacadeAccessor() 函數(shù)省咨,如果調(diào)用的是基類的 getFacadeAccessor() 函數(shù)則報錯肃弟。然后調(diào)用 resolveFacadeInstance() 函數(shù)獲得“cache”對應的服務實例。resolveFacadeInstance() 函數(shù)主要是從 Laravel 服務容器 static::$app[$name] 中解析出相應的服務零蓉◇允埽“cache”服務是應用程序初始化時,在類“Illuminate\Foundation\Bootstrap\RegisterProviders”中被注冊到容器中的敌蜂。
因為在程序啟動時箩兽,將 Facade 的別名通過 RegisterFacades 類進行了加載注冊,所以可以直接使用別名 Cache 代替“Illuminate\Support\Facades\Cache”章喉。
其實汗贫,Cache::get('key') 的寫法等價于以下寫法。

$value = $app->make('cache')->get('key');

建立 Facade

建立自己的 Facade秸脱,需要做以下幾方面的工作:

  • 創(chuàng)建自定義類(Facade 的實現(xiàn)類)
  • 創(chuàng)建 Facade 類
  • Facade 類別名設置
  • 創(chuàng)建 ServiceProvider
  • 加載 ServiceProvider

創(chuàng)建自定義類(Facade 的實現(xiàn)類)

我們現(xiàn)在 app\Facades 目錄下創(chuàng)建 PaymentGateway\Payment 類落包。

<?php
//app\Facades\\PaymentGateway\Payment.php

namespace App\Facades\PaymentGateway;

class Payment
{
    public function get(){
        return "Facade Test ...";
    }

}

創(chuàng)建 Facade 類

創(chuàng)建自定義的 Facade 類,該類繼承基類 Facade摊唇,并重寫基類的 getFacadeAccessor() 函數(shù)咐蝇。

<?php
//app\Facades\\PaymentGateway\Facade\Payment.php

namespace App\Facades\PaymentGateway\Facade;
use Illuminate\Support\Facades\Facade;

class Payment extends Facade
{
    /**
     * Get the registered name of the component.
     *
     * @return string
     */
    protected static function getFacadeAccessor()
    {
        return 'payment';
    }
}

Facade 類別名設置

我們可以為自定義的 Facade 類起個別名,只需要將別名和類的對應關系添加到 config/app.php 配置文件中的 aliases 數(shù)組即可巷查。

//config/app.php

  'aliases' => [
        ...
        'Payment' => App\Facades\PaymentGateway\Facade\Payment::class,
        ...
    ],

創(chuàng)建 ServiceProvider

在 app\Providers 文件夾下創(chuàng)建 PaymentServiceProvider有序,提供“payment”服務。

<?php
//app\Providers\PaymentServiceProvider.php

namespace App\Providers;

use App\Facades\PaymentGateway\Payment;
use Illuminate\Support\ServiceProvider;

class PaymentServiceProvider extends ServiceProvider
{
    /**
     * Indicates if loading of the provider is deferred.
     * $defer為true岛请,表示延遲加載此類
     *
     * @var bool
     */
    protected $defer = true;

    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {
        $this->app->singleton('payment', function ($app) {
            return new Payment();
        });

    }

    /**
     * 設置了延遲啟動旭寿,需要重寫 providers 函數(shù)
     * 該方法返回provider中注冊的服務容器綁定別名
     */
    public function provides()
    {
        return ["payment"];
    }
}

其中,$defer 設置為 true崇败,是為了提供延遲加載功能盅称,provides() 函數(shù)也是為了輔助延遲加載功能而重寫的。register() 函數(shù)中的服務名“payment”應該與 Facade 類中 getFacadeAccessor() 函數(shù)返回值保持一致后室。

加載 ServiceProvider

為了能加載我們創(chuàng)建的 PaymentServiceProvider微渠,需要在 config/app.php 配置文件中 providers 數(shù)組內(nèi)添加 PaymentServiceProvider。

//config/app.php

    'providers' => [
        ...
        App\Providers\PaymentServiceProvider::class,
        ...
 ],

最后咧擂,使用如下代碼即可以調(diào)用 Facade 類逞盆。

$value = Payment::get();

總結(jié)

之所以能夠簡單的使用 Cache::get() 操作,是因為程序啟動時自動進行了別名注冊松申,使用 Cache 等價于“Illuminate\Support\Facades\Cache”云芦。另外俯逾,程序在基類 Facade 中自動調(diào)用魔術(shù)函數(shù) __callStatic() 進行了動態(tài)綁定。

門面類列表

下面列出了每個 Facade 舅逸、對應的底層類以及服務容器綁定鍵桌肴。

門面 Facade 類 Class 服務容器綁定
App Illuminate\Foundation\Application app
Artisan Illuminate\Console\Application artisan
Auth Illuminate\Auth\AuthManager auth
Auth (實例) Illuminate\Auth\Guard
Blade Illuminate\View\Compilers\BladeCompiler blade.compiler
Bus Illuminate\Contracts\Bus\Dispatcher
Cache Illuminate\Cache\CacheManager cache
Config Illuminate\Config\Repository config
Cookie Illuminate\Cookie\CookieJar cookie
Crypt Illuminate\Encryption\Encrypter encrypter
DB Illuminate\Database\DatabaseManager db
DB (實例) Illuminate\Database\Connection
Event Illuminate\Events\Dispatcher events
File Illuminate\Filesystem\Filesystem files
Hash Illuminate\Contracts\Hashing\Hasher hash
Input Illuminate\Http\Request request
Lang Illuminate\Translation\Translator translator
Log Illuminate\Log\Writer log
Mail Illuminate\Mail\Mailer mailer
Password Illuminate\Auth\Passwords\PasswordBroker auth.password
Queue Illuminate\Queue\QueueManager queue
Queue (實例) Illuminate\Queue\QueueInterface
Queue (基礎類) Illuminate\Queue\Queue
Redirect Illuminate\Routing\Redirector redirect
Redis Illuminate\Redis\Database redis
Request Illuminate\Http\Request request
Response Illuminate\Contracts\Routing\ResponseFactory
Route Illuminate\Routing\Router router
Schema Illuminate\Database\Schema\Blueprint
Session Illuminate\Session\SessionManager session
Session (實例) Illuminate\Session\Store
Storage Illuminate\Contracts\Filesystem\Factory filesystem
URL Illuminate\Routing\UrlGenerator url
Validator Illuminate\Validation\Factory validator
Validator (實例) Illuminate\Validation\Validator
View Illuminate\View\Factory view
View (實例) Illuminate\View\View
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市琉历,隨后出現(xiàn)的幾起案子坠七,更是在濱河造成了極大的恐慌,老刑警劉巖旗笔,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件彪置,死亡現(xiàn)場離奇詭異,居然都是意外死亡蝇恶,警方通過查閱死者的電腦和手機拳魁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來撮弧,“玉大人潘懊,你說我怎么就攤上這事』哐埽” “怎么了授舟?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長贸辈。 經(jīng)常有香客問我释树,道長,這世上最難降的妖魔是什么裙椭? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮署浩,結(jié)果婚禮上揉燃,老公的妹妹穿的比我還像新娘。我一直安慰自己筋栋,他們只是感情好炊汤,可當我...
    茶點故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著弊攘,像睡著了一般抢腐。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上襟交,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天迈倍,我揣著相機與錄音,去河邊找鬼捣域。 笑死啼染,一個胖子當著我的面吹牛宴合,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播迹鹅,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼卦洽,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了斜棚?” 一聲冷哼從身側(cè)響起阀蒂,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎弟蚀,沒想到半個月后蚤霞,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡粗梭,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年争便,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片断医。...
    茶點故事閱讀 38,059評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡滞乙,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出鉴嗤,到底是詐尸還是另有隱情斩启,我是刑警寧澤,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布醉锅,位于F島的核電站兔簇,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏硬耍。R本人自食惡果不足惜垄琐,卻給世界環(huán)境...
    茶點故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望经柴。 院中可真熱鬧狸窘,春花似錦、人聲如沸坯认。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽牛哺。三九已至陋气,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間引润,已是汗流浹背巩趁。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留淳附,地道東北人晶渠。 一個月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓凰荚,卻偏偏與公主長得像,于是被迫代替她去往敵國和親褒脯。 傳聞我的和親對象是個殘疾皇子便瑟,可洞房花燭夜當晚...
    茶點故事閱讀 42,792評論 2 345

推薦閱讀更多精彩內(nèi)容

  • 介紹 Facades 為應用的 IoC 服務容器 的類提供了一個靜態(tài)的接口。Laravel 里面自帶了一些 Fac...
    伊Summer閱讀 11,033評論 0 11
  • Laravel 學習交流 QQ 群:375462817 本文檔前言Laravel 文檔寫的很好番川,只是新手看起來會有...
    Leonzai閱讀 7,773評論 2 12
  • 原文鏈接 必備品 文檔:Documentation API:API Reference 視頻:Laracasts ...
    layjoy閱讀 8,603評論 0 121
  • 1. Java基礎部分 基礎部分的順序:基本語法到涂,類相關的語法,內(nèi)部類的語法颁督,繼承相關的語法践啄,異常的語法,線程的語...
    子非魚_t_閱讀 31,581評論 18 399
  • 聽說: navigationController已經(jīng)實現(xiàn)了右滑返回上一頁. 然后打聽度娘之后, 發(fā)現(xiàn)iOS7出來了...
    L_zix閱讀 575評論 0 0