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

Sf Front Editor Laravel Package

loicpennamen/sf-front-editor

sf-front-editor is a PHP package that adds an in-place front-end editing layer to your application, letting authorized users update page content directly in the browser. It simplifies copy changes and reduces reliance on backend admin screens.

View on GitHub
Deep Wiki
Context7

Getting Started

Reality check first: this is not a Laravel package, and it is probably not a modern Composer package either. The sf- prefix is Symfony 1.x naming (sfFrontEditorPlugin), which predates Composer entirely and corresponds to a framework that reached end-of-life in 2012. Before you write a line of integration code, confirm what you actually cloned:

git clone https://bitbucket.org/LoicPennamen/sf-front-editor.git
cd sf-front-editor
ls -la
cat package.xml 2>/dev/null   # Symfony 1 plugin manifest → plugin:install
cat composer.json 2>/dev/null # Symfony 2+ bundle → VCS repository entry
cat README* 2>/dev/null

If you see package.xml and config/*PluginConfiguration.class.php, it is a Symfony 1 plugin and the install path is php symfony plugin:install — nothing about it will run under Laravel. If you see composer.json, it is a Symfony 2+ bundle; you would install it via a VCS repository entry and only inside a Symfony app.

For a Laravel codebase, treat the "install" step as reading the source, not requiring it. Where to look, in order:

  1. The controller/module action that handles the save request. This is the entire contract: what payload it accepts, how it authenticates the editor, and where it writes. Read this before the README.
  2. The helper/partial that renders an editable region. This tells you what attributes the JS layer needs (target ID, field name, culture/locale) — that is the client-side seam you would reproduce.
  3. The model/schema. This tells you how content is stored (likely a Doctrine table keyed by page + field + culture). That shape is what you would mirror as an Eloquent model.
  4. The frontend assets (web/js/, web/css/). These may be reusable independently of Symfony, which is the only part with real day-to-day value.

The first use case to validate, if you are porting the pattern into Laravel: one editable text region on one Blade-rendered page. Click it, change the text, hit save, reload, see it persisted. If you cannot get that round-trip working in an afternoon with your own thin implementation, the package was never the bottleneck — your content model was.

If you are actually on a Symfony 1 project (rare but possible), install is:

php symfony plugin:install sfFrontEditorPlugin
php symfony plugin:publish-assets
php symfony cc

Implementation Patterns

Every in-place front-end editor follows the same three-part shape, and this one will too: a server-side helper emits a wrapper element with data attributes, a JavaScript layer promotes that element into an editable surface, and an AJAX save posts the new value back to a controller action. The port to Laravel is a port of that shape, not of the code. Concretely:

1. Own the render seam. Do not call the package's helper from Blade even if you could shim it. Write your own Blade component or directive and decide its public API yourself:

<x-editable field="hero.body" :model="$page" culture="{{ app()->getLocale() }}">
    {!! $page->hero_body !!}
</x-editable>

The component renders the same data attributes the Symfony helper does (a target, a field key, a locale), but you control the markup. That gives you one place to add sanitization, permission checks, and cache-busting later — the single most important decision in this whole assessment.

2. Route saves through a service, not a controller-to-model write. The Symfony module almost certainly writes directly to the content column. Do not reproduce that. In Laravel:

// app/Actions/UpdateContentBlock.php
public function handle(Page $page, string $field, string $value, User $editor): ContentRevision
{
    return DB::transaction(function () use ($page, $field, $value, $editor) {
        $revision = ContentRevision::create([
            'page_id' => $page->id, 'field' => $field,
            'old' => $page->{$field}, 'new' => $value,
            'user_id' => $editor->id,
        ]);
        $page->update([$field => $value]);
        return $revision;
    });
}

Inline editing generates many small unreviewed writes. An audit table is cheap now and impossible to retrofit once editors are used to instant saves.

3. Gate edit mode in middleware, and check one flag in templates. The Symfony original likely gates on sfContext::getInstance()->getUser()->isAuthenticated(). In Laravel, resolve an editing flag once in a middleware or Gate, share it with Inertia::share/View::share, and let the Blade component and the JS entry point both read that single source of truth. Never scatter @if(auth()->user()->can(...)) across views — that is exactly how these integrations rot.

4. Keep the JS layer thin and framework-agnostic. If the package ships usable JS (a contenteditable wrapper plus a fetch call), extract it, replace the save URL with a configurable route, and drop it into your Vite pipeline. That is the one piece that survives the port verbatim. Bind it to a PATCH /api/content/{block} endpoint behind auth:sanctum and can:update-content — an API contract you own, not Symfony's route.

5. Wire editor-mode into your cache strategy from day one. Front-end editing means writes land next to the render path. Wrap page reads in your cache layer, and bust the specific page's key inside the UpdateContentBlock action above. Do this in the same PR as the feature — retrofitting cache invalidation onto a live inline editor is how you get editors seeing stale text and losing confidence in the tool.

Gotchas and Tips

  • sf- means Symfony 1, not Symfony 2. If you were handed this as a "Symfony bundle," verify the version first. A Symfony 1 plugin has no Composer support, no namespaces, and no upgrade path. Do not build a roadmap on it.
  • Zero stars / zero dependents / Bitbucket-only is a real signal, not noise. There is no license file evidence, no changelog, no tagged releases, no security response process. If you vendor it, budget for owning it permanently, or treat it strictly as a reference implementation.
  • Sanitization is the failure mode that bites hardest. Front-end editors persist whatever the browser sent. The Symfony original's save action likely trusts the payload. In your port, run every save through an HTML sanitizer (mews/purifier or symfony/html-sanitizer via an adapter) before persistence and escape on output. Stored XSS via an inline editor is a content-team-facing security incident.
  • The save endpoint is the attack surface. Confirm the package's controller checks authorization per-field, not just per-user. A common pattern in packages this old is "any authenticated user can edit any field." Your Laravel route should authorize the specific model and field, not just auth.
  • Locale/culture handling is usually bolted on. The Symfony helper takes a culture argument, which suggests a page_content table keyed by (page, field, culture). Preserve that key shape if you port the schema; dropping it means a painful migration the first time marketing needs a second language.
  • Assets may not be published automatically. On the Symfony 1 path, plugin:publish-assets is a separate step and forgetting it produces a silent "click does nothing" — the markup is there, the JS 404s. Check the browser network tab before debugging PHP.
  • The extension point you actually want is the save action. If you ever do run this on Symfony, override the module's executeSave (or the equivalent) rather than editing vendor files — that is where you add transactions, revisioning, and cache invalidation. Everything else in the package is cosmetic.
  • Do not let the front-end editor become your only write path. If this is the sole way content changes, you have coupled editing to the render path with no staging, and a bad render deploy takes the editor down with it. Keep an artisan command or a minimal admin form as a break-glass path.
  • Time-box it. Give the read-the-source-and-decide pass half a day. If after that the honest answer is "we would rewrite this in Laravel in two days," do that instead — the pattern is small, and the package's real contribution is showing you that the pattern is small.
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.
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle