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

Source Laravel Package

redaxo/source

REDAXO is an easy-to-learn, flexible open-source CMS with content built from custom modules and full control over input and output. Multilingual, highly extendable, and adaptable to your workflow, it has been powering websites since 2004 and is backed by a friendly, helpful community.

View on GitHub
Deep Wiki
Context7

Getting Started

REDAXO is a full PHP CMS, not a Composer library you require into a Laravel app — so the first decision is integration mode: run it as a standalone app and talk to it over HTTP/JSON, or share its database. Plan for the former.

Fastest orientation path

  1. Download the latest release, run the web installer, log into the backend.
  2. Use the bundled Installer addOn to pull in demo_base — it's the only demo fully translated to English and it walks through templates, modules, categories, and the media pool. That's ~30 minutes to a working mental model.
  3. Then read the actual content loop: a template (layout) contains REX_ARTICLE[], and each module has an input form and an output fragment. That pairing is 80% of day-to-day work.

From source (per the repo README)

git clone https://github.com/redaxo/core redaxo && cd redaxo
composer install
docker-compose up -d          # REDAXO_PORT=8080 docker-compose up -d if :80 is taken

The default branch is 5.x; PRs target it. PHP 8.3+ is required.

Where to look first

  • redaxo/src/core/CHANGELOG.md — the release notes are unusually detailed and are the de-facto upgrade guide. They're written in German, but they name every changed class/method.
  • redaxo/src/addons/ — structure, mediapool, metainfo, media_manager, cronjob, backup, be_style, install are all first-party addons. They are the best real-world reference for the addon API, extension points, and backend pages.
  • Docs: https://redaxo.org/doku/5.x, API reference https://friendsofredaxo.github.io/phpdoc/, patterns at https://friendsofredaxo.github.io/tricks/.
  • Slack at https://redaxo.org/slack/ — the community is small, German-centric, and genuinely responsive; there is no Stack Overflow corpus to fall back on.

First use case to build: a two-column page template plus your own module (e.g. a teaser grid) rendered through REX_ARTICLE[]. If you're Laravel-side, the equivalent first task is a tiny rex_api_* JSON endpoint addon that Laravel fetches and caches.

Implementation Patterns

Content modeling via modules and templates. Templates are layouts with placeholders; modules pair an input form (backend) with an output fragment (frontend). Keep markup in modules, not templates, so editors can reorder. Escape output with rex_escape($value, 'html') / 'html_attr'.

Extension points instead of core edits. rex_extension::register('OUTPUT_FILTER', $callback) (and PACKAGES_INCLUDED, ART_INIT, etc.) is the service-provider analogue. A boot.php per addon is where you wire these. Never patch redaxo/src/core — changes vanish on core update.

Addon/plugin skeleton as the unit of packaging. package.yml + boot.php + install.php + uninstall.php + pages/ + lib/. This is how you ship anything reusable across projects, and it keeps composer check green.

Schema-as-code with rex_sql_table. There is no artisan migrate. The pattern is:

rex_sql_table::get(rex::getTable('teaser'))
    ->ensurePrimaryIdColumn()
    ->ensureColumn(new rex_sql_column('title', 'varchar(255)'))
    ->ensure();

Call it from install.php, not on every request. It's idempotent, and it is the idiomatic migration mechanism.

Data access. rex_sql::factory() for raw queries; rex_article::get($id), rex_category::get($id), rex_article_slice for content. These objects go through the instance pool — build on them rather than writing parallel ORM layers, or you'll get cache coherency bugs.

Headless integration with Laravel. Expose a namespaced endpoint addon returning JSON (rex_api_* classes or a custom page with rex_response::json()), scoped by rex_clang for multilingual sites. Cache on the Laravel side; use the shared DB only as a last resort, since it couples you to internals that change between 5.x minors.

Scheduled work via the cronjob addon. Register jobs through the addon's API rather than system cron entries pointing at arbitrary PHP — it gives you logging, backend visibility, and safe-mode behavior for free.

Media handling. Use mediapool types plus media_manager effects for derived images. Don't hand-roll thumbnails; the effect pipeline handles WebP/AVIF and the per-type caching.

Multilingual discipline. rex_clang appears everywhere — queries, URLs, permission checks. Always carry the clang id explicitly rather than assuming the current one, especially in API endpoints.

Quality gates if you contribute back. composer check runs cs (rector + php-cs-fixer, fixes in place), sa (PHPStan + Psalm), phpunit, and taint. composer baseline regenerates analysis baselines.

Gotchas and Tips

  • Package metadata vs. reality: Packagist shows NOASSERTION, the README badge says MIT, and LICENSE.md exists. Verify LICENSE.md before using it in a client deliverable.
  • Release notes are German and security-dense. The 5.21.x line shipped multiple GHSAs for stored XSS in the link/linklist/media/medialist widgets and for missing category/language permission checks on slice operations and version previews. Read the CHANGELOG before every minor upgrade; treat it as mandatory.
  • Safe mode needs a CSRF token since 5.21.5. Handy ?safemode=1 bookmarks and support instructions no longer work — a real annoyance mid-debug.
  • The directory protection check can lock you out. It probes one directory per day and the requests can trip fail2ban on the backend user. The use_directory_protection_check config option disables it — set it off in dev and CI.
  • rex_sql_table::ensure() was over-eager on MySQL vs MariaDB. Column type and default normalization differed, so ensure re-issued ALTER on every call. Fixed in 5.21.5; pin at least that version, and never call ensure() at runtime.
  • Instance pool now caches misses. rex_article::get($nonexistent) no longer re-hits the DB each time — good for performance, but a stale null persists for the request. Don't assume a miss is a fresh lookup.
  • CSRF and escaping are the recurring bug class. The metainfo and mediapool patches were literally "missing CSRF on save". Use rex_csrf_token::factory($scope) plus a check on every write, and escape everything at output.
  • Password changes rotate the session id and the "stay logged in" key. Any code storing those values (audit logs, custom SSO bridges) must re-read after a password change.
  • rex_file::mimeType() is PHP-version sensitive. Newer PHP returns text/javascript; 5.21.5 normalizes it to application/javascript. Pass the original filename if provided, and never hardcode MIME comparisons.
  • rex_api_package now enforces admin. Scripts that deactivated/reactivated addons through that endpoint with a demoted session will start failing — correctly.
  • Extension point ordering is registration order. Two addons hooking OUTPUT_FILTER can double-escape or clobber each other's <head> output. Pick a narrow EP and document your ordering assumption.
  • Debugging toolkit: safe mode first, then rex::isDebugMode(), then the logs under redaxo/data/log/ (rex_logger). Backend pages you can't reach are usually a permission-scope problem, not a fatal.
  • composer psalm:no-cache exists for a reason — Psalm's cache goes stale after refactors and produces phantom errors.
  • Backup addon exports are now permission-scoped. Non-admin users with backup[export] only get REDAXO-prefixed tables, excluding rex_user, rex_user_passkey, rex_user_session. Any custom export tooling must replicate those restrictions or it becomes a credential-leak vector.
  • PHP 8.6 workarounds are already landing (voku/portable-utf8 no longer mutates global encoding). Pin your PHP minor in CI; the core supports 8.3+ but several fixes are version-conditional.
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.
marcelgwerder/laravel-api-handler
firebrikdotcom/conveyor-laravel-broadcaster
kanata-php/conveyor-laravel-broadcaster
alish/short-message
sonrac/lumen-league-oauth2
pushery/sanctum-hardening-for-laravel
evanschleret/laravel-uuidable
yigit-serin/laravel-openvidu
adachsoft/command-executor-lib
tagixo/document-builder
tagixo/page-builder
tagixo/mail-builder
tagixo/form-builder
primix/primix
tagixo/core
alesima/laravel-azure-service-bus
tomshaw/shopcart
likyly/laravel
darthsoup/shoppingcart
tdt/core