Git Product home page Git Product logo

Comments (3)

CHenzel avatar CHenzel commented on June 26, 2024 2

@antonioperic
Make an TranslationWalker is too complex

It's more easier to make that manually

Some solutions with api-platform

Create an HydrationExtension

final class HydrationExtension implements ContextAwareQueryCollectionExtensionInterface, QueryItemExtensionInterface
{
    private $patranslator; //Locastic\ApiPlatformTranslationBundle\Translation\Translator

    public function __construct(
        PaTranslator $translator,
    ) {
....
        $this->patranslator = $translator;
....
    }
    /**
     * {@inheritdoc}
     */
    public function applyToCollection(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, string $operationName = null, array $context = [])
    {
        $this->addHydrationToCollection($queryBuilder, $resourceClass, $operationName, $context);
    }

    /**
     * {@inheritdoc}
     */
    public function applyToItem(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, array $identifiers, string $operationName = null, array $context = [])
    {
        $this->addTranslationHydrationToItem($queryBuilder, $resourceClass, $operationName);
    }

    /**
     * @param QueryBuilder $queryBuilder
     * @param string       $resourceClass
     * @param string       $operationName
     * @param mixed        $context
     */
    private function addTranslationHydrationToCollection(QueryBuilder $queryBuilder, string $resourceClass, string $operationName, $context)
    {
        $locale = $this->patranslator->loadEntityCurrentLocale($resourceClass);
        $rootAlias = $queryBuilder->getRootAliases()[0];
        if (
            BlogPost::class === $resourceClass ||
           Tag::class === $resourceClass ||
           ......
        ) {
            $queryBuilder->addSelect('t');
            //Manage filter
            $findFilterTranslations = false;
            if (isset($context['filters']) && is_array($context['filters'])) {
                foreach ($context['filters'] as $key => $value) {
                    if (Utils::starts_with($key, 'translations.')) {
                        $findFilterTranslations = true;
                        break;
                    }
                }
            }
            if ($findFilterTranslations ) {
                $queryBuilder->leftJoin($rootAlias.'.translations', 't', Join::WITH, 't.locale = :locale');
                $queryBuilder->setParameter('locale', $locale);
            } else {
                $queryBuilder->leftJoin($rootAlias.'.translations', 't', Join::WITH);
            }
            //You can join other object link to translations
            if (Tag::class === $resourceClass) {
                $queryBuilder->addSelect('ti');
                $queryBuilder->leftJoin('t.image', 'ti', Join::WITH);
            }
        }
    }

    /**
     * @param QueryBuilder $queryBuilder
     * @param string       $resourceClass
     * @param string       $operationName
     */
    private function addTranslationHydrationToItem(QueryBuilder $queryBuilder, string $resourceClass, string $operationName)
    {
        $rootAlias = $queryBuilder->getRootAliases()[0];
        if (
            BlogPost::class === $resourceClass ||
            Tag::class === $resourceClass ||
            .....
        ) {
            $queryBuilder->addSelect('t');
            $queryBuilder->leftJoin($rootAlias.'.translations', 't', Join::WITH);

            if (Tag::class === $resourceClass) {
                $queryBuilder->addSelect('ti');
                $queryBuilder->leftJoin('t.image', 'ti', Join::WITH);
            }
            ......
        }
    }

    /**
     * @param QueryBuilder $queryBuilder
     * @param string       $resourceClass
     * @param string       $operationName
     * @param mixed        $context
     */
    private function addHydrationToCollection(QueryBuilder $queryBuilder, string $resourceClass, string $operationName, $context)
    {
        $this->addTranslationHydrationToCollection($queryBuilder, $resourceClass, $operationName, $context);
    }
}

Other tips : when doctrine need to automatically JOIN missing values (translations), you can make two queries to pre-hydrate what doctrine needs on the second query.

Example nested Tree with translations

...
        //First Query to get childs with translations
        $queryBuilder = $repo->createQueryBuilder('ca')
        ->select('ca', 't')
        ->leftjoin('ca.translations', 't')
        ->where('ca.parent IS NOT NULL')
        ...;
        $query = $queryBuilder->getQuery();
        $query->getResult(); //Results will be not use but pre-hydrate childs translations for second query
....
       //Second Query 
        $queryBuilder = $repo->createQueryBuilder('ca')
        ->where....;

        $query = $queryBuilder->getQuery();
        $tree = $query->getResult('tree'); //Result return by controller

We have just two queries in symfony profiler and if we use redis cache it's zero.
It's not the best solutions but it's working

from apiplatformtranslationbundle.

antonioperic avatar antonioperic commented on June 26, 2024

@CHenzel do you maybe have some solution for this?

from apiplatformtranslationbundle.

antonioperic avatar antonioperic commented on June 26, 2024

@CHenzel ping for this one

from apiplatformtranslationbundle.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.