国产av日韩一区二区三区精品,成人性爱视频在线观看,国产,欧美,日韩,一区,www.成色av久久成人,2222eeee成人天堂

Laravel 里面model如何重用
伊謝爾倫
伊謝爾倫 2017-05-16 16:53:44
[PHP討論組]

我們公司現(xiàn)在在用Laravel開發(fā)項(xiàng)目,同時(shí)還增加了Biz層和Repositories層,來實(shí)現(xiàn)業(yè)務(wù)邏輯封裝,反而model里面什么代碼都沒有。
Controller里寫代碼的時(shí)候,嘗嘗困擾我的問題是如果復(fù)用Biz對(duì)象,Repositories對(duì)象和Model對(duì)象。
以前用Yii開發(fā)項(xiàng)目的時(shí)候,有一個(gè)工廠模式,所以調(diào)用Model的時(shí)候,基本都不new,都是字節(jié)用 XXX::model() 來調(diào)用的,一個(gè)對(duì)象被new一次就夠了,能有效節(jié)省內(nèi)存。
Controller代碼:

$productModel = Product::model()->getList('xxxxxxxxx');

多簡(jiǎn)單,有沒有?

Laravel里,Model好像沒有工廠,要調(diào)用,都需要實(shí)例,假如Repositories里面封裝了5個(gè)方法,每個(gè)都使用了Model,那么我在Controller里調(diào)用了這5個(gè)方法,Model就被new了5次。
目前在網(wǎng)上看到一種辦法,就是在Repositories的構(gòu)造函數(shù)里注入Model對(duì)象,放在Repositories的私有成員變量里,這樣5個(gè)方法都調(diào)用當(dāng)前類的私有變量就可以了。但使用起來就麻煩了,在Controller里寫代碼的時(shí)候,需要這樣寫:

$xxxBiz = new XXXBiz(\xxx\xxx\Repositories);

在Repositories里需要這樣寫:

$xxxRepositories = new XXXRepositories(\xxx\xx\xxxModel);

在new一個(gè)Biz的時(shí)候,還必須傳入Repositories對(duì)象,而且命名空間還老長(zhǎng),我基本都是在拼字符串了,寫代碼效率超低,還要打開這寫文件,去把名字拼出來。

想問一下大家在用Laravel開發(fā)項(xiàng)目的時(shí)候,是如何解決Model這種邏輯層類復(fù)用的情況?

伊謝爾倫
伊謝爾倫

小伙看你根骨奇佳,潛力無限,來學(xué)PHP伐。

全部回復(fù)(5)
漂亮男人

0x0 前言

有趣的問題,Yii 在業(yè)界也是被公認(rèn)為性能比 Laravel 高的一個(gè)框架。于是我想單從 ActiveRecord 的構(gòu)造,看看兩大框架的具體實(shí)現(xiàn)。

0x1 Laravel 的 Eloquent 框架

在 Laravel 中可以很輕松地使用關(guān)系查詢:

    $user = User::find(1);

我在 User 類里并沒有找到 find 方法,WTF,發(fā)生了什么?。?/p>

User 的基類是 Model,使用靜態(tài)調(diào)用,所以會(huì)調(diào)用 Model 的 __callStatic 魔術(shù)方法:

    public static function __callStatic($method, $parameters)
    {
        // $method = 'find';
        // $parameters = [1];
        
        // 實(shí)例化當(dāng)前類,即 User 模塊
        $instance = new static;
        // 調(diào)用當(dāng)前實(shí)例的 find 方法
        return call_user_func_array([$instance, $method], $parameters);
    }

其實(shí)就是再調(diào)用 __call 魔術(shù)方法:

    public function __call($method, $parameters)
    {
        //...

        $query = $this->newQuery();

        return call_user_func_array([$query, $method], $parameters);
    }

追根溯源,我們發(fā)現(xiàn)其實(shí) find 方法來自 Illuminate\Database\Eloquent\Builder,而該類內(nèi)部使用 Illuminate\Database\Query\Builder 的實(shí)現(xiàn)。

等等,Illuminate\Database\Eloquent\BuilderIlluminate\Database\Query\Builder 的區(qū)別是啥?

其實(shí) Eloquent\Builder 是對(duì) Query\Builder 的進(jìn)一步封裝,以便更好的實(shí)現(xiàn)關(guān)系對(duì)象查詢。

那么,其實(shí)過程為:

也就是說,你每次 靜態(tài)調(diào)用 Model 的方法,都會(huì)實(shí)例化一次 Model,走一次過程。

0x2 Yii 1.1 中的 CActiveRecord

題主既然用到 model 方法,那應(yīng)該是 1.1 的版本,模塊繼承自 CActiveRecord(Yii2 中則繼承自 Yii\db\ActiveRecord)。

好了,伙計(jì)們,現(xiàn)在使用 Yii 實(shí)現(xiàn)關(guān)系查詢,先定義:

    class User extends CActiveRecord
    {
        public static function model($className=__CLASS__)
        {
            return parent::model($className);
        }
    }

查詢:

    $user = User::model()->findAllByPk(1);

明顯查詢對(duì)象來自 model,看看父類怎么實(shí)現(xiàn)這個(gè)函數(shù):

    public static function model($className=__CLASS__)
    {
        // 如果已經(jīng)實(shí)例化了則直接返回該實(shí)例
        if(isset(self::$_models[$className]))
            return self::$_models[$className];
        else
        {
            // 初始化,并將保存當(dāng)前實(shí)例
            $model=self::$_models[$className]=new $className(null);
            $model->attachBehaviors($model->behaviors());
            return $model;
        }
    }

findAllByPk 方法直接封裝于 CActiveRecord 內(nèi)部:

    public function findByPk($pk,$condition='',$params=array())
    {
        // ...

        $criteria = $this->getCommandBuilder()->createPkCriteria($this->getTableSchema(),
            $pk, $condition, $params, $prefix);
            
        return $this->query($criteria);
    }

所以其過程為:

0x3 使用 Laravel 的依賴注入

通常情況下(無參數(shù)的構(gòu)造函數(shù)或注入?yún)?shù)已配置),Laravel 會(huì)自動(dòng)幫你實(shí)例化:

<?php namespace App\Repositories;

use App\User;    
    
class Repository {
    
    protected $user;
    
    public __construct(User $user) {
        $this->user = $user;
    }
}

所以你可以很輕松復(fù)用同一個(gè)對(duì)象:

class Repository {
    
    protected $user;
    
    public __construct(User $user) {
        $this->user = $user;
    }
    
    public function first() {
        $this->user->first();
    }
    
    public function find(Request $request, $id) {
        if (Gate::denies('view', $request->user())) {
            abort(403);
        }
        
        return $this->user->find($id);
    }
    
    public function excited() {
        return $this->user->where('name', 'bigNews')->get();
    }
}

實(shí)現(xiàn)完倉(cāng)庫(kù)后,你需要手動(dòng)實(shí)例化嗎:

    $repo = new App\Repositories\Repository(new App\User());

不,這不符合 Laravel 的哲♂學(xué),你可以如此簡(jiǎn)單:

<?php
    use App\Repositories\Repository;
    
    public function index(Repository $repo) {
        return $repo->first();
    }

是的,沒錯(cuò),你無需手動(dòng)構(gòu)造,傳入 User 實(shí)例等等,一切只是一個(gè)簡(jiǎn)單的自動(dòng)注入。而且題主注意到這里使用了命名空間,所以你只需 use 一次。(當(dāng)然如果你不想拼寫這么長(zhǎng)的命名空間,那你是時(shí)候換一款 IDE 了,PhpStorm 中可以使用 Alt + Enter 快速導(dǎo)入

0x4 最后

對(duì)于靜態(tài)和非靜態(tài)開銷的問題,在 StackOverflow 上有一篇討論:http://stackoverflow.com/questions/14727...

所以說到底還是看業(yè)務(wù)需求嘛23333

阿神

通過依賴注入呀
直接可以注入到Controller中
可以看看這個(gè)文章
http://slides.com/howtomakeaturn/model#/

高洛峰

我假定你對(duì)Laravel還不是很了解。

第一,Laravel的Model也就是模型,不需要顯式的實(shí)例化,調(diào)用方式像下面這樣(摘自官方文檔):

$flights = App\Flight::where('active', 1)
               ->orderBy('name', 'desc')
               ->take(10)
               ->get();

第二,你的描述有錯(cuò)誤。你尋找的不是工廠模式(factory pattern),而是單例模式(singleton pattern),對(duì)象在一次請(qǐng)求生命周期之內(nèi),最多只需要實(shí)例化一次。在Laravel當(dāng)中,需要用到IOC(inversion of control)容器或者說是服務(wù)容器(service container)。像下面這樣:

// 先綁定需要實(shí)例化的對(duì)象或者服務(wù)
$this->app->singleton('FooBar', function ($app) {
    return new FooBar($app['SomethingElse']);
});
// 調(diào)用對(duì)象或服務(wù)有多種方式,比如以下兩種:
// 第一種
$fooBar = $this->app->make('FooBar'); // 顯式解析
$fooBar = $this->app['FooBar']; // 像訪問數(shù)組一樣調(diào)用之前被顯式解析(實(shí)例化)過的對(duì)象或服務(wù)
// 第二種
// 通過類型聲明(type hinting)來自動(dòng)解析,無需顯式解析(實(shí)例化),直接調(diào)用,請(qǐng)參考最后附上的文檔
// 除了單例模式外,當(dāng)然還支持工廠模式,即每次調(diào)用,返回一個(gè)新的實(shí)例,像下面這樣:
$this->app->bind('HelpSpot\API', function ($app) {
    return new HelpSpot\API($app['HttpClient']);
});

以上只是簡(jiǎn)單的摘錄,具體用法,請(qǐng)參考Laravel官方優(yōu)秀的文檔,鏈接如下:
Service Container(IOC容器/服務(wù)容器)

PHP中文網(wǎng)

我司是繼承一個(gè)BaseRepository,BaseRepository中定義

protected function getUserCouponModel($new = false)
{
    if (is_null($this->userCouponModel) || true === $new) {
        $this->userCouponModel = new UserCouponModel();
    }
    return $this->userCouponModel;
}

CouponRepository中

public function create($couponID)
{
    $attributes = [
        'couponID' => $couponID,
    ];

    return $this->getUserCouponModel(true)->create($attributes);
}

Biz中類似,繼承一個(gè)BaseBiz,然后方法這么寫

public function create($fields)
{
    return $this->getCouponRepository()->create($fields);
}

Controller中調(diào)用

$biz = new Biz();
$biz->create($fields);

Controller ---> Biz ---> Repository

淡淡煙草味

我是這么做的,在底層 model 里建立這個(gè)函數(shù)
修改bootstrap/app.php 和 AppServiceProvider.php
具體參考 Service Provider

    static public function load(){
        return app()->make(get_called_class());
    }

在controller 里調(diào)用 Foo::load() 就可以了

最新下載
更多>
網(wǎng)站特效
網(wǎng)站源碼
網(wǎng)站素材
前端模板
關(guān)于我們 免責(zé)申明 意見反饋 講師合作 廣告合作 最新更新
php中文網(wǎng):公益在線php培訓(xùn),幫助PHP學(xué)習(xí)者快速成長(zhǎng)!
關(guān)注服務(wù)號(hào) 技術(shù)交流群
PHP中文網(wǎng)訂閱號(hào)
每天精選資源文章推送
PHP中文網(wǎng)APP
隨時(shí)隨地碎片化學(xué)習(xí)
PHP中文網(wǎng)抖音號(hào)
發(fā)現(xiàn)有趣的

Copyright 2014-2025 http://www.miracleart.cn/ All Rights Reserved | php.cn | 湘ICP備2023035733號(hào)