iblock-elements
Skill4 starsChanged 4 months agoMITView on GitHub
Read and write 1C-Bitrix information block elements — the D7 ORM (`\Bitrix\Iblock\Elements\ElementTable` / `ElementObject`) versus the legacy `CIBlockElement`, property access, list vs detail, filtering, and active/date fields, with safe handling of untrusted filter input. Use when the user needs to create, read, update, or delete Bitrix information block elements and asks whether to use the D7 ORM (`\Bitrix\Iblock\Elements\ElementTable`) or the legacy `CIBlockElement`; пользователь строит список элементов инфоблока с фильтром по активности, дате или свойству (`getList` в D7 ORM или `CIBlockElement::GetList`) и спрашивает, как безопасно передать пользовательский ввод в фильтр; the user needs to read or write iblock element properties (single, multiple, or list values) — via the D7 `PropertyValues` collection or the legacy `CIBlockElement::GetProperty` / `SetPropertyValues`. Keywords: bitrix, iblock, elements, d7, orm, legacy, properties, filter, input, sql, security, битрикс, инфоблок, элементы.
In this repository119 other files it gives its agents.
- strategy-bitrix-d7-incrementalSkill
- strategy-explicit-over-magicSkill
- strategy-framework-conventionsSkill
- strategy-legacy-safe-editsSkill
- strategy-minimal-diffSkill
- strategy-no-untested-refactorSkill
- strategy-preserve-public-apiSkill
- strategy-readonly-immutabilitySkill
- strategy-security-firstSkill
- strategy-test-drivenSkill
- openapiSkill
- paginationSkill
- rest-designSkill
- versioningSkill
- cqrsSkill
- dependency-inversionSkill
- hexagonalSkill
- repository-patternSkill
- service-layerSkill
- bitrixSkill
- findings-reportSkill
- laravelSkill
- performanceSkill
- phpSkill
- project-analysisSkill
- refactoringSkill
- roi-prioritizationSkill
- securitySkill
- stack-detectionSkill
- cache-layersSkill
- component-engineSkill
- d7-eventsSkill
- d7-loaderSkill
- d7-orm-queriesSkill
- kernel-main-moduleSkill
- localizationSkill
- controllersSkill
- ormSkill
- validationSkill
- controllersSkill
- query-builderSkill
- routingSkill
- autoload-psr4Skill
- dependency-managementSkill
- scriptsSkill
- connection-poolingSkill
- mysql-indexingSkill
- redisSkill
- transactionsSkill
- ci-github-actionsSkill
- deployment-strategiesSkill
- docker-phpSkill
- env-configSkill
- associationsSkill
- entities-mappingSkill
- orm-basicsSkill
- entity-apiSkill
- module-developmentSkill
- routing-controllersSkill
- formsSkill
- The first 60 shown.
The file
Show its rules and text
We split this skill into the rules it gives an agent
13 rules. About 0 are common, 7 are distinctive, and 6 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈7
Distinctive · estimate
This author's own choices. Worth a look.
6
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 87
Do not use this skill for Highload block entities or arbitrary module ORM tables that are not information block elements.
- Very specific: line 89
Do not use this skill on a non-Bitrix PHP app.
- Distinctive: line 139
Verify: The entity class corresponds to the target iblock and is loaded after includeModule.
- Very specific: line 140
Create the object, set fields ($el->setName($name).
- Distinctive: line 143
Verify: Required fields and properties are set from validated values before saving.
- Very specific: line 144
Call $result = $el->save().
- Distinctive: line 146
Verify: Save success is checked and errors are surfaced, not swallowed.
- Distinctive: line 164
Verify: Element classes are only reached when the iblock module is present.
- Very specific: line 165
Read the request value through the kernel Request and cast it, e.g.
- Distinctive: line 167
Verify: The value is an int bound to a fixed filter key, never a user-chosen key.
- Very specific: line 168
Call ElementTable::getList(['select' => ['ID', 'NAME'], 'filter' => ['=ACTIVE' => 'Y', '=IBLOCK_SECTION_ID' => $sectionId], 'limit' => 20]).
- Distinctive: line 171
Verify: Only rendered fields are selected, ACTIVE is enforced, and paging is bounded.
- Very specific: line 184
Read D7 element properties via the object's getValue() on the PropertyValues collection (or a withProperties/->fill() load).
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
<!-- generated: do not edit — source: knowledge/atoms/bitrix/iblock-elements/ --><!-- schema: atomVersion=3 skillVersion=2 graphVersion=1 --><!-- compile: @php-skills/compiler v1.0.0 (deterministic build) -->Bitrix Iblock Elements
When to use
- The user needs to create, read, update, or delete Bitrix information block
elements and asks whether to use the D7 ORM
(
\Bitrix\Iblock\Elements\ElementTable) or the legacyCIBlockElement. - Пользователь строит список элементов инфоблока с фильтром по активности, дате
или свойству (
getListв D7 ORM илиCIBlockElement::GetList) и спрашивает, как безопасно передать пользовательский ввод в фильтр. - The user needs to read or write iblock element properties (single, multiple,
or list values) — via the D7
PropertyValuescollection or the legacyCIBlockElement::GetProperty/SetPropertyValues.
When NOT to use
- Do not use this skill for Highload block entities or arbitrary module ORM tables that are not information block elements; their storage and API differ.
- Do not use this skill on a non-Bitrix PHP app; information blocks,
CIBlockElement, and\Bitrix\Iblock\...exist only inside 1C-Bitrix.
Core guidance
- Never build filter keys from untrusted input — Pass user input only as filter values through the array filter (D7
filteror legacy$arFilter); never interpolate user input into filter keys, operators, field names, or aruntime/raw SQL expression. - Prefer the D7 iblock ORM for new element code — In new code, read and write elements through the D7 ORM
(
\Bitrix\Iblock\Elements\ElementTableor a generatedElement<CODE>Table) instead ofCIBlockElement::GetList/CIBlockElement::Add.
Decision Engine
Walk this section before choosing an implementation path.
Are you writing new element code, or editing an existing legacy CIBlockElement path?
├── Editing legacy path: → legacy — keep the existing CIBlockElement call and make a minimal local edit; do not rewrite to the ORM opportunistically.
└── New code: Does the operation need a legacy-only feature (workflow/BizProc hooks, `CIBlockElement::Add` side effects, deep GetList mode)?
├── No legacy-only feature: → d7 — use ElementTable/getList with select, filter, and PropertyValues; pass user input only as filter values.
└── Needs legacy-only feature: → legacy — call CIBlockElement (e.g. Add/Update with workflow) behind a thin repository so call sites stay D7-shaped.
Full engine: references/decision-engine.md — Decision Tree, Priority Matrix, Decision Table.
Workflows
Workflow: Create Element D7
Progress:
- [ ] Include iblock, then resolve the element entity for the iblock — a generated
`Element<CODE>Table` or `\Bitrix\Iblock\Elements\ElementTable` compiled for the
iblock id
- [ ] Create the object, set fields (`$el->setName($name); $el->setIblockId($id);
$el->setActive('Y');`) and set property values through the object's
`PropertyValues` collection with validated data
- [ ] Call `$result = $el->save();` and branch on `$result->isSuccess()`, reading
`$result->getErrorMessages()` on failure instead of assuming success- Include iblock, then resolve the element entity for the iblock — a generated
Element<CODE>Tableor\Bitrix\Iblock\Elements\ElementTablecompiled for the iblock id.- Verify: The entity class corresponds to the target iblock and is loaded after includeModule.
- Create the object, set fields (
$el->setName($name); $el->setIblockId($id); $el->setActive('Y');) and set property values through the object'sPropertyValuescollection with validated data.- Verify: Required fields and properties are set from validated values before saving.
- Call
$result = $el->save();and branch on$result->isSuccess(), reading$result->getErrorMessages()on failure instead of assuming success.- Verify: Save success is checked and errors are surfaced, not swallowed.
Workflow: Read List D7
Progress:
- [ ] Include the module with
`if (!\Bitrix\Main\Loader::includeModule('iblock')) { return; }` before
referencing any element class
- [ ] Read the request value through the kernel Request and cast it, e.g
- [ ] Call `ElementTable::getList(['select' => ['ID', 'NAME'], 'filter' =>
['=ACTIVE' => 'Y', '=IBLOCK_SECTION_ID' => $sectionId], 'limit' => 20]);` and
iterate the typed result- Include the module with
if (!\Bitrix\Main\Loader::includeModule('iblock')) { return; }before referencing any element class.- Verify: Element classes are only reached when the iblock module is present.
- Read the request value through the kernel Request and cast it, e.g.
$sectionId = (int) $request->getQuery('section');, rejecting non-positive ids.- Verify: The value is an int bound to a fixed filter key, never a user-chosen key.
- Call
ElementTable::getList(['select' => ['ID', 'NAME'], 'filter' => ['=ACTIVE' => 'Y', '=IBLOCK_SECTION_ID' => $sectionId], 'limit' => 20]);and iterate the typed result.- Verify: Only rendered fields are selected, ACTIVE is enforced, and paging is bounded.
Best practices
- On the public frontend, filter lists with
ACTIVE => 'Y'and respect the activity dates (ACTIVE_DATE_FROM/ACTIVE_DATE_TO, or the ORM equivalent) so drafts and expired elements are not shown; only admin/edit contexts may drop them - Guard element access with
\Bitrix\Main\Loader::includeModule('iblock')(or the legacyCModule::IncludeModule('iblock')) and bail out when it returns false, before referencingCIBlockElementor any\Bitrix\Iblock\...class - For a list, select only the fields and properties you render and page with
limit/offset(D7) ornPageSize(legacy); for a detail view load the single element by id and its properties in one pass - Read D7 element properties via the object's
getValue()on thePropertyValuescollection (or awithProperties/->fill()load); in legacy code useCIBlockElement::GetProperty/GetElementValuesin bulk rather than one call per property per row
Anti-patterns
| Anti-pattern | Why it fails | Do instead |
| Opportunistic ORM rewrite during an unrelated fix | The rewrite widens the diff and risks changing behavior (filter semantics, ordering) the task never intended to touch. | Keep the scoped fix minimal on the legacy API; propose the ORM migration as a<br>separate, signed-off task. |
| Passing raw superglobals straight into the filter | Unvalidated input can smuggle in unexpected filter keys and types, causing<br>filter injection and returning data the caller never intended to expose. | Read specific values through the kernel Request, validate and cast each one, and<br>bind them to explicit filter keys you control. |
| Selecting every field and property for a list | Fetching all fields and every property inflates the query and hydration cost for data you never render. | List the exact fields and property codes you display in select; load the full<br>record only on the detail page. |
See references/anti-patterns.md.
Debugging
- User input flowing into a filter key or field — Bitrix parameterizes filter values but emits keys, fields, and raw expressions into SQL verbatim. Fix: Keep filter keys, fields, and operators as constants in code; whitelist any input-selected field against a fixed allow-list and bind only validated values.
- Forgetting the active filter on public lists — Bitrix does not filter inactive or future-dated elements automatically at the query layer. Fix: Add
=ACTIVE => 'Y'plus the activity-date conditions (or reuse the component's standard public filter) on every frontend list, restricting the unfiltered query to admin contexts. - Fetching properties one element at a time — Per-row property fetches scale linearly with the result set and dominate page time. Fix: Select the needed properties with the list query (D7
PropertyValues/withReferences) or useCIBlockElement::GetElementValuesto bulk-load property values for all ids at once. - Ignoring the result of an element write — A silent write failure leaves the caller believing data was persisted when it was not. Fix: For legacy, check the return value and read
$el->LAST_ERROR; for the ORM, branch on$result->isSuccess()and surfacegetErrorMessages().
Performance notes
- Fetching properties one element at a time — Calling
CIBlockElement::GetProperty(or reloading the ORM property collection) inside a list loop issues one or more queries per row, an N+1 explosion on large lists. - Select only needed fields for lists, full record for detail — For a list, select only the fields and properties you render and page with
limit/offset(D7) ornPageSize(legacy); for a detail view load the single element by id and its properties in one pass. - Access properties through the proper collection, not GetNext loops — Read D7 element properties via the object's
getValue()on thePropertyValuescollection (or awithProperties/->fill()load); in legacy code useCIBlockElement::GetProperty/GetElementValuesin bulk rather than one call per property per row.
Production checklist
- Every public-facing element list enforces
ACTIVE => 'Y'and the activity-date bounds so drafts and expired elements never reach visitors. - List queries select only the fields and properties actually rendered and use paging (limit/offset or nPageSize), with no per-row property fetches in a loop.
- Filter keys, field names, and operators are constants in code; only validated, cast values derive from user input, and any input-selected field is whitelisted.
- Edits to legacy CIBlockElement paths are minimal and reversible, with no opportunistic rewrite into the D7 ORM during an unrelated change.
- Every element access is preceded by a checked
Loader::includeModule('iblock')(or legacy equivalent) that bails out cleanly when the module is absent. - Every create/update checks its outcome — legacy return value plus
$el->LAST_ERROR, or the ORM$result->isSuccess()— before the caller treats the data as persisted.
Version notes
- The iblock ORM supersedes CIBlockElement on modern cores — The D7 iblock ORM (
\Bitrix\Iblock\Elements\ElementTableand generatedElement<CODE>Tableentities) is the current API on modern cores (iblock ~20+);CIBlockElementremains as the legacy facade that older code and some workflow-aware writes still rely on. - PHP support tracks the Bitrix core version — Modern Bitrix cores run the iblock module on PHP 7.4 through 8.2; the module and its ORM were not certified past 8.2 at the time of writing, so avoid relying on PHP 8.3+ syntax in iblock-adjacent code.
Security
- Treat iblock filter input as an injection boundary — Treat every request value used in an element filter as untrusted: validate and
cast it, bind it only as a filter value under a fixed key, and never let input
choose a field name, operator, or feed a
runtime/raw SQL expression.
Testing
- Activation and decision behavior are verified in
eval/scenarios/bitrix/iblock-elements.yaml.
Additional resources
- references/anti-patterns.md
- references/core.md
- references/decision-engine.md
- references/examples.md
- references/pitfalls.md
- references/recipes.md
- references/version-differences.md
Knowledge graph
Prerequisites: bitrix/d7-orm-queries
Related: bitrix/cache-layers
<!-- graph-fragment: graph/fragments/bitrix/iblock-elements.yaml -->Skill contract
Produces: iblock.elements-accessed
Requires: bitrix.iblock-module-available, bitrix.d7-orm-available
Risk: medium · Confidence: 0.9
<!-- contract-fragment: contracts/fragments/bitrix/iblock-elements.yaml -->Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

