Semantical error is not defined

API Platform version(s) affected: 3.0.0 | 3.0.1 Description When upgraded from 2.7.0 to 3.0.0, I used the automatic tool provided by ApiPlatform. It created some more operations on my entities but ...

API Platform version(s) affected: 3.0.0 | 3.0.1

Description
When upgraded from 2.7.0 to 3.0.0, I used the automatic tool provided by ApiPlatform.

It created some more operations on my entities but they seem not work.

For example, I have an Account entity and a Channel entity like below:

# Entity/Account

#[ApiResource]
#[Entity(repositoryClass: AccountRepository::class)]
class Account implements Stringable, Timestampable
{
    use TimestampableEntity;

    #[Column(name: 'id', type: Types::INTEGER)]
    #[Id]
    #[GeneratedValue(strategy: 'IDENTITY')]
    private int $id;

    #[OneToMany(targetEntity: Channel::class, mappedBy: 'account')]
    private Collection $channels;

    ...
}
# Entity/Channel

#[APIApiResource]
#[APIApiResource(uriTemplate: '/accounts/{id}/channels.{_format}', uriVariables: ['id' => new APILink(fromClass: Account::class, identifiers: ['id'])], status: 200, operations: [new APIGetCollection()])]
#[APIApiResource(uriTemplate: '/users/{id}/accounts/{accounts}/channels.{_format}', uriVariables: ['id' => new APILink(fromClass: User::class, identifiers: ['id']), 'accounts' => new APILink(fromClass: Account::class, identifiers: ['id'])], status: 200, operations: [new APIGetCollection()])]
#[Entity(repositoryClass: ChannelRepository::class)]
class Channel implements ConfigurableRemote, Stringable, Timestampable
{
    use RemoteTrait;
    use TimestampableEntity;

    #[Column(name: 'id', type: Types::INTEGER)]
    #[Id]
    #[GeneratedValue(strategy: 'IDENTITY')]
    private int $id;

    #[ManyToOne(targetEntity: Account::class, inversedBy: 'channels')]
    private Account $account;

    ...
}

When I call /api/accounts/1/channels, I get the following error from Doctrine:

[Semantical Error] line 0, col 63 near ‘o_a1.id = :id_p1’: Error: ‘o_a1’ is not defined.

Additional Context

The query that causes the bug is this:

SELECT o FROM AppEntityChannel o WHERE o_a1.id = :id_p1 ORDER BY o.id ASC

As you can see, it uses o_a1 as table alias, while it sets the alias of the table to o. So it seems there is a problem generating the correct DQL.

Digging into the code following the origin of the bug, I came to the trait ApiPlatformDoctrineOrmStateLinksHandlerTrait::57:

This is the interested code:

            if (!$link->getFromProperty() && !$link->getToProperty()) {
                $doctrineClassMetadata = $manager->getClassMetadata($link->getFromClass());
/* 57 */        $currentAlias = $link->getFromClass() === $resourceClass ? $alias : $queryNameGenerator->generateJoinAlias($alias);

                foreach ($identifierProperties as $identifierProperty) {
                    $placeholder = $queryNameGenerator->generateParameterName($identifierProperty);
                    $queryBuilder->andWhere("$currentAlias.$identifierProperty = :$placeholder");
                    $queryBuilder->setParameter($placeholder, $this->getIdentifierValue($identifiers, $hasCompositeIdentifiers ? $identifierProperty : null), $doctrineClassMetadata->getTypeOfField($identifierProperty));
                }

                $previousAlias = $currentAlias;
                $previousJoinProperties = $doctrineClassMetadata->getIdentifierFieldNames();
                continue;
            }

At line «57» the code is executed well: I have two classes:

  • Account
  • Channel

so the code correctly calls the method $queryNameGenerator->generateJoinAlias($alias).

The problem is that the query builder passed, in the DQL parts, for the select part, has the o value already set while the method $queryNameGenerator->generateJoinAlias($alias) returns o_a1.

Possible solution

The solution I tested is very simple: change === with !==:

            if (!$link->getFromProperty() && !$link->getToProperty()) {
                $doctrineClassMetadata = $manager->getClassMetadata($link->getFromClass());
- /* 57 */        $currentAlias = $link->getFromClass() === $resourceClass ? $alias : $queryNameGenerator->generateJoinAlias($alias);
+ /* 57 */        $currentAlias = $link->getFromClass() !== $resourceClass ? $alias : $queryNameGenerator->generateJoinAlias($alias);

                foreach ($identifierProperties as $identifierProperty) {
                    $placeholder = $queryNameGenerator->generateParameterName($identifierProperty);
                    $queryBuilder->andWhere("$currentAlias.$identifierProperty = :$placeholder");
                    $queryBuilder->setParameter($placeholder, $this->getIdentifierValue($identifiers, $hasCompositeIdentifiers ? $identifierProperty : null), $doctrineClassMetadata->getTypeOfField($identifierProperty));
                }

                $previousAlias = $currentAlias;
                $previousJoinProperties = $doctrineClassMetadata->getIdentifierFieldNames();
                continue;
            }

Doing this simple change, makes the DQL being generated correctly.

As I don’t know deeply the internals of Api Platform, I don’t know if this is an actual fix or simply a lucky shot.

UPDATE

Continuing to work on this, it seems the fix I provided is wrong: the problem is the logic is broken.

The fix I provided works with GetCollection.

But with Get it is completely broken (or, maybe, the documentation is wrong and I’m missing something in configuration of operations).

Anyway, the two DQL queries generated are wrong in any case:

$currentAlias = $link->getFromClass() !== $resourceClass ? $alias : $queryNameGenerator->generateJoinAlias($alias);

generates

SELECT o FROM CoommercioAppCoommercioEntityChannel o WHERE o.id = :id_p1 AND o_a1.id = :id_p2

while

$currentAlias = $link->getFromClass() === $resourceClass ? $alias : $queryNameGenerator->generateJoinAlias($alias);

generates

SELECT o FROM CoommercioAppCoommercioEntityChannel o WHERE o_a1.id = :id_p1 AND o.id = :id_p2

In both cases, the alias o_a1 is not defined.

More, the query seems to be wrong also for the fields it uses. The correct one should be similar to this:

SELECT o FROM CoommercioAppCoommercioEntityChannel o WHERE o.id = :id_p1 AND o.account_id = :id_p2

394 votes

1 answers

Get the solution ↓↓↓

your learning Symfony neighbor here,

I am calling a method from my controller through Ajax on a select change.
I manage to get the data I send to the controller, but I’m struggling as I try to make a Select with the data I get, for some reason, no matter the existing column I decide to return, I get a «specifiedColumn is not defined» and I can’t figure out why.

Here’s my method :

public function getPricesAction(Request $request)
{

            $first = $request->request->get('first');
            $final = $request->request->get('final');

            $em = $this->getDoctrine()->getManager();

    //not too sure about stacking 2 setParameter here, guess there's a better way. But even if I just use one parameter, I still get the same error 'id is not defined'.
            $getPrice = $em->createQuery('SELECT id FROM CarsBundle:Travel t WHERE t.first = :tst and t.final = :tfi')->setParameter('tre', $first)->setParameter('tra', $final);
            $result = $getPrice->getResult();

            return new JsonResponse($result);

}

I am using Symfony 3.3

thanks for the help !

2022-08-2

Write your answer


578

votes

Answer

Solution:

$getPrice = $em->createQuery('SELECT id FROM CarsBundle:Travel t WHERE t.first = :tst and t.final = :tfi')->setParameter('tre', $first)->setParameter('tra', $final);

Should be:

$getPrice = $em->createQuery('SELECT id FROM CarsBundle:Travel t WHERE t.first = :tst and t.final = :tfi')->setParameter('tst', $first)->setParameter('tfi', $final);

You got the wrong parameter name


Share solution ↓

Additional Information:

Date the issue was resolved:

2022-08-2

Link To Source

Link To Answer
People are also looking for solutions of the problem: dompdf image not found or type unknown

Didn’t find the answer?

Our community is visited by hundreds of web development professionals every day. Ask your question and get a quick answer for free.


Similar questions

Find the answer in similar questions on our website.

229

March 23, 2018, at 7:02 PM

your learning Symfony neighbor here,

I am calling a method from my controller through Ajax on a select change.
I manage to get the data I send to the controller, but I’m struggling as I try to make a Select with the data I get, for some reason, no matter the existing column I decide to return, I get a «specifiedColumn is not defined» and I can’t figure out why.

Here’s my method :

public function getPricesAction(Request $request)
{
            $first = $request->request->get('first');
            $final = $request->request->get('final');
            $em = $this->getDoctrine()->getManager();
    //not too sure about stacking 2 setParameter here, guess there's a better way. But even if I just use one parameter, I still get the same error 'id is not defined'.
            $getPrice = $em->createQuery('SELECT id FROM CarsBundle:Travel t WHERE t.first = :tst and t.final = :tfi')->setParameter('tre', $first)->setParameter('tra', $final);
            $result = $getPrice->getResult();
            return new JsonResponse($result);
}

I am using Symfony 3.3

thanks for the help !

Answer 1

$getPrice = $em->createQuery('SELECT id FROM CarsBundle:Travel t WHERE t.first = :tst and t.final = :tfi')->setParameter('tre', $first)->setParameter('tra', $final);

Should be:

$getPrice = $em->createQuery('SELECT id FROM CarsBundle:Travel t WHERE t.first = :tst and t.final = :tfi')->setParameter('tst', $first)->setParameter('tfi', $final);

You got the wrong parameter name

  • 05:30

    Trying to take the file extension out of my URL

  • 04:00

    display list that in each row 1 li

  • 00:00

    Read audio channel data from video file nodejs

  • 10:30

    session not saved after running on the browser

  • 9:10

    Best way to trigger worker_thread OOM exception in Node.js

  • 07:40

    Firebase Cloud Functions: PubSub, «res.on is not a function»

  • 04:00

    TypeError: Cannot read properties of undefined (reading ‘createMessageComponentCollector’)

  • 9:20

    AWS XRAY on Fargate service

  • 7:40

    How to resolve getting Error 429 Imgur Api

Rent Charter Buses Company

Posted By: Anonymous

I have a problem with getting data from the database using the expr() method function. I would like to get data where isPublic = true and objectType = $objectType OR user = $user and objectType = $objectType, no matter what the value of isPublic is.

I’m getting this error:

[Semantical Error] line 0, col 76 near 'user-avatar)': Error: 'user' is not defined.

My code in repository:

    public function findByObjectType($objectType, $user)
    {
        $qb = $this->createQueryBuilder('s');

        return $qb->where($qb->expr()->andX(
                $qb->expr()->eq('s.isPublic', true),
                $qb->expr()->eq('s.objectType', $objectType)
            ))
            ->orWhere($qb->expr()->andX(
                $qb->expr()->eq('s.user', $user->getId()),
                $qb->expr()->eq('s.objectType', $objectType)
            ))
            ->getQuery()
            ->getResult();
    }

where: $objectType = 'user-avatar'; $user = UserInterface

Solution

expr()->eq() will treat the expression as literals, trying to use them literally as they appear on method call.

As mentioned by the library author:

You are not using parameter binding. Expressions use string concatenation internally, so this outcome is actually expected.

In your case, you should be doing something like::

 return $qb->where($qb->expr()->andX(
        $qb->expr()->eq('s.isPublic', ':true'),
        $qb->expr()->eq('s.objectType', ':objectType')
    ))
    ->orWhere($qb->expr()->andX(
        $qb->expr()->eq('s.user', ':userId'),
        $qb->expr()->eq('s.objectType', ':objectType')
    ))

    ->setParameter('true', true)
    ->setParameter('userId', $user->getId())
    ->setParameter('objectType', $objectType)

    ->getQuery()
    ->getResult();

This way your code is easier to read, safer and more portable.

Answered By: Anonymous

Related Articles

  • How to prevent scrolling the whole page?
  • error LNK2005: ✘✘✘ already defined in…
  • Vue.JS & Spring Boot — Redirect to homepage on 404
  • Fastest way to pad a dataframe with uneven columns
  • How to map values in a dataframe to a key with values…
  • C++ template,typename and operator
  • Laravel Concat to get first name + middle name + last name
  • How to filter a RecyclerView with a SearchView
  • Unexpected end of JSON input while parsing
  • Form field border-radius is not working only on the last…

Disclaimer: This content is shared under creative common license cc-by-sa 3.0. It is generated from StackExchange Website Network.

Понравилась статья? Поделить с друзьями:
  • Semantic error читать новеллу
  • Security error this phone has been flashed with unauthorized software is locked что делать nokia
  • Semantic error перевод
  • Security error this phone has been flashed with unauthorized software is locked call your mobile
  • Semantic error перевести