Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Bitrix Models Laravel Package

arrilot/bitrix-models

A lightweight Eloquent-style ORM for Bitrix: map infoblocks and highload blocks to PHP model classes, query them through a fluent builder, and use familiar ActiveRecord patterns. It makes Bitrix data access cleaner and more maintainable for PHP projects.

Deep Wiki
Context7

Getting Started

Install via Composer alongside an existing Bitrix project:

composer require arrilot/bitrix-models

Look first at the package README and the src/Models directory. The four base classes you will live in are ElementModel, SectionModel, UserModel, and FileModel. Everything else (Query, relations, caching) is layered on top of those.

Minimal first use case — expose one infoblock as a model:

use Arrilot\BitrixModels\Models\ElementModel;

class News extends ElementModel
{
    const IBLOCK_ID = 1;

    // Whitelist the fields this model exposes.
    public static function getMap(): array
    {
        return [
            'ID'           => 'ID',
            'NAME'         => 'NAME',
            'ACTIVE'       => 'ACTIVE',
            'PREVIEW_TEXT' => 'PREVIEW_TEXT',
            'DETAIL_TEXT'  => 'DETAIL_TEXT',
        ];
    }
}

Then query it like Eloquent:

$items = News::query()
    ->filter(['ACTIVE' => 'Y'])
    ->sort(['SORT' => 'ASC'])
    ->limit(10)
    ->get();

$one = News::find(42);
echo $one->NAME;

The mental model is: one model class per infoblock (or section/user/file pool), getMap() maps Bitrix field names to model attributes, and query() returns a builder that ultimately calls CIBlockElement::GetList (or the section/user equivalent). The package buys you object hydration, relations, and a fluent API; it does not replace Bitrix's storage, permissions, or cache components.

Implementation Patterns

One model per entity, scopes for reusable filters. Encapsulate recurring filters as named builder methods so templates and components don't repeat raw filter arrays:

class News extends ElementModel
{
    const IBLOCK_ID = 1;

    public static function active()
    {
        return static::query()->filter(['ACTIVE' => 'Y']);
    }
}

$news = News::active()->sort(['ACTIVE_FROM' => 'DESC'])->get();

Relations instead of hand-rolled GetList calls. Define hasOne/hasMany/belongsTo between models (e.g. an element belongs to a SectionModel, or references a UserModel or FileModel) and eager-load with with() when rendering lists. This is where the package earns its keep: without with(), each relation is a separate CIBlockElement::GetList, and a 50-item list becomes 50+ queries.

Model as the write boundary. Create and update through the model rather than calling CIBlockElement::Add/Update directly, so getMap() stays the single source of truth for which fields the app is allowed to touch:

$news = new News();
$news->NAME = 'Hello';
$news->ACTIVE = 'Y';
$news->save();

Cache at the query level and invalidate deliberately. Query caching (typically ->cache($seconds)) memoizes the underlying Bitrix call. Because the cache backend is usually Bitrix's own managed cache, you still need to clear it when content changes — hook model saves or use Bitrix's infoblock cache-clearing events, and don't assume the model invalidates for you.

Keep models thin, push display logic into accessors. Use accessors/mutators for derived attributes (image paths from FileModel, formatted dates, property arrays) so templates only see plain attributes. This is also where you normalize Bitrix's habit of returning arrays for what is conceptually a scalar.

Component/template integration. Instantiate models inside a component, pass hydrated collections into the template, and let the template call accessors. This keeps CIBlockElement::GetList parameter arrays out of .php templates, which is the main day-to-day win over raw Bitrix.

Mixed D7/legacy code. The models wrap the legacy CIBlock* API, so they interoperate fine with D7 code — but don't expect D7 EOrm entities to participate in with()/relation loading. Pick one style per module.

Gotchas and Tips

  • The package is archived (last release mid-2020). Pin the version, vendor a fork if you need fixes, and treat Illuminate/PHP version compatibility as a live risk on modern stacks. Check composer.json constraints before adding it to a PHP 8 project.
  • Bitrix filter operators leak through. filter() passes keys through to CIBlockElement::GetList, so ['>ID' => 100], [ '%NAME' => 'foo'], ['!ACTIVE' => 'N'] behave exactly as in Bitrix. This is powerful but undocumented in the package — learn Bitrix's filter syntax, not the package's.
  • Property values are inconsistent. PROPERTY_* vs PROPERTY_*_VALUE, and multi-value properties returning arrays vs scalars, is a classic source of "works on one element, breaks on another" bugs. Normalize in accessors and test with both single- and multi-value properties.
  • Lazy loading is silent. $element->section->NAME in a loop issues a query per element with no warning. Audit list-rendering code for missing with().
  • Permissions and CHECK_PERMISSIONS. The model runs as the current user unless you explicitly override it. Admin-panel testing can mask permission bugs that surface for anonymous users — verify with a real guest session.
  • Bitrix component cache is separate from query cache. Clearing the model cache does not clear component cache, and vice versa. Document which cache layer is responsible for what; stale content after edits almost always comes from this gap.
  • save() semantics. Know whether a save is an Add or an Update, which fields are written, and what happens to fields omitted from getMap() (they're typically untouched, but confirm — silent field loss is the worst failure mode here).
  • Debugging queries. There's no query log out of the box; wrap calls with Bitrix's debug/$DB timing or Xdebug, and confirm the generated GetList parameters by temporarily dumping the query's toArray()/params rather than guessing.
  • Extension points are the subclasses. Override getMap(), the query class, or the base Model methods in your own abstract base model (e.g. AppModel extends ElementModel) rather than editing package files — this is the only sane way to survive a fork or patch.
  • No test fixtures. There's no in-memory driver. Either test against a seeded test infoblock or mock the CIBlock* static calls; don't expect the package to make Bitrix unit-testable on its own.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect
youbar/easy-crud
c-point-labs/laravel-hostyourai
dbravoan/dbcms-admin-theme-dbcms
dbravoan/dbcms-theme-db-cyber
dbravoan/dbcms-blocks-basic
dbravoan/dbcms-module-content-audit
dbravoan/dbcms-module-ai-assistant
paygate-to/paygate-php
padosoft/askmydocs-connector-base
defstudio/supercharged-carbon
bernskioldmedia/laravel-matomo