Download the PHP package jul6art/push-bundle without Composer

On this page you can find all versions of the php package jul6art/push-bundle. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package push-bundle

logo dev in the hood

Symfony real-time notification bundle

License Version

Requirements

Installation

Then Download the mercure hub depending on your operating system and install it in the root of your project. For each release, the assets section list operating systems implementations. The folder must contain the mercure bin. Rename this folder mercure.

EventSource Polyfill

and import it on client side to make push works on IE and Edge

Generate new JWT token (Optionnal)

Go to jwt.io and put your future mercure secret key (default it's !ChangeMe!) in the verify signature textarea and this array in the payload textarea

Because the array is empty, the Symfony app will only be authorized to publish public updates (see the authorization section of symfony/mercure-bundle for further information).

THen store the generated token in your .env file as MERCURE_JWT_TOKEN parameter

Start mercure server

The default token is signed with the secret key: !ChangeMe!

CORS_ALLOWED_ORIGINS is the client URL and port. It can be * or a list of domains ADDR is the server url and 3000 is the port for mercure server

:warning: By default, push messages are async so you need to launch a crawler in a terminal to dequeue messages and send it

Using with api-platform

Server side

Client side

Using without api-platform

Server side

Sync (Optionnal)

Other messenger messages (Optionnal)

Can be async_priority_high or async_priority_low or sync

Asyncable Attribute (Optionnal)

The Asyncable annotation is now a PHP attribute: Jul6Art\PushBundle\Attribute\Asyncable.

My Entity

My EntityEvent

The event class must accept the entity as its only constructor argument and must extend Jul6Art\CoreBundle\Event\AbstractEvent.

All actions in listeners who listen these event class consts will be async

You can also specify which doctrine events you want to track

Available events are

Real-time entity feed

Everything above pushes messages you write yourself. This part pushes them for you: annotate an entity, and every insert, update and delete on it emits a small Mercure update.

Mercure\EntityChangePublisher reads the attribute on Doctrine's onFlush / postFlush. There is nothing else to wire — but there are three things to know before relying on it.

The payload carries no business data, on purpose

A subscriber receives everything published on a topic it is allowed to listen to, without passing through a voter. Putting a field value in the payload would therefore broadcast it past every access rule you have. Consumers refetch through the API, which is where those rules live.

changedFields is a whitelist, not a diff: only the intersection of what actually changed with what the attribute names is exposed, so a client can decide whether a change concerns it without learning about the fields you did not list.

The topic is your decision

The bundle publishes on whatever Mercure\FeedTopicResolverInterface returns, and ships GlobalFeedTopicResolver — everything on /global/feed. That is right for a single tenant and a leak for two.

⚠️ Do not let a tenant-scoped entity fall back to the shared topic. Every tenant user is subscribed to /global/feed, so a row landing there leaks its existence and triggers a reload for everyone. The example routes it to /admin/feed, which only an administrator's token covers. This mistake is silent: the feed keeps working, for too many people.

The topic is also how a burst is grouped: more than EntityChangePublisher::BURST_THRESHOLD entities of one type on one topic in a single flush collapse into a single action: "bulk" event carrying a count. Importing 500 rows then costs one reload per subscriber instead of 500.

A hub that is down must not break a write

Publishing inside postFlush means an HTTP call inside $em->flush(). A slow hub makes a slow response; an unreachable one throws, and the user gets a 500 on a write that succeeded.

Mercure\BufferingHub decorates the hub so publish() only fills an in-memory buffer, and Mercure\MercureDrainListener empties it on kernel.terminate — after the response has left — and on console.terminate for commands. A hub failure there is logged and swallowed.

It is on by default. The trade is explicit: between the response and the drain there is a millisecond-scale window where the client has been told "saved" and subscribers have not heard yet, and if the process dies in between those updates are lost. No data is lost — the row is committed — only a notification, and the next page load shows the new state anyway.

Letting a browser subscribe

A subscriber authenticates with a JWT carrying a mercure.subscribe claim, and an EventSource cannot send an Authorization header — hence a cookie scoped to the hub path. Mercure\SubscriberCookieFactory mints both:

Which topics an account may subscribe to stays in your application — it is an authorisation decision and the claim is what enforces it on the hub. Hand the same list back in the response so the front end subscribes to exactly what the token allows; deriving it twice is how the two drift.

⚠️ *`is a wildcard on both sides.** A claim of['*']` covers every topic, present and future. Convenient for an administrator, a tenant leak for anyone else.

Without jwt_secret the factory is not registered — signing a subscriber token with anything but the hub's own secret produces a token the hub rejects, which reads as "real-time is broken" rather than "the configuration is wrong".

Messenger routing and buffering are alternatives, not layers

With push.async: true — the default — this bundle routes Symfony\Component\Mercure\Update to the async_priority_high transport, so a worker publishes it instead of the request. That is a second way of solving the same problem the buffering hub solves, and running both is not twice as safe:

⚠️ Routing to async_priority_high requires a worker consuming that transport. An application whose supervisor only runs messenger:consume async will queue every real-time update into a transport nobody drains, and the feed stops — silently, with the rows committed and the queue growing. Check your worker before leaving async: true, and remember that an application with no #[Asyncable] entity has nothing else to gain from it.

The trap worth repeating

No hub, no publishing — silently. The whole real-time stack is registered only when the application configures mercure.hubs; without it, #[BroadcastableEntity] emits nothing and reports nothing. That is deliberate — an application can install this bundle for its Messenger side alone — but it means "my events never arrive" and "I never configured a hub" look identical.

Quality assurance

License

The Push Bundle is open-sourced software licensed under the MIT license.

© 2026 jul6art


All versions of push-bundle with dependencies

PHP Build Version
Package Version
Requires php Version ^8.5
doctrine/orm Version ^3.3
doctrine/persistence Version ^3.4 || ^4.0
jul6art/core-bundle Version ^2.0.1 || ^3.0
symfony/config Version ^7.4 || ^8.0
symfony/dependency-injection Version ^7.4 || ^8.0
symfony/http-kernel Version ^7.4 || ^8.0
symfony/mercure Version ^0.9
symfony/mercure-bundle Version ^0.6
symfony/messenger Version ^7.4 || ^8.0
symfony/service-contracts Version ^3.5
symfony/yaml Version ^7.4 || ^8.0
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package jul6art/push-bundle contains the following files

Loading the files please wait ...