TransWikia.com

ORM, Symfony 4, SQL Запрос

Stack Overflow на русском Asked by Winteriscoming on November 15, 2020

Объясните пожалуйста, как правильно сделать, мне необходимо получить результат следующего запроса:

select 
    value 
from variables 
where 
    id_language = (SELECT value FROM globalSetting WHERE code = 'lang' limit 1)
    and code = :code  

Для взаимодействия контроллера и сущности я использую следующий mapping :

AppEntityVariables:
  type: entity
  table: variables
  repositoryClass: AppRepositoryVariablesRepository
  id:
    id:
      type: guid
  fields:
    name:
      type: string
      length: 50
      nullable: false
    code:
      type: string
      length: 100
      nullable: false
    value:
      type: string
      length: 100
      nullable: false
    id_language:
      type: integer
      length: 11
      nullable: false  

Модель:

namespace AppEntity;
use DoctrineORMMapping as ORM;

class Variables
{
    private $id;
    private $name;
    private $code;
    private $value;
    private $id_language;

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

    public function getId_language(): int
    {
        return $this->id_language;
    }

    public function getValue(): string
    {
        return $this->value;
    }

}  

Контроллер :

namespace AppControllerAdmin;

use SymfonyBundleFrameworkBundleControllerController;
use SymfonyComponentHttpFoundationRequest;
use SymfonyComponentHttpFoundationResponse;
use SymfonyComponentSecurityHttpAuthenticationAuthenticationUtils;

class AdminsController extends Controller
{
    private $entityManger;

    public function __construct()
    {
        $this->entityManger = $this->getDoctrine()->getManager();
    }

    public function entrance(Request $request)
    {
        $title = "Admin panel";

        if($request->isMethod('POST'))
        {
            $error = "";
            $login = $request->get('login');
            $password = $request->get('password');

            $user = $this->entityManger->getRepository('App:Admins')
                ->findOneBy(array('login'=>$login));

            if(is_null($user))
            {
                $result = $this->entityManger->getRepository('App:Variables')->getLanguageMessage("AuthorizationError");
                   // ->findOneBy(array('id_language' => $langId, 'code' => 'AuthorizationError'));

                print_r($result);
            }


            return $this->render('adminlogin.html.twig', array('title' => $title, 'error' => $error));
        }
        else
        {
            return $this->render('adminlogin.html.twig', array('title' => $title));
        }
    }

    public function logIn()
    {
        return $this->render('adminlogin.html.twig');
    }
}  

И VariablesRepository:

<?php

namespace AppRepository;

use AppEntityProduct;
use DoctrineBundleDoctrineBundleRepositoryServiceEntityRepository;
use SymfonyBridgeDoctrineRegistryInterface;

/**
 * @method Product|null find($id, $lockMode = null, $lockVersion = null)
 * @method Product|null findOneBy(array $criteria, array $orderBy = null)
 * @method Product[]    findAll()
 * @method Product[]    findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
 */
class VariablesRepository extends ServiceEntityRepository
{
    public function __construct(RegistryInterface $registry)
    {
        parent::__construct($registry, Product::class);
    }

    public function getLanguageMessage($code)
    {
        $conn = $this->getEntityManager()->getConnection();

        $query =
        "
            select 
                value 
            from variables 
            where 
                id_language = (SELECT value FROM globalSetting WHERE code = 'lang' limit 1)
                and code = :code
        ";

        $stmt = $conn->prepare($query);
        $stmt->execute(['code' => $code]);

        // returns an array of arrays (i.e. a raw data set)
        return $stmt->fetchAll();
    }

//    /**
//     * @return Product[] Returns an array of Product objects
//     */
    /*
    public function findByExampleField($value)
    {
        return $this->createQueryBuilder('p')
            ->andWhere('p.exampleField = :val')
            ->setParameter('val', $value)
            ->orderBy('p.id', 'ASC')
            ->setMaxResults(10)
            ->getQuery()
            ->getResult()
        ;
    }
    */

    /*
    public function findOneBySomeField($value): ?Product
    {
        return $this->createQueryBuilder('p')
            ->andWhere('p.exampleField = :val')
            ->setParameter('val', $value)
            ->getQuery()
            ->getOneOrNullResult()
        ;
    }
    */
}  

Я изучаю symfony, до это как правило писал на чистом php, понимаю, что фреймворк должен мне облегчить жизнь, но пока все совсем наоборот, кажется все дико запутанным. Зачем вообще существуют классы Repository? Разве они не нужны только когда mapping прописывается в аннотациях? Пожалуйста подскажите. Без фреймворка я бы давным давно сделал то что мне нужно :(.

2 Answers

Что бросается в глаза

  1. nullable: false - это необязательно писать, так как nullable по умолчанию false.

  2. То что вы называете моделью некий объектный "образ" сущности, хранимой в БД.

  3. Очевидно, что из-за недостатка опыта, вы используете, на мой субъективный взгляд, более сложные подходы. Контроллер и репозиторий у вас это сервисы которые сами резолвят необходимые классы через DI:

Репозиторий

<?php

namespace AppRepository;

use DoctrineORMEntityManagerInterface;

/**
 * Class VariablesRepository
 * @package AppRepository
 */
class VariablesRepository
{
    /**
     * @var EntityManagerInterface
     */
    private $manager;

    /**
     * VariablesRepository constructor.
     *
     * @param EntityManagerInterface $manager
     */
    public function __construct(EntityManagerInterface $manager)
    {
        $this->manager = $manager;
    }

    /**
     * @param $code
     *
     * @return array
     * @throws DoctrineDBALDBALException
     */
    public function getLanguageMessage($code)
    {
        $conn = $this->manager->getConnection();

        $query =
            "
            select 
                value 
            from variables 
            where 
                id_language = (SELECT value FROM globalSetting WHERE code = 'lang' limit 1) and code = :code
        ";

        $stmt = $conn->prepare($query);
        $stmt->execute(['code' => $code]);
        return $stmt->fetchAll();
    }
}

Контроллер:

<?php

namespace AppController;

use AppRepositoryVariablesRepository;
use SymfonyComponentHttpFoundationRequest;
use SymfonyComponentHttpFoundationResponse;
use SymfonyComponentValidatorExceptionValidatorException;

/**
 * Class VariableController
 * @package AppController
 */
class VariableController
{
    /**
     * @var VariablesRepository
     */
    private $variableRepo;

    /**
     * VariableController constructor.
     *
     * @param VariablesRepository $variablesRepository
     */
    public function __construct(VariablesRepository $variablesRepository)
    {
        $this->variableRepo = $variablesRepository;
    }

    /**
     * @param Request $request
     *
     * @return Response
     * @throws DoctrineDBALDBALException
     */
    public function someAction(Request $request)
    {
        $code = $request->get('code');
        if (empty($code)) {
            throw new ValidatorException('code is null');
        }

        $message = $this->variableRepo->getLanguageMessage($code);
        return new Response($message);
    }
}

Надеюсь, я объяснил понятно

Answered by StereoFlo on November 15, 2020

Нашел ошибку, вот тут указан класс Product:

class VariablesRepository extends ServiceEntityRepository
{
    public function __construct(RegistryInterface $registry)
    {
        parent::__construct($registry, Product::class);
    }  

а надо Variables. Вопрос "Зачем Repository?" остался открытым, почему нельзя подобное написать в модели?

Answered by Winteriscoming on November 15, 2020

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP