Maison > Questions et réponses > le corps du texte
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次。
目前在网上看到一种办法,就是在Repositories
Je 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 ?
漂亮男人2017-05-16 16:55:44
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.
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.
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);
}
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
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
阿神2017-05-16 16:55:44
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#/
高洛峰2017-05-16 16:55:44
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)
PHP中文网2017-05-16 16:55:44
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 --->
淡淡烟草味2017-05-16 16:55:44
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