rompetomp / inertia-bundle Goto Github PK
View Code? Open in Web Editor NEWInertia.js server-side adapter for Symfony
License: MIT License
Inertia.js server-side adapter for Symfony
License: MIT License
I don't know if this is the best place to tell this ...
but
With the Symfony => Inertia => vuejs we loose the HMR
( you can't use the webpack-encore server because you need the symfony render ... )
Today using a HMR is obvious for dev, but with this stack you can't ...
So after some researche we can use a old cousin of HMR: LiveReload
3 Step to get ready :
npm install --save-dev webpack-livereload-plugin
in webpack.config.js add :
if (!Encore.isProduction()) {
Encore.addPlugin(new LiveReloadPlugin());
}
{% if app.debug %}
<script src="http://localhost:35729/livereload.js"></script>
{% endif %}
First of all, thanks for providing a way to use Inertia.js with Symfony, I really want to take it for a test drive.
And this might be out of scope for your project but I still wanted to give it a shot. This project's README says:
Find a frontend adapter that you wish to use here https://github.com/inertiajs. The README's are using Laravel's Webpack Mix. It's not hard translating this to Webpack Encore, just follow the documentation
Actually it's hard for me, as I haven't worked with Encore or Mix before and only have basic Webpack knowledge. So maybe you could provide example configurations for one or more of the available adapters.
I would like to add compatibility for 8.0
in composer.json
.
That means there also have to be tests on 8.0 though...
Currently PHPUnit 6.5 is used in the CI script which doesn't support 8.0, I propose that can be bumped up to the latest greatest 9.x - might need some minor changes in the tests but that should be trivial.
Also I couldn't find any info on whether Travis CI supports 8.0. Are you okay with replacing the current usage of Travis CI with an equivalent GitHub action?
If that sounds like a good approach to you, I can prepare a PR. Also I haven't really tried it on 8.0 yet but I doubt the actual code needs any changes. Will see...
and so on.
Is it possible to update for symfony 7?
Is it possible for this bundle to send the Symfony-Debug-Toolbar-Replace
header (as described here: https://symfony.com/blog/new-in-symfony-4-1-self-updating-debug-toolbar) to replace the Symfony debug toolbar's "current page" with the request that responded to the Inertia.js page request (i.e. when clicking on an inertia powered link)?
I didn't see mention of this in the docs at all (and nothing came up when searching here on github).
Currently just the XHR section of the toolbar updates when navigating via inertia links.
Thanks for your work on this bundle!
I think I'm missing something regarding sending a collection of entities to be rendered by Inertia. I have the following action:
/**
* @Route("/item/", name="item_list")
*/
public function itemList(InertiaInterface $inertia, ItemRepository $repo)
{
return $inertia->render('ItemList', [
'items' => $repo->findAll(),
]);
}
Which works great when doing a hard browser refresh:
<div id="app" data-page="{"component":"ItemList","props":{"items":[{"id":1,"name":"Bike","price":"150.00"},{"id":2,"name":"Car","price":"2500.00"},...}]},"url":"\/item\/","version":null}"></div>
But returns empty objects in the xhr response:
{"component":"ItemList","props":{"items":[{},{},{},{},{},{},{},{},{},{}]},"url":"\/item\/","version":null}
What am I missing?!
Since #42 landed I noticed a bug in this bundle.
When rendering certain data I ended up getting an ArgumentCountError
, and in this specific case it was because PHP's system
global function was trying to be called with 0 arguments. This seemed odd because we don't call system
anywhere in our code.
It seems that this is due to the is_callable
check that was added in #42. In our case, we had a value that was System
for an item in an array (not a parent level prop, but an array of data that we were passing to Inertia).
is_callable
will accept a string as the first parameter, and if that string is a global function name (which system
is, https://www.php.net/system) is_callable
will return true
and then try to execute that function in the call_user_func
that follows (https://github.com/rompetomp/inertia-bundle/blob/master/Service/Inertia.php#L160) which is probably not the intent here.
The previous behavior of checking if the prop was a Closure
didn't have this issue. I suspect anyone that has basic string props that happen to match a global PHP function name will also run into this issue of inertia trying to execute PHP functions when the prop itself was just a simple string.
I'm trying to use inertia to post to the login form but the form is sent in the body as json, which is not being understood by the symfony/security-bundle
Is there a way to convert the post request to use a normal HTTP payload instead, or to convert the received json to the $request->request automatically?
Hi Hannes,
not sure if you are up for this lengthy and rather inconvenient issue - as you said you were not using the project any more - but I'll try my luck anyway.
TLDR: see the PR, I guess... #20
I am currently using the bundle in a project where the Vue side of things expects an empty errors
object to determine that there were no errors.
In the current state of the bundle, it seems impossible to get an empty object - in my case it's just a new ArrayObject()
- all the way through to the JSON string that is finally returned by the render
method of Inertia
and I always end up with this warning in the console:
[Vue warn]: Invalid prop: type check failed for prop "errors". Expected Object, got Array
If my findings 🕵🏻♂️ are correct, this is due to two things:
I. When Symfony's Serializer
is found in the serialize
method of Inertia
(as in my case), the objects in $page
eventually make their way through AbstractObjectNormalizer
which will return an empty array for empty objects - unless the key preserve_empty_objects
is present in the context.
Relevant excerpt from AbstractObjectNormalizer
:
$data = [];
[...]
if (isset($context[self::PRESERVE_EMPTY_OBJECTS]) && !\count($data)) {
return new \ArrayObject();
}
return $data;
So my first proposal would be to add preserve_empty_objects
to the context that is passed from the serialize
method in Inertia
, like so:
if (null !== $this->serializer) {
$json = $this->serializer->serialize($page, 'json', array_merge([
'json_encode_options' => JsonResponse::DEFAULT_ENCODING_OPTIONS,
AbstractNormalizer::CIRCULAR_REFERENCE_HANDLER => function () { return null; },
AbstractObjectNormalizer::PRESERVE_EMPTY_OBJECTS => true,
], $context));
} else {
$json = json_encode($page);
}
(Sidenote: if the Serializer
is not found and json_encode
is used instead, all is fine so far. But that's unlikely in a Symfony project...)
All right, one down.
II. Now at the very end of the serialize
method, this happens:
return json_decode($json, true) ?? [];
The second parameter is true
, meaning JSON objects will be returned as associative arrays
(as the PHP docs tell us), so this will once again turn all our carefully preserved objects in $json
to arrays.
I don't think this was intended and you mainly set it to true
to be able to return an array instead of the odd stdClass
object that json_decode
gives us when this is not set.
I think we can fix this by just replacing it with:
return (array) json_decode($json, false);
Now I am finally getting my desired empty object in the final response sent by Symfony.
The downside is: this might break things for users of your bundle who are (unknowingly) relying on this behavior. But I would assume it was never your intention to actually cast or manipulate any objects or types.
What do you think?
Also maybe @innocenzi has some thoughts on this as well, as he added the Serializer
feature.
Hi there!
I have been experimenting with this bundle but just realized that it is missing one of the key features of Inertia: the server-side rendering mode.
Is it on a roadmap? In the works?
If not, would you eventually accept a PR for it?
Hi again, I ran into a case where I could use some view data only for Twig, without passing it to the front-end.
inertia-bundle/Service/Inertia.php
Line 70 in 1d25664
Maybe just allowing a third argument, $viewData
, would be enough? Then you would just add it to the compact
method on the render.
$response->setContent($this->engine->render($this->rootView, compact('page', 'viewData')));
This way, the page
variable will still be accessible to the Twig extension without any change, and we could use some other data for Twig.
It wouldn't cover all cases though. We could allow to do the same as shared data: allow adding view data in an event subscriber, and then merge the render
method's viewData
argument with the sharedViewData
.
$viewData = array_merge($this->sharedViewData, $viewData);
$response->setContent($this->engine->render($this->rootView, compact('page', 'viewData')));
Hello, with the last update (2.3.1) It's required to have that is a config file :
rompetomp_inertia:
ssr:
enabled: false
url: 'http://127.0.0.1:13714/render'
Otherwise it throws an error. Maybe do a check to make it optional? Or add it in a recipe.
Rompetomp\InertiaBundle\Service\Inertia::setSsrUrl(): Argument #1 ($url) must be of type string, null given, called in /app/var/cache/dev/ContainerLcyDPuy/App _KernelDevDebugContainer.php on line 1664
Happens when executing cache:clear
(so right after installation). It is fixed by adding an empty string as url in the rompetomp_inertia.yaml
config file.
I've been desperately trying to make the "Remember Me' feature work with Inertia Bundle, but no luck so far. Any clue on how to have the REMEMBERME cookie set after login?
Hello, thanks for this nice bundle.
I have a little problem with settings version for Inertia. When i set in my subscriber version, i get always refresh.
for example if i set this as my version
$this->inertia->version('123')
i would except to not get refresh on every request. After a little debugging i found, that in InertiaListener.php
theres a condition for checking versions. (i am not be dev) After dump, i can see version is null.
var_dump($request->headers->get('X-Inertia-Version')); var_dump($this->inertia->getVersion());
Results in:
/srv/app/vendor/rompetomp/inertia-bundle/EventListener/InertiaListener.php:38:string '123' (length=3) /srv/app/vendor/rompetomp/inertia-bundle/EventListener/InertiaListener.php:39:null
Hi,
We would like to use two root views in a project, as we have 2 separate frontend applications that need a different set of assets. As far as I can see, we can configure only a single root_view. Is it possible to have multiple?
Thanks for your work on the bundle!
When using the Link
component pages navigate correctly but when you input a page via the address bar I get the following exception:
12:36:38.709 critical | Uncaught PHP Exception Twig\Error\RuntimeError: "An exception has been thrown during the rendering of a template ("Response body is empty.")." at /Users/xxx/Sites/symfony/app/templates/app.html.twig line 5
It looks like it's dying at:
{{ inertiaHead(page) }}
Any ideas what's up, or any additional info you need?
Redirecting doesn't work properly when issuing a POST request. It pops up in a Modal.
I have a entity that contains another entity...
I load the entity througth doctrine and passe it to the inertia render.
$transaction = $this->getDoctrine()->getRepository(Transaction::class)->find($id);
return $inertia->render('transaction/show', [
'entity' => $transaction
]);
But when i inspect the entity with the vue-devtool a found some properties in it ( seem from doctrine ? ) !
So...
I think we are all ok with the fact we didn't want __cloner__
, __initializer__
and __isInitialized__
...
But, its my jobs to sananitize my object before sending it to inertia ( and the sf serializer ) ?
I have to use a real serializer at this point ?
Ok we can concidere this like a bug in this vendor and we need to finding a walkaround (PR) ?
Could you update this to Symfony 6?
Hi, I'm quite confused about shared properties in this bundle. They seem to not be added in the response?
inertia-bundle/Service/Inertia.php
Lines 66 to 95 in e95c179
I think adding $props = array_merge($this->sharedProps, $props);
at the start of the function would handle it correctly.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.