ux icon indicating copy to clipboard operation
ux copied to clipboard

[ExpressionLanguage] Add function `service`

Open seb-jean opened this issue 1 year ago • 11 comments

Symfony version(s) affected

7.0.7

Description

I have an error :

The function "service" does not exist around position 1 for expression `service('App\Service\Generator').generate('songs_by_artist_' ~ entity.getId())`.

How to reproduce

I have the following entity:

<?php

namespace App\Entity;

use App\Repository\BookRepository;
use Doctrine\ORM\Mapping as ORM;
use Symfony\UX\Turbo\Attribute\Broadcast;

#[ORM\Entity(repositoryClass: BookRepository::class)]
#[Broadcast(topics: ["@=service('App\\Service\\Generator').generate('songs_by_artist_' ~ entity.getId())", 'books'], template: 'broadcast/Book.stream.html.twig', private: true)]
class Book
{
    #[ORM\Id]
    #[ORM\GeneratedValue]
    #[ORM\Column]
    private ?int $id = null;

    #[ORM\Column(length: 255)]
    private ?string $title = null;

    public function getId(): ?int
    {
        return $this->id;
    }

    public function getTitle(): ?string
    {
        return $this->title;
    }

    public function setTitle(string $title): static
    {
        $this->title = $title;

        return $this;
    }
}

But when I create a Book entity, I get the following error:

The function "service" does not exist around position 1 for expression `service('App\Service\Generator').generate('songs_by_artist_' ~ entity.getId())`.

In my case, $this->functions is enum and constant : https://github.com/symfony/symfony/blob/7.1/src/Symfony/Component/ExpressionLanguage/Parser.php#L242

Possible Solution

No response

Additional Context

No response

seb-jean avatar May 16 '24 10:05 seb-jean

I think this is more something related to https://github.com/symfony/ux

Kocal avatar May 28 '24 06:05 Kocal

This has never been possible as i see it .. I believe expression language is used there to compose topic names based on the enttity props.

Or am i missing something ?

smnandre avatar May 28 '24 19:05 smnandre

Yes but I saw in the documentation below that it was possible to use the service function in expression languages: https://symfony.com/doc/current/service_container/expression_language.html

seb-jean avatar May 28 '24 19:05 seb-jean

... in the service container:)

smnandre avatar May 28 '24 19:05 smnandre

Yes, but the ExpressionLanguage used in the service container's configuration is configured to access the Symfony Container (or at least something to fetch services from), which was never the case here with Symfony\UX\Turbo\Attribute\Broadcast attribute.

Maybe you can achieve what you want by tweaking the Symfony Container by using some Compiler Pass, or maybe you can go for an easier solution by moving your logic into a (static?) method in your entity.

Kocal avatar May 28 '24 19:05 Kocal

So, won't fix?

seb-jean avatar May 28 '24 20:05 seb-jean

Maybe we can find another alternative, instead of passing the whole container, we can inject a service that could be configured under broadcard.topic_generator (or smth like that)?

Kocal avatar May 28 '24 21:05 Kocal

So, won't fix?

Maybe let's use another word than fix ... as this is a request for a feature (that has never existed in the first place, right ? 😅)

Could you give you the final usage you're looking after, so maybe we can suggest other ways to achieve it ?

smnandre avatar May 28 '24 21:05 smnandre

Maybe we can find another alternative, instead of passing the whole container, we can inject a service that could be configured under broadcard.topic_generator (or smth like that)?

Yes, why not :).

Maybe let's use another word than fix ... as this is a request for a feature (that has never existed in the first place, right ? 😅)

Yes, it's true, you're right, sorry 😄.

Could you give you the final usage you're looking after, so maybe we can suggest other ways to achieve it ?

Currently, when I put:

<div id="book_{{ book.id }}" {{ turbo_stream_listen('book_detail_' ~ book.id) }}></div>

it becomes:

<div id="book_7" data-controller="symfony--ux-turbo--mercure-turbo-stream" data-symfony--ux-turbo--mercure-turbo-stream-topic-value="book_detail_7" data-symfony--ux-turbo--mercure-turbo-stream-hub-value="http://127.0.0.1:56215/.well-known/mercure"></div>

But with a generator, this will hash/encode the data-symfony--ux-turbo--mercure-turbo-stream-topic-value. It will then be more secure.

This line

<div id="book_{{ book.id }}" {{ turbo_stream_listen(('book_detail_' ~ book.id)|mercure_topic) }}></div>

will then become:

<div id="book_7" data-controller="symfony--ux-turbo--mercure-turbo-stream" data-symfony--ux-turbo--mercure-turbo-stream-topic-value="AiLvziwlkB5M9UpYKRyiHvDs/BK7t4T6B7CR48ropyA=" data-symfony--ux-turbo--mercure-turbo-stream-hub-value="http://127.0.0.1:56215/.well-known/mercure"></div>

seb-jean avatar May 29 '24 09:05 seb-jean

I like the idea, should it be something to add here or in the Mercure bundle ?

smnandre avatar May 29 '24 16:05 smnandre

You might as well do it directly in MercureBundle. But is there a downside?

seb-jean avatar May 29 '24 19:05 seb-jean

Thank you for this issue. There has not been a lot of activity here for a while. Has this been resolved?

carsonbot avatar Nov 30 '24 12:11 carsonbot

No resolved.

seb-jean avatar Nov 30 '24 13:11 seb-jean

I still doubt this repo is the best place to implement this feature.

smnandre avatar Nov 30 '24 18:11 smnandre

Closed in favor of https://github.com/symfony/ux/pull/2447

seb-jean avatar Apr 12 '25 11:04 seb-jean