Comment réutiliser des modèles dans Laravel
伊谢尔伦
伊谢尔伦 2017-05-16 16:53:44
0
5
774

Notre entreprise utilise actuellement Laravel开发项目,同时还增加了Biz层和Repositories层,来实现业务逻辑封装,反而model里面什么代码都没有。
Controller里写代码的时候,尝尝困扰我的问题是如果复用Biz对象,Repositories对象和Model对象。
以前用Yii开发项目的时候,有一个工厂模式,所以调用Model的时候,基本都不new, qui s'appelle octets en utilisant XXX::model() Il suffit qu'un objet soit nouveau une fois, ce qui peut effectivement économiser de la mémoire.
Code contrôleur :

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

Comme c'est simple, non ?

Dans Laravel, Model ne semble pas avoir de fabrique. Pour l'appeler, une instance est requise. Si Repositories encapsule 5 méthodes, chacune l'est. utilisé Model, puis j'ai appelé ces 5 méthodes dans Controller, et Model était nouveau cinq fois. Laravel里,Model好像没有工厂,要调用,都需要实例,假如Repositories里面封装了5个方法,每个都使用了Model,那么我在Controller里调用了这5个方法,Model就被new了5次。
目前在网上看到一种办法,就是在RepositoriesJe vois actuellement un moyen sur Internet, qui consiste à injecter l'objet Model dans le constructeur de Repositories et à le mettre dans les variables membres privées des Repositories. De cette façon, les cinq méthodes peuvent appeler le. variables privées de la classe actuelle. Mais c'est difficile à utiliser. Lorsque vous écrivez du code dans Controller, vous devez écrire comme ceci :

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

Vous devez écrire ceci dans les référentiels :

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

Il y a un objet Biz的时候,还必须传入Repositories dans new, et l'espace de noms est encore long. J'épelle essentiellement des chaînes et l'efficacité de l'écriture du code est extrêmement faible.

Je voudrais vous demander comment résolvez-vous le problème de la réutilisation des classes de couches logiques telles que Model lors du développement de projets avec Laravel ?

伊谢尔伦
伊谢尔伦

小伙看你根骨奇佳,潜力无限,来学PHP伐。

répondre à tous(5)
漂亮男人

Préface 0x0

Question intéressante, Yii est également reconnu dans l'industrie comme un framework plus performant que Laravel. Je voulais donc examiner l'implémentation spécifique des deux principaux frameworks uniquement à partir de la structure d'ActiveRecord.

0x1 Framework éloquent pour Laravel

Il est facile d'utiliser des requêtes relationnelles dans Laravel :

    $user = User::find(1);

Je n'ai pas trouvé la méthode find dans la classe User, WTF, que s'est-il passé ! ?

La classe de base de User est Model, qui utilise des appels statiques, donc la méthode magique __callStatic de Model sera appelée :

    public static function __callStatic($method, $parameters)
    {
        // $method = 'find';
        // $parameters = [1];
        
        // 实例化当前类,即 User 模块
        $instance = new static;
        // 调用当前实例的 find 方法
        return call_user_func_array([$instance, $method], $parameters);
    }

En fait, il s'agit d'appeler à nouveau la méthode magique __call :

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

        $query = $this->newQuery();

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

En remontant à la source, nous avons constaté que la méthode find provient en fait d'IlluminateDatabaseEloquentBuilder, et que cette classe utilise en interne l'implémentation d'IlluminateDatabaseQueryBuilder.

Attendez une minute, quelle est la différence entre IlluminateDatabaseEloquentBuilder et IlluminateDatabaseQueryBuilder ?

En fait, EloquentBuilder est une encapsulation supplémentaire de QueryBuilder pour mieux implémenter la requête d'objet relationnel.

Donc, le processus réel est :

En d'autres termes, chaque fois que vous appelez statiquement la méthode Model, le Modèle sera instancié et le processus sera terminé.

0x2 CActiveRecord dans Yii 1.1

Puisque le questionneur utilise la méthode model, il devrait s'agir de la version 1.1. Le module hérite de CActiveRecord (dans Yii2, il hérite de YiidbActiveRecord).

D'accord, les gars, utilisez maintenant Yii pour implémenter une requête relationnelle, définissez d'abord :

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

Enquête :

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

Évidemment, l'objet requête vient du modèle, voyons comment la classe parent implémente cette fonction :

    public static function model($className=__CLASS__)
    {
        // 如果已经实例化了则直接返回该实例
        if(isset(self::$_models[$className]))
            return self::$_models[$className];
        else
        {
            // 初始化,并将保存当前实例
            $model=self::$_models[$className]=new $className(null);
            $model->attachBehaviors($model->behaviors());
            return $model;
        }
    }
La méthode

findAllByPk est directement encapsulée dans CActiveRecord :

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

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

Le processus est donc :

Injection de dépendances 0x3 à l'aide de Laravel

Dans des circonstances normales (un constructeur sans paramètre ou des paramètres injectés ont été configurés), Laravel l'instanciera automatiquement pour vous :

<?php namespace App\Repositories;

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

Vous pourrez ainsi réutiliser le même objet facilement :

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();
    }
}

Après avoir implémenté l'entrepôt, devez-vous l'instancier manuellement :

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

Non, cela n'est pas conforme à la philosophie de Laravel, vous pouvez le faire aussi simplement que :

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

Oui, c'est vrai, vous n'avez pas besoin de construire manuellement, de transmettre l'instance User, etc., tout n'est qu'une simple injection automatique. Et la personne qui a posé la question a remarqué qu'un espace de noms est utilisé ici, vous ne devez donc l'utiliser qu'une seule fois. (Bien sûr, si vous ne voulez pas épeler un espace de noms aussi long, alors il est temps pour vous de passer à un IDE. Vous pouvez utiliser Alt + Entrée pour importer rapidement dans PhpStorm

0x4 Enfin

Pour la question des frais généraux statiques et non statiques, il existe une discussion sur StackOverflow : http://stackoverflow.com/questions/14727...

Donc en dernière analyse, cela dépend toujours des besoins de l'entreprise 23333

阿神

Grâce à l'injection de dépendances
Il peut être injecté directement dans le contrôleur
Vous pouvez lire cet article
http://slides.com/howtomakeaturn/model#/

小葫芦

Je suppose que vous ne savez pas encore grand-chose sur Laravel.

Premièrement, le modèle de Laravel est un modèle qui ne nécessite pas d'instanciation explicite. La méthode d'appel est la suivante (extraite de la documentation officielle) :

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

Deuxièmement, votre description est fausse. Ce que vous recherchez n'est pas le modèle d'usine, mais le modèle singleton. L'objet ne doit être instancié qu'une seule fois au cours du cycle de vie d'une requête. Dans Laravel, vous devez utiliser un conteneur IOC (inversion de contrôle) ou un conteneur de service. Comme ça :

// 先绑定需要实例化的对象或者服务
$this->app->singleton('FooBar', function ($app) {
    return new FooBar($app['SomethingElse']);
});
// 调用对象或服务有多种方式,比如以下两种:
// 第一种
$fooBar = $this->app->make('FooBar'); // 显式解析
$fooBar = $this->app['FooBar']; // 像访问数组一样调用之前被显式解析(实例化)过的对象或服务
// 第二种
// 通过类型声明(type hinting)来自动解析,无需显式解析(实例化),直接调用,请参考最后附上的文档
// 除了单例模式外,当然还支持工厂模式,即每次调用,返回一个新的实例,像下面这样:
$this->app->bind('HelpSpot\API', function ($app) {
    return new HelpSpot\API($app['HttpClient']);
});

Ce qui précède n'est qu'un simple extrait. Pour une utilisation spécifique, veuillez vous référer à l'excellente documentation officielle de Laravel. Le lien est le suivant :
Conteneur de service (conteneur IOC/conteneur de service)

.
洪涛

Notre entreprise hérite d'un BaseRepository, qui est défini dans BaseRepository

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

Référentiel de coupons

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

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

Similaire en Biz, héritez d'un BaseBiz, puis écrivez la méthode comme ceci

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

Contrôleur

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

Contrôleur ---> Biz --->

淡淡烟草味

C'est ce que j'ai fait, créer cette fonction dans le modèle sous-jacent
Modifier bootstrap/app.php et AppServiceProvider.php
Pour plus de détails, veuillez vous référer au fournisseur de services

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

Appelez simplement Foo::load() dans le contrôleur

Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal