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

Phax Bundle Laravel Package

phax/phax-bundle

Phax Bundle is a Symfony integration package for the Phax library. It registers services, handles configuration, and connects Phax components to Symfony’s dependency injection and framework features, reducing boilerplate for developers. Use it to wire Phax into Symfony apps with minimal setup and co...

View on GitHub
Deep Wiki
Context7

Getting Started

Phax is a Symfony 2.x-only bundle (last release April 2014, archived) that gives AJAX calls a structure: you define a named server-side "Phax" action, the bundle exposes a single dispatch route, and a small JS library calls that action by name and hands you a normalized JSON envelope. If you inherit an app that uses it, the mental model is "one class per AJAX endpoint + a dispatcher route," not "one controller action per URL."

Minimum steps to get it running:

  1. Confirm the environment fits. Symfony 2.3–2.8 era, PHP 5.4–7.0. It will not install cleanly on Symfony 3+ or PHP 8 (getRequest(), app/console, old DI XML/YAML, possibly each()).
  2. Install. composer require phax/phax-bundle if Packagist still serves it; otherwise add a repositories VCS entry pointing at the GitHub tag, or vendor the bundle into src/ and register it manually.
  3. Register in app/AppKernel.php: new Phax\Bundle\PhaxBundle\PhaxBundle() (check PhaxBundle.php in the repo root for the exact namespace/class — it matters, the repo layout is unusual).
  4. Import the routing in app/config/routing.yml:
    phax:
        resource: "@PhaxBundle/Resources/config/routing.yml"
        prefix:   /phax
    
    This is what creates the single endpoint every call goes through.
  5. Publish the JS: php app/console assets:install web --symlink, then include the bundle's script (look in Resources/public/js/) after jQuery in your base layout. There may also be a Twig helper — grep Resources/views/ for it.
  6. Where to look first: Resources/doc/ (if present), then the shipped phax.js — the JS file is the specification for the wire format. Read it before the PHP; it tells you what keys the response envelope must contain and what defaults (redirect, reload, flash) are handled for you.

First use case — a form submit that returns validation errors or a success payload without writing a controller:

// src/Acme/DemoBundle/Phax/SaveCommentPhax.php
namespace Acme\DemoBundle\Phax;

use Symfony\Component\HttpFoundation\Request;

class SaveCommentPhax extends BasePhax // extend the bundle's base class
{
    public function execute(Request $request)
    {
        $comment = new Comment();
        $comment->setContent($request->request->get('content'));
        $this->getDoctrine()->getManager()->persist($comment);
        $this->getDoctrine()->getManager()->flush();

        return array('id' => $comment->getId()); // becomes the `data` key
    }
}

Register it as a service with the bundle's tag and a short alias (save_comment), then from JS call that alias and handle the envelope. Adjust names to whatever the bundle's DependencyInjection/ and tag definitions actually use — the shape is stable, the identifiers are not well documented.

Implementation Patterns

One Phax class per action, thin controllers. Treat each class like a single-use-case command object reachable over HTTP. Resist putting three operations behind one alias with an action parameter — you lose the per-action DI and tagging that makes the bundle worth using at all.

Keep the response envelope canonical. The JS layer auto-handles a subset of keys (success flag, message, redirect, reload, DOM target). Use the bundle's response object rather than hand-rolling new JsonResponse([...]), or the default client-side handlers silently stop working.

Form validation as structured errors. Inject form.factory into the Phax service, build the form, call handleRequest($request), and on failure return the errors keyed by field name inside data so the JS can paint them next to inputs:

if (!$form->isValid()) {
    return $this->error($this->getFormErrors($form)); // field => [messages]
}

This is the single biggest real-world win — you get one error format for every form in the app.

Namespace your aliases. If the dispatcher supports dots (comment.save, comment.delete, user.avatar.upload), use them. A flat namespace of 40 aliases becomes unsearchable fast.

Security must be explicit. The dispatch route is a generic entry point; controller-level @Security annotations won't cover it. Either put the whole /phax prefix behind a firewall with access_control, or add an isGranted() check in a base Phax class that every action extends.

Progressive enhancement. Keep a normal HTML form action/method as the fallback and layer phax.call() on top. When the JS or the dispatcher breaks (and on an archived bundle, it will), the app still works.

Return scalars, not entities. The bundle predates robust circular-reference handling. Map entities to small arrays/DTOs inside execute().

Testability is the redeeming feature. A Phax class is a plain service: unit-test execute() with a Request stub and a mocked entity manager. For integration, POST to the /phax/{alias} route with the kernel test client and assert on the envelope.

Testing the client side: stub phax.call (or your own wrapper around it) in JS tests and assert on the payload shape you send, not on jQuery internals.

Cross-cutting concerns belong in a base class or a kernel event listener: CSRF verification, JSON decoding, logging every call with its alias and duration, and global exception-to-envelope conversion.

Gotchas and Tips

  • Archived = no fixes. No security patches, no PHP 8 / Symfony 3+ compatibility. Budget a fork or a rewrite if the app is long-lived.
  • JSON bodies. Symfony only populates $request->request for application/x-www-form-urlencoded. If the JS sends application/json, read json_decode($request->getContent(), true) yourself — otherwise every field looks empty and you'll blame the bundle.
  • CSRF is the classic silent failure. The token must be rendered into the page (a data- attribute on <body> is the usual trick) and validated in the base Phax class. Forget it and you get opaque 403/empty responses that don't appear in the app log unless you check the security channel.
  • Swallowed exceptions. The dispatcher often converts any throwable into a generic error envelope. In dev, temporarily rethrow inside execute() or check app/logs/dev.log; a stack trace is usually there even when the browser shows nothing.
  • Route shadowing. The dispatch route can be greedy. Always import it under a prefix (/phax) and constrain the alias parameter with a regex; otherwise it can match unrelated URLs imported later.
  • Asset publishing on Windows: use assets:install web without --symlink, and re-run after every bundle update — stale copies of phax.js cause maddening "the fix didn't take" moments.
  • Envelope drift. Changing a key (success → ok, message → msg) breaks default handlers invisibly. Pin the envelope in one PHP constant and one JS constant, and grep for both when refactoring.
  • getRequest() / service location. Older Symfony 2 code here may call $this->getRequest() or reach into the container. It's deprecated in 2.8 and gone in 3.x — this is the main thing that makes migration a rewrite rather than a bump.
  • Extension points worth using: decorate the Phax dispatcher to add logging/metrics; add a base class for shared helpers (getDoctrine(), translator, security context); add a kernel listener for authentication so you don't repeat checks in 40 classes.
  • For anything new, don't adopt this. The pattern is a two-hour rebuild: FOSJsRoutingBundle or a data-attribute route + one controller returning a fixed envelope, or modern Symfony UX (Stimulus/Turbo) which gives you the same structured-AJAX ergonomics with maintained packages. Migrate action-by-action: each Phax class maps one-to-one onto a controller action or a Messenger handler, so the rewrite is mechanical.
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