arrilot / bitrix-models
Requires
- php: >=5.6.4
- illuminate/pagination: ^5.4,<5.8
- illuminate/support: ^5.4,<5.8
Requires (Dev)
- mockery/mockery: ~1
- phpunit/phpunit: ^5.0
Suggests
- arrilot/bitrix-blade: To render pagination views using ->links()
- illuminate/database: ^5.4,<5.8 to use Eloquent models
- illuminate/events: ^5.4,<5.8 to use events in Eloquent models
- dev-master
- 0.8.0
- 0.7.22
- 0.7.21
- 0.7.20
- 0.7.19
- 0.7.18
- 0.7.17
- 0.7.16
- 0.7.15
- 0.7.14
- 0.7.13
- 0.7.12
- 0.7.11
- 0.7.10
- 0.7.9
- 0.7.8
- 0.7.7
- 0.7.6
- 0.7.5
- 0.7.4
- 0.7.3
- 0.7.2
- 0.7.1
- 0.7.0
- 0.6.13
- 0.6.12
- 0.6.11
- 0.6.10
- 0.6.9
- 0.6.8
- 0.6.7
- 0.6.6
- 0.6.5
- 0.6.4
- 0.6.3
- 0.6.2
- 0.6.1
- 0.6.0
- 0.5.4
- 0.5.3
- 0.5.2
- 0.5.1
- 0.5.0
- 0.4.0
- 0.3.7
- 0.3.6
- 0.3.5
- 0.3.4
- 0.3.3
- 0.3.2
- 0.3.1
- 0.3.0
- 0.2.5
- 0.2.4
- 0.2.3
- 0.2.2
- 0.2.1
- 0.2.0
- 0.1.2
- 0.1.1
- 0.1.0
This package is auto-updated.
Last update: 2023-01-17 12:28:50 UTC
README
该包不再活跃维护
原因是我们不再在我们的项目中使用Bitrix。如果您对此项目感兴趣并希望维护它 - 分支它并在本存储库中创建一个Issue,以便我们将链接放在这里。
分支
Bitrix模型
简介
此包将Model Layer引入Bitrix。此层逻辑上由两部分组成
- 为Bitrix实体创建的模型(以下将称为“Bitrix模型”),通过Bitrix的API(如
CIBlockElement
等)工作,并作为其上层构建。从外部来看,这个上层构建类似于Eloquent
。 - 用于任意表的模型,通过
illuminate/database
(尤其是Eloquent
)工作。
安装
composer require arrilot/bitrix-models
- 在
init.php
中注册包 -Arrilot\BitrixModels\ServiceProvider::register();
使用Bitrix模型
以下模型可用于继承
Arrilot\BitrixModels\Models\ElementModel Arrilot\BitrixModels\Models\SectionModel Arrilot\BitrixModels\Models\UserModel Arrilot\BitrixModels\Models\D7Model
以下我们将以ElementModel(信息块元素的模型)为例,其他实体的API几乎相同。
ElementModel完全支持第二版信息块(存储属性在单独的表中)。第一版可能由于CIBlockElement::GetList()的工作方式而无法正常工作。最大的问题是:如果信息块有多个属性,那么limit()、take()和first()的请求将无法正常工作,并且会得到比需要的更少的元素,并且不会得到完整的多个属性集合。如果您仍然打算使用第一版信息块与ElementModel一起使用,则必须在模型类中设置const IBLOCK_VERSION = 1;
创建一个商品信息块的模型。
<?php use Arrilot\BitrixModels\Models\ElementModel; class Product extends ElementModel { /** * Corresponding iblock id. * * @return int */ const IBLOCK_ID = 1; }
要使用模型,只需在常量中设置信息块的ID。对于用户来说,这也不是必需的。
如果您不想绑定到信息块ID,可以在模型中重写
public static iblockId()
方法并从该方法获取信息块ID,例如按代码。这提供了更大的灵活性,但您可能需要额外的数据库查询。
我们将使用我们的Product类作为静态和动态上下文。
添加产品
// $fields - массив, аналогичный передаваемому в CIblockElement::Add(), но IBLOCK_ID в нём можно не указывать. $product = Product::create($fields);
注意:如果在以后使用中使用了$product字段,建议立即使用新的数据库查询更新对象。这是由于CIblockElement::Add()和CIblockElement::GetList()中的字段格式在100%上不匹配。这样做的方法是
$product = Product::create($fields) $product->refresh();
更新
// вариант 1 $product['NAME'] = 'Новое имя продукта'; $product->save(); // вариант 2 $product->update(['NAME' => 'Новое имя продукта']);
不查询数据库进行模型实例化。
对于一些操作,不需要从数据库获取信息,只需要对象的ID。在这种情况下,只需实例化模型对象,并在构造函数中传递标识符。
$product = new Product($id); //теперь есть возможно работать с моделью, допустим $product->deactivate();
从数据库获取对象字段
$product = new Product($id); // метод `load` обращается к базе, только если информация еще не была получена. $product->load(); // Если мы хотим принудительно обновить информацию из базы даже если она уже была получена ранее $product->refresh(); // После любого из этих методов, мы можем работать с полученными полями (`echo $product['CODE'];`) //Для текущего пользователья есть отдельный хэлпер $user = User::current(); // В итоге мы получаем инстанс User с заполненными полями. // Сколько бы раз мы не вызывали `User::current()` в рамках работы скрипта, запрос в базу происходит только один раз - первый. // `User::freshCurrent()` - то же самое, но получает данные из базы каждый раз.
描述的方法将数据库中的数据保存在类模型实例内部。模型对象实现了ArrayAccess,因此可以像处理数组一样处理它们。
$product->load(); if ($product['CODE'] === 'test') { $product->deactivate(); }
将模型转换为数组/json。
$array = $product->toArray(); $json = $product->toJson();
默认情况下,模型的所有字段都可在数组中访问,这并不总是希望的。模型有特殊的属性protected $visible = [];
和protected $hidden = [];
,可以通过这些属性来构建白名单/黑名单字段,以将模型转换为数组/json。
获取数据库信息
使用模型的最常见场景是从数据库获取元素/列表。用于构建查询的是“Fluent API”,它内部使用标准的Bitrix API。
开始构建查询使用静态方法::query()
。此方法返回一个查询构建器对象(ElementQuery
、SectionQuery
或UserQuery
),通过它来构建查询链。
简单示例
$products = Product::query()->select('ID')->getList();
实际上,这个形式主要是为了理解,有一个更方便的版本,它使用__callStatic
将控制权传递给查询对象。
$products = Product::select('ID')->getList();
任何查询链都必须以以下方法之一结束
->getList()
- 获取对象集合(参见 https://laravel.net.cn/docs/master/collections)。默认情况下,每个元素的键是其ID。->getById($id)
- 根据其ID获取对象。->first()
- 获取符合查询参数的一个(第一个)对象。->count()
- 获取对象数量。->paginate() 或 ->simplePaginate()
- 获取分页列表及其元数据(参见 https://laravel.net.cn/docs/master/pagination)- 针对单个实体的方法:
->getByLogin($login)
和->getByEmail($email)
- 获取具有给定登录名/email的第一个用户。->getByCode($code)
和->getByExternalId($id)
- 获取第一个元素或分类信息,通过CODE/EXTERNAL_ID
管理选择
->sort($array)
- 等同于$arSort
(CIBlockElement::GetList
的第一个参数)
示例
->sort(['NAME' => 'ASC', 'ID' => 'DESC'])
->sort('NAME', 'DESC') // = ->sort(['NAME' => 'DESC'])
->sort('NAME') // = ->sort(['NAME' => 'ASC'])
->filter($array)
- 等同于$arFilter
->navigation($array)
->select(...)
- 等同于$arSelect
示例
->select(['ID', 'NAME'])
->select('ID', 'NAME')
select()
支持两个附加值 - 'FIELDS'
(选择所有字段),'PROPS'
(选择所有属性)。对于用户也可以指定 'GROUPS'
(在查询中添加用户组)。对于 ElementModel
的默认值是 ['FIELDS', 'PROPS']
->limit($int)
、->take($int)
、->page($int)
、->forPage($page, $perPage)
- 用于导航
Fetch和GetNext
默认情况下,在遍历从数据库获取的元素/部分/用户时,使用高效的方法 ->Fetch()
。与 ->GetNext()
不同,它不会将数据转换为html安全格式,也不会将 DETAIL_PAGE_URL、SECTION_PAGE_URL 转换为元素和类别的真实网址。如果查询结果需要这些转换,则可以切换到该方法。
-
可以立即切换整个模型,只需为其设置属性。
public static $fetchUsing = 'GetNext'; // полная форма, если нужно менять параметры. public static $fetchUsing = [ 'method' => 'GetNext', 'params' => [true, true], ];
-
也可以只为单个请求切换。
Products::query()->filter(['ACTIVE' => 'Y'])->fetchUsing('GetNext')->getList()` // вместо строки `'GetNext'` можно как и в первом случае использовать массив.
一些额外的注意事项
- 为了限制选择,添加了别名
limit($value)
(对应于nPageSize
)和page($num)
(对应于iNumPage
)。 - 在API的一些地方,与Bitrix本身相比更友好。例如,在按用户筛选时,不一定要使用
'GROUP_IDS'
。在传递'GROUP_ID'
(这正是Bitrix需要的键,例如在创建用户时)或'GROUPS'
时,结果将是相同的。 - 在创建或更改信息块元素和部分时,Bitrix会重建搜索索引,并允许在特定的
Add/Update
调用中跳过重建,以提高性能。在模型中,您可以通过直接在模型类中设置protected static $updateSearch = false;
或在添加/更新之前调用单独的静态方法Product::setUpdateSearch(false)
来实现相同的效果。 - 对于 CIBlockElement::Add/Update,也可以用相同的方式管理 $bWorkFlow 和 $bResizePictures 标志。
查询作用域
可以通过在模型中添加 "query scopes" 来扩展查询构建器。为此,需要创建一个以 scope
开头的方法。
包中已经存在一个 "query scope" 的示例。
/** * Scope to get only active items. * * @param BaseQuery $query * * @return BaseQuery */ public function scopeActive($query) { $query->filter['ACTIVE'] = 'Y'; return $query; } ... $products = Product::filter(['SECTION_ID' => $secId]) ->active() ->getList();
在 "query scopes" 中也可以传递额外的参数。
/** * @param ElementQuery $query * @param string|array $category * * @return ElementQuery */ public function scopeFromSectionWithCode($query, $category) { $query->filter['SECTION_CODE'] = $category; return $query; } ... $users = Product::fromSectionWithCode('sale')->getList();
这些作用域已经存在于包中,可以开始使用。
停止操作
有时需要从查询作用域中停止数据库选择。为此,只需返回 false 即可。示例
public function scopeFromCategory($query, $category) { if (!$category) { return false; } $query->filter['SECTION_CODE'] = $category; return $query; } ...
结果不会对数据库进行查询 - getList()
将返回空集合,getById()
将返回 false,而 count()
将返回 0。
也可以通过手动调用方法
->stopQuery()
达到相同的效果。
查询缓存
对于所有上述Bitrix模型,都有一个简单的内置缓存机制。只需在调用链中添加 ->cache($minutes)->
即可,然后数据库选择的结果将缓存指定的分钟数。示例:$products = Products::query()->cache(30)->filter(['ACTIVE' => 'Y'])->getList()
在幕后,缓存使用的是d7 Bitrix的标准机制。缓存键取决于模型和所有查询参数。
访问器
有时需要在从数据库中选择数据并从模型获取数据之间修改数据。为此,使用访问器。同样,对于 "query scopes",要添加访问器,需要向相应的模型添加方法。
方法命名的规则是 $methodName = "get".camelCase($field)."Attribute"
。示例
public function getXmlIdAttribute($value) { return (int) $value; } // теперь в $product['XML_ID'] всегда будет целочисленное значение
需要谨慎使用此方法,因为原始值将不可用。
也可以为不存在的(虚拟)字段创建访问器,例如
public function getFullNameAttribute() { return $this['NAME']." ".$this['LAST_NAME']; } ... echo $user['NAME']; // John echo $user['LAST_NAME']; // Doe echo $user['FULL_NAME']; // John Doe
为了使这样的虚拟访问器在 toArray() 和 toJson() 中显示,必须在模型的 $appends 字段中显式指定它们。
protected $appends = ['FULL_NAME'];
语言访问器
对于多语言网站,通常的做法是为每种语言创建一个属性,例如,UF_TITLE_RU,UF_TITLE_BY。在这种情况下,可以为这样的字段创建一个访问器。
// используем далее $section['UF_TITLE'];
public function getUfTitleAttribute()
{
return $this['UF_TITLE_' . strtoupper(LANGUAGE_ID)];
}
// используем далее $element['PROPERTY_TITLE'];
public function getPropertyTitleAttribute()
{
return $this['PROPERTY_TITLE_' . strtoupper(LANGUAGE_ID) . '_VALUE'];
}
由于这些访问器类型相同并且有污染模型的不良特性,因此可以为他们使用特殊的简短语法。
class Product extends ElementModel
{
protected $languageAccessors = [
'PROPERTY_TITLE',
'PROPERTY_FOO'
];
}
模型事件(Model Events)
事件允许在模型的生命周期中的不同点插入代码。例如,在创建元素时自动设置字符代码。模型事件不使用Bitrix的事件模型(无论是旧内核还是D7),仅涉及模型内部发生的事情。使用Bitrix事件覆盖了更多用例。
事件处理器通过在模型类中重定义相应的方法来设置。
class News extends ElementModel { /** * Hook into before item create or update. * * @return mixed */ protected function onBeforeSave() { $this['CODE'] = CUtil::translit($this['NAME'], "ru"); } /** * Hook into after item create or update. * * @param bool $result * * @return void */ protected function onAfterSave($result) { // } }
其他事件处理器的签名与上面所述相同。
可用的事件列表
onBeforeCreate
- 在添加记录之前onAfterCreate(bool $result)
- 在添加记录之后onBeforeUpdate
- 在更新记录之前onAfterUpdate(bool $result)
- 在更新记录之后onBeforeSave
- 在添加或更新记录之前onAfterSave(bool $result)
- 在添加或更新记录之后onBeforeDelete
- 在删除记录之前onAfterDelete(bool $result)
- 在删除记录之后
如果从onBefore...()
处理器返回return false;
,则后续操作将被取消。在处理器中可以通过当前模型的属性获取额外信息。例如,在onBefore...()
处理器中,可以通过$this->fields
访问所有字段。在所有onAfter...()
中,可以通过$this->eventErrors
访问错误数组;在onBeforeUpdate()
和onBeforeSave()
中,可以通过$this->fieldsSelectedForSave
访问要更新的字段的键数组。
D7 Model
与之前模型相比,《D7Model》有些特别。它使用D7作为后端而不是旧的GetList等,可以通过它来处理D7的普通实体和块。
块示例
class Subscriber extends D7Model { public static function tableClass() { $hlBlock = HighloadBlockTable::getRowById(1); return HighloadBlockTable::compileEntity($hlBlock)->getDataClass(); } }
获取块类的逻辑可以是任何形式,但重要的是不要忘记编译它,否则它将无法工作。最方便的方法是使用辅助包https://github.com/arrilot/bitrix-iblock-helper/。有了它,我们得到以下结果
class Subscriber extends D7Model { public static function tableClass() { return highloadblock_class('app_subscribers'); } }
如果我们不处理块,而是处理完整的D7 ORM实体,那么我们只需在此方法中返回该实体的完整类名即可。D7Model的调用链和命名方法与之前模型相同。我们传递给这些方法的任何内容都将传递到D7。
获取所有名为John的订阅者的示例,并缓存5分钟
$subscribers = Subscriber::query()->cache(5)->filter(['=NAME'=>'John])->getList();
完整的方法列表如下
/** * static int count() * * D7Query methods * @method static D7Query runtime(array|\Bitrix\Main\Entity\ExpressionField $fields) * @method static D7Query enableDataDoubling() * @method static D7Query disableDataDoubling() * @method static D7Query cacheJoins(bool $value) * * BaseQuery methods * @method static Collection getList() * @method static D7Model first() * @method static D7Model getById(int $id) * @method static D7Query sort(string|array $by, string $order='ASC') * @method static D7Query order(string|array $by, string $order='ASC') // same as sort() * @method static D7Query filter(array $filter) * @method static D7Query addFilter(array $filters) * @method static D7Query resetFilter() * @method static D7Query navigation(array $filter) * @method static D7Query select($value) * @method static D7Query keyBy(string $value) * @method static D7Query limit(int $value) * @method static D7Query offset(int $value) * @method static D7Query page(int $num) * @method static D7Query take(int $value) // same as limit() * @method static D7Query forPage(int $page, int $perPage=15) * @method static \Illuminate\Pagination\LengthAwarePaginator paginate(int $perPage = 15, string $pageName = 'page') * @method static \Illuminate\Pagination\Paginator simplePaginate(int $perPage = 15, string $pageName = 'page') * @method static D7Query stopQuery() * @method static D7Query cache(float|int $minutes) */
有关详细信息,请参阅vendor/arrilot/bitrix-models/src/Models/D7Model.php
和vendor/arrilot/bitrix-models/src/Queries/D7Query.php
模型之间的关系(Relations)
除了处理单独的Bitrix模型之外,还可以在模型之间建立关系,这使得它们可以通过主要数据对象轻松访问。例如,商品与商品问题相关联。通过声明这种关系,您可以使用表达式$product->questions获取模型问题对象,它返回问题的信息,以Question类(BaseBitrixModel的子类)对象的集合形式。
声明关系
/** * Class Product * * @property Brand $brand * @property ProductQuestion $questions * @property Storage $storages */ class Product extends ElementModel { ... /** * ID Brand записан в текущую модель в свойтво PROPERTY_BRAND_VALUE (не множественное) * (у товара может быть только один бренд, но у бренда много товаров) */ public function brand() { return $this->hasOne(Brand::class, 'ID', 'PROPERTY_BRAND_VALUE'); } /** * У ProductQuestion в свойтве PROPERTY_PRODUCT_VALUE записан ID текущей модели * (у товара может быть много вопросов, но вопрос относится только к одному товару) * * Но это будет так же работать, если PROPERTY_PRODUCT_VALUE будет множественным */ public function questions() { return $this->hasMany(ProductQuestion::class, 'PROPERTY_PRODUCT_VALUE', 'ID'); } /** * ID Storage записан в текущую модель в свойтво PROPERTY_STORAGE_VALUE (множественное) * (у товара может быть много складов, на складе может быть много товаров) */ public function storages() { return $this->hasMany(Storage::class, 'ID', 'PROPERTY_STORAGE_VALUE'); } }
关系名称对大小写敏感。
在声明关系时,您必须指定以下信息
- 关系的数量:通过调用 hasMany() 方法或 hasOne() 方法来指定。
- 关联类名称:作为 hasMany() / hasOne() 方法的第一个参数指定。
- 两种数据类型之间的关系:第二个参数是外部模型中的字段,第三个参数是内部模型中的字段(默认为 ID)。
- 与其他 ORM 不同,多对多关系不使用中间(pivot)表。相反,使用 Bitrix 的多属性。
访问关联数据
声明关系后,您可以通过关系名称访问关联数据。访问是通过对象的属性完成的。属性名称 = 关联方法名称(但去掉方法括号)
$product = Product::getById(1); // В этот момент используются магические методы и выполняются sql запросы в БД за данными. $product->brand; // Объект класса Brand $product->questions; // Collection объектов класса ProductQuestion // Запросы в базу выполняются лишь один раз. При повторном обращении к переменной возвращаются данные получененные при первом запросе. $product->brand; $product->questions;
延迟和贪婪加载
上面的示例使用了延迟加载(在首次访问时加载数据)。当处理数据数组时,会收到循环查询,产生 n + 1 问题。
$products = Product::getList(); foreach($products as $product) { // Выполняется запрос $product->brand; }
为了避免这种情况,需要使用贪婪加载
// Выполняется один дополнительный запрос который получит все бренды для всех полученных продуктов. $products = Product::query()->with('brand')->getList(); foreach($products as $product) { // Запрос не выполняется $product->brand; }
- with 方法可以多次调用。
- 它接受一个字符串作为参数 - 关联名称或多个字符串/字符串数组
->with('brand', 'questions')
/->with(['brand', 'questions'])
。 - 您可以指定嵌套关系
->with('questions.answers')
(在这种情况下,将立即加载问题和每个问题的答案列表。总共 3 个请求 - 商品,问题,答案)。 - 可以通过回调来修改查询。例如,为了只加载活动问题,并为它们加载答案
->with([ 'questions' => function ($query) { $query->filter(['ACTIVE' => 'Y']) }, 'questions.answers' ])
使用 Eloquent 模型
包的第二部分是 ORM Eloquent 的集成,用于 Bitrix 中的用户表,即手动创建的表,而不是与系统一起提供的表。实际上,这是直接向数据库查询、D7 ORM 和此包中的 D7Model 的替代方案。
通过 Eloquent
,不仅可以处理用户表,还可以处理 Highload 块,这非常方便。在这种情况下,我们与 Highload 块的表一起工作,而无需使用 Bitrix 的任何 API。
值得注意的是,与 Bitrix 不同,Eloquent
使用 PHP 扩展访问 mysql,而不是 mysql/mysqli,而是 PDO。这意味着
- 必须安装和配置 PDO
- 将创建两个数据库连接。
注意:问题:为什么在包中包含 Eloquent,如果已经有 D7Model?哪个更好?回答:选择取决于项目条件和个人偏好。Eloquent 比Bitrix 和 D7Model 中所有内容都更方便且功能更强大,例如,它提供了通过中间表进行的完整模型之间的关联等。另一方面,这是一个较大的外部依赖,有它自己的要求
缺点
安装
首先,需要安装另一个依赖项 - composer require illuminate/database
之后,在 init.php
中添加一行 - Arrilot\BitrixModels\ServiceProvider::registerEloquent();
现在可以创建 Eloquent 模型,继承自 EloquentModel
<?php use Arrilot\BitrixModels\Models\EloquentModel; class Product extends EloquentModel { protected $table = 'app_products'; }
如果表名为 products
(类名称的复数形式),则可以省略 protected $table = 'products';
- 这是 Eloquent 的标准行为。不同之处在于
- 主键是
ID
,而不是id
- 用于创建和更新记录的字段称为
UF_CREATED_AT
和UF_UPDATED_AT
,而不是created_at
和updated_at
如果您决定不在表中添加 UF_CREATED_AT 和 UF_UPDATED_AT 字段,则需要在模型中设置
public $timestamps = false;
通过 Eloquent 使用高负载块
假设我们创建了一个名为 Brands
的高负载块,为它指定了 brands
表,并添加了 UF_NAME
属性。那么它的模型类将如下所示
<?php use Arrilot\BitrixModels\Models\EloquentModel; class Brand extends EloquentModel { public $timestamps = false; }
要向其中添加新记录,只需要以下代码
$brand = new Brand(); $brand['UF_NAME'] = 'Nike'; $brand->save(); // либо даже такого если настроены $fillable поля. $brand = Brand::create(['UF_NAME' => 'Nike']);
要充分利用 Eloquent 模型,重要的是要熟悉该 ORM 的官方文档 (链接再次)
最后要注意的是,尽管 Bitrix 模型和 Eloquent 模型的 API 非常相似(这在很大程度上是因为 Bitrix 模型是在 Eloquent 的影响下开发的),但它们确实是不同的事物,并且内部是完全独立的。不能例如创建 Eloquent 模型和 Bitrix 模型的关联。
Highload 块和 Eloquent 模型的多个属性
高负载块中的多个属性实现得有些巧妙。数据存储在两个地方
- 直接在 Highload 块的表中以序列化形式。
- 在用于该属性的一个附加表中。幸运的是,该包能够很好地解决这个问题。添加多个属性时,只需将此属性的代码添加到模型的
$multipleHighloadBlockFields
字段数组中即可。例如public $multipleHighloadBlockFields = ['UF_SOME_MULTIPLE_FIELD'];
然后 $model['UF_SOME_MULTIPLE_FIELD']
将返回反序列化的数组- 要添加/更新字段值,也只需将数组放在
$model['UF_SOME_MULTIPLE_FIELD']
中,无需手动序列化。 - 添加/更新字段值时,更改将自动应用于辅助表。无需手动更改。要使最后一点生效,需要安装额外的依赖项 -
composer require illuminate/events
。没有这个依赖项,辅助表将不会更新。关于它的更多信息将在下一段中介绍。
Eloquent 模型中的事件
Eloquent 有所谓的 模型事件 / Model events,它允许在模型的某个时刻进行干预。总的来说,它与 Bitrix 的 OnBeforeIblockElementUpdate
等事件非常相似。如果您需要它们,则还需要安装 illuminate/database
和 illuminate/events
依赖项。
composer require illuminate/events
查询构建器
在连接 Eloquent 时,我们免费获得 Laravel 的 Query Builder,它位于 https://laravel.net.cn/docs/master/queries,它非常有用,如果需要直接与数据库交互而无需通过模型层进行抽象。它比 $DB->Query()
和其他方法更方便、更安全。
通过全局可访问的类 DB
进行构建器的工作。例如,向 HL 块添加品牌元素将如下所示
DB::table('brands')->insert(['UF_NAME' => 'Nike']);
分页导航 (pagination)
Bitrix-模型和Eloquent-模型都支持->paginate()
和->simplePaginate()
(参见https://laravel.net.cn/docs/master/pagination)。为了然后通过->links()
显示分页导航,需要
- 安装https://github.com/arrilot/bitrix-blade/
- 将默认视图从https://github.com/laravel/framework/tree/master/src/Illuminate/Pagination/resources/views复制到
local/views/pagination
之后,可以修改这些视图或创建新的视图。
连接到多个数据库,详细配置连接。
默认情况下,连接到数据库使用的是与Bitrix一起工作的标准配置。例如,它可以看起来像这样(文件.settings.php
):
'connections' => [ 'value' => [ 'default' => [ 'className' => '\\Bitrix\\Main\\DB\\MysqliConnection', 'host' => 'localhost', 'database' => 'db', 'login' => 'login', 'password' => 'password', 'options' => 2, ], ], 'readonly' => true, ]
为了能够使用Eloquent的全部功能,需要在.settings.php
文件中添加一个描述连接的数组bitrix-models.illuminate-database
[ ... 'bitrix-models.illuminate-database' => [ 'value' => [ 'default' => 'mysql', 'connections' => [ 'mysql' => [ 'driver' => 'mysql', 'url' => getenv('DB_MYSQL_URL'), 'host' => getenv('DB_MYSQL_HOST'), 'port' => getenv('DB_MYSQL_PORT'), 'database' => getenv('DB_MYSQL_DATABASE'), 'username' => getenv('DB_MYSQL_USERNAME'), 'password' => getenv('DB_MYSQL_PASSWORD'), 'unix_socket' => getenv('DB_MYSQL_SOCKET'), 'charset' => 'utf8', 'collation' => 'utf8_unicode_ci', 'prefix' => '', 'prefix_indexes' => true, 'strict' => false, 'engine' => null, 'options' => [], ], 'mysql_2' => [ ... ], ], ], 'readonly' => true, ], ]
重要!如果指定了bitrix-models.illuminate-database
数组,那么Eloquent的数据库连接配置只从这个数组中获取,而标准配置将被忽略。
更多配置连接的示例(connections):https://github.com/laravel/laravel/blob/5.7/config/database.php
D7Model/EloquentModel中的元素活动状态
在Bitrix的信息块中有一个ACTIVE = 'Y'/'N'字段,根据这个字段进行过滤非常常用。在HiLoad块和自定义表中默认没有这样的字段,但该包提供了一个帮助创建此类功能的trait。它是如何工作的
-
在表/HiLoad块中添加字段UF_DEACTIVATED_AT,类型为datetime。
-
在D7Model/EloquentModel中添加trait
use \Arrilot\BitrixModels\Models\Traits\DeactivationTrait;
-
现在在模型中可用的方法有
3.1.
$model->deactivate()
和$model->activate()
- 在数据库中禁用或激活元素。3.2.
$model->markForDeactivation()
和$model->markForActivation()
- 与上面相同,但只更改php变量,不执行->save()。如果需要激活时在表中进行其他更改,并且不想执行额外的数据库查询,这很有用。3.3. 范围
->active()
和->deactivated()
。例如SomeD7Model::query()->active()->getList()
。