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 Cache Laravel Package

webarchitect609/bitrix-cache

A caching library for 1C-Bitrix that simplifies storing and invalidating cached data using tags, dependencies, and TTL. It wraps Bitrix’s native cache API, reduces boilerplate, and helps keep site content fresh and performant.

View on GitHub
Deep Wiki
Context7

Getting Started

This package is a thin, fluent wrapper around Bitrix’s native \Bitrix\Main\Data\Cache, so before anything else confirm:

  1. The project is a 1C‑Bitrix site (or a component/plugin running inside one) with the main module installed — the package delegates all real caching to \Bitrix\Main\Data\Cache.
  2. Install with Composer:
    composer require webarchitect609/bitrix-cache
    
  3. The Bitrix cache root (/bitrix/cache, or whatever bitrix.cache_path is configured to) is writable by PHP.

Where to look first. Open the README.md and then the Cache class itself — the codebase is small (one main facade plus a small handful of support classes). The README shows the intended “happy path,” which is roughly:

use WebArchitect609\BitrixCache\Cache;

$value = Cache::create()
    ->expiresAfter(3600)
    ->withBaseDir('/queries/products')
    ->withKey('featured-products')
    ->get(function () {
        // expensive work happens only on a cache miss
        return ProductRepository::featured();
    });

First realistic use case. Replace an existing hand-rolled block of Cache::createInstance() / initCache() / startDataCache() / endDataCache() with the fluent call above. Pick something small and well bounded — one query, one HTTP call, or one rendered block — so you can measure TTL and invalidation behaviour before converting the hot spots.

If your project is not a Bitrix project (or is Bitrix but you mostly write standalone PHP), this package provides no value; use PSR‑16/PSR‑6 (symfony/cache, laminas-cache) instead.

Implementation Patterns

Cache a query result (read-through / “remember”) pattern. This is the pattern this package is built for: the closure runs only on a miss, the returned value is serialized and stored, and the cached value is returned on a hit. Keep closures pure — they should have no side effects other than the read they represent.

$count = Cache::create()
    ->expiresAfter(300)
    ->withBaseDir('/counters')
    ->withKey("active-users-{$segmentId}")
    ->get(fn() => (int)$connection
        ->query('SELECT COUNT(*) FROM users WHERE segment = ?', [$segmentId])
        ->fetch());

Namespacing with withBaseDir. Bitrix’s cache is a two-level key space: a directory and a key. Use withBaseDir() to group logically related entries (per module, per entity, per page zone) and withKey() for the specific variant. This makes bulk invalidation and cache inspection in /bitrix/cache human-readable. A good convention is /{module}/{entity}/{scope}.

Parameterised keys. Build the key from the inputs that actually affect the result:

->withBaseDir('/pricing')
->withKey("price-{$productId}-{$currency}-{$priceGroup}")

Avoid putting unstable values (timestamps, request IDs, session IDs) into the key — they defeat the cache.

Cache rendered fragments. Cache the output of a template include or a view render, not the whole page, so a single component can be busted independently:

$html = Cache::create()
    ->expiresAfter(600)
    ->withBaseDir('/components/news-list')
    ->withKey('index')
    ->get(fn() => $APPLICATION->IncludeComponent('bitrix:news.list', '.default', $params, true));

Service-layer wrapper. Rather than sprinkling Cache::create() calls across templates, wrap caching in a repository or service class so TTLs and key conventions live in one place. This is where a fluent API earns its keep:

final class CachedProductGateway
{
    public function find(int $id): ?array
    {
        return Cache::create()
            ->expiresAfter(60 * 15)
            ->withBaseDir('/gateways/products')
            ->withKey((string)$id)
            ->get(fn() => $this->api->fetchProduct($id));
    }

    public function forget(int $id): void
    {
        Cache::create()
            ->withBaseDir('/gateways/products')
            ->withKey((string)$id)
            ->delete(); // or clean() — check the class for the exact method name
    }
}

Invalidation from event handlers. The natural Bitrix integration point is OnAfterIBlockElementUpdate, OnAfterUserUpdate, etc.: subscribe, compute the same base dir + key that reads use, and clear. Centralise the key-building in a helper so the read path and the invalidation path cannot drift apart.

Nested caching / layering. Because the wrapper is thin, it composes well: an outer short-TTL cache around an inner long-TTL cache of the same data lets you tune freshness vs. cost independently, as long as both keys are deterministic.

Testing. Because the closure is the only thing that “misses,” unit tests can stub the compute side and assert it is called once, or you can run with a very short TTL to force misses deterministically — but keep in mind the underlying Bitrix cache is global state, so tests need a clean cache directory or a mocked adapter.

Gotchas and Tips

The package is a thin wrapper — all the real semantics are Bitrix’s. TTL resolution, serialization, and where files land are governed by \Bitrix\Main\Data\Cache and bitrix.cache_path. Read the Bitrix docs on the Cache class before debugging the wrapper.

Key + base dir collisions are silent. Two callers using the same withBaseDir/withKey will read each other’s data with no warning. Establish a convention (module/entity/scope/variant) early; retrofitting it once stale data is being served is painful.

Only serializable values. Arrays, scalars, and plain DTOs are fine; resources, closures, PDO handles, and Bitrix Result objects with live connections are not. Serialize to an array in the closure if you need to cache a domain object.

TTL edge cases. Zero, negative, and null TTLs behave differently across Bitrix versions (some mean “never expire,” some mean “always expire”). Standardise on a positive integer of seconds in your service layer and avoid passing raw TTLs from caller code.

Cache misses are expensive; keep the closures small. If a closure takes 30 s and 40 callers hit it in a stampede, every one runs it. For very hot, very slow data, layer a short lock or use a slightly stale-tolerating pattern (short TTL on a “soft” cache, longer TTL on the computed payload).

Bitrix context matters. The underlying cache behaviour can differ between web requests, admin pages, and CLI (bitrix/php_interface/cli.php) because of how the kernel is bootstrapped and which paths are available. If a job “works on the site but not in cron,” check the cache directory permissions and bitrix.cache_path first.

Old release — pin and audit before upgrading surrounding code. The last tagged release is from December 2021. In a modern Bitrix project still on older PHP this is fine, but if you are on PHP 8.x, verify the package’s composer.json constraints before assuming it installs. Treat it as “working code,” not “actively maintained code,” and be prepared to fork it — the surface is small enough that a private fork is usually easier than fighting a dependency conflict.

No PSR‑16 / PSR‑6. This is a Bitrix-shaped API, not an interoperable one. If you need to share a cache abstraction with non-Bitrix code, wrap this package behind your own interface; do not leak the fluent API into code that should not depend on Bitrix.

Debugging a miss. First place to look is the actual cache directory (/bitrix/cache/<your-base-dir>/) — if the directory isn’t being created, it is a filesystem permission problem, not a cache logic problem. If files exist but code still recomputes, check that the key is byte-for-byte stable (whitespace, integer vs. string casts, trailing slashes on the base dir).

Extension points. The wrapper exposes the compute closure and the key/TTL/base-dir setters, and that is essentially it. If you need per-request request-logging of hits/misses, tagging, or a Redis backend, plan to wrap it (adapter/event listener around the class) rather than expect it to grow the feature. Because the facade is small, a light decorator that logs before/after each get() call is a realistic half-hour job.

Housekeeping. Bitrix does not garbage-collect aggressively by default. If you create many one-off base dirs, add a scheduled cleanup or stick to a fixed, small set of base dirs so the cache tree stays inspectable and the disk footprint stays bounded.

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.
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle
adachsoft/api-version-bundle
elsayed85/laravel-api-exceptions
ouhssini/laravel-demo-mode
daworks/ncloud-outbound-mailer-driver
gp247/cms
ignibyte/aic-gates
nexa-merchant/blog
novasa/laravel-language-center
opencage/geocode
adolfoholzer/parameters
livenetworks/ln-starter
cgv/localized-resource