Не удается получить доступ к настраиваемому репозиторию, не связанному с какой-либо сущностью из контроллера в symfony 3.4?

Я пытаюсь получить доступ к настраиваемому репозиторию, который содержит настраиваемые необработанные sql-запросы доктрины, и репозиторий не связан ни с одним объектом, но я получаю сообщение об ошибке:

Cannot autowire service "app_bundle_custom_respository": argument "$em" of method "Doctrine\ORM\EntityRepository::__construct()" has no type-hint, you should configure its value explicitly.

services.yaml:

# Learn more about services, parameters and containers at
# https://symfony.com/doc/current/service_container.html
parameters:
    #parameter_name: value

services:
    AppBundle\Twig\AppExtension:
        public: false
        tags: ['twig.extension']
    # default configuration for services in *this* file
    _defaults:
        # automatically injects dependencies in your services
        autowire: true
        # automatically registers your services as commands, event subscribers, etc.
        autoconfigure: true
        # this means you cannot fetch services directly from the container via $container->get()
        # if you need to do this, you can override this setting on individual services
        public: false

    # makes classes in src/AppBundle available to be used as services
    # this creates a service per class whose id is the fully-qualified class name
    AppBundle\:
        resource: '../../src/AppBundle/*'
        # you can exclude directories or files
        # but if a service is unused, it's removed anyway
        exclude: '../../src/AppBundle/{Entity,Repository,Tests}'

    # controllers are imported separately to make sure they're public
    # and have a tag that allows actions to type-hint services
    AppBundle\Controller\:
        resource: '../../src/AppBundle/Controller'
        public: true
        tags: ['controller.service_arguments']

    # add more services, or override services that need manual wiring
    # AppBundle\Service\ExampleService:
    #     arguments:
    #         $someArgument: 'some_value'

    app_bundle_custom_respository:
        class: AppBundle\Repository\CustomRepository
        public: true

DefaultController.php:

namespace AppBundle\Controller;

use AppBundle\Entity\EventType;
use AppBundle\Entity\VenueType;
use AppBundle\Repository\CustomRepository;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use AppBundle\Entity\Testimonial;
use AppBundle\Form\TestimonialSearchForm;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;


class DefaultController extends Controller
{
    /**
     * @Route("/", name = "homepage")
     */
    public function indexAction(Request $request)
    {
        $categories = array();
        $eventTypes = $this->getDoctrine()->getRepository(EventType::class)->findAllSortedByName(4, true, true);
        foreach ($eventTypes as $eventType) {
            $categories[] = array(
                "type" => "events",
                "name" => $eventType->getName(),
                "slug" => $eventType->getSlug(),
                "image" => $eventType->getImage()
            );
        }
        $venueTypes = $this->getDoctrine()->getRepository(VenueType::class)->findAllSortedByName(4, true, true);
        foreach ($venueTypes as $venueType) {
            $categories[] = array(
                "type"  => "venues",
                "name"  => $venueType->getName(),
                "slug"  => $venueType->getSlug(),
                "image" => $venueType->getImage()
            );
        }
        $recentBlogs = $this->get('app_bundle_custom_respository');
        $recentBlogs = $recentBlogs->getLatestBlogPosts();
        return $this->render('default/index.html.twig', [
            'categories' => $categories,
            'recentBlogs' => $recentBlogs
        ]);
    }
}

CustomRepository:

namespace AppBundle\Repository;

use Doctrine\ORM\EntityRepository;

class CustomRepository extends EntityRepository
{
    /**
     * Get the latest blog posts
     *
     * @return mixed
     */
    public function getLatestBlogPosts()
    {
        $sql = "SELECT wp_posts.ID, wp_posts.post_title, wp_posts.post_content, wp_posts.guid FROM wp_posts WHERE  post_type = 'post' AND  post_status = 'publish' ORDER BY post_date DESC LIMIT 2";
        $em = $this->getEntityManager();
        $stmt = $em->getConnection()->prepare($sql);
        $stmt->execute();
        $recentBlogs = $stmt->fetchAll();
        foreach ($recentBlogs as $k => $recentBlog) {
            $sql = "SELECT meta_value as thumbnail_info FROM wp_postmeta WHERE post_id= (SELECT meta_value FROM wp_postmeta WHERE meta_key= '_thumbnail_id' AND post_id = " . $recentBlog['ID'] . ") AND meta_key = '_wp_attachment_metadata'";
            $stmt = $em->getConnection()->prepare($sql);
            $stmt->execute();
            $img = $stmt->fetchAll();
            if (isset($img[0]['thumbnail_info'])) {
                $thumbnail_data = unserialize($img[0]['thumbnail_info']);
                $upload_directory = explode('/', $thumbnail_data['file']);
                $recentBlogs[$k]['img'] = "/blog/wp-content/uploads/$upload_directory[0]/$upload_directory[1]/".$thumbnail_data['sizes']['medium']['file'];
            }
        }
        return $recentBlogs;
    }
}

@TarasV: Спасибо, но предоставленная вами ссылка предназначена для репозиториев, которые используются для расширения ваших текущих сущностей, но мой репозиторий не имеет никакого отношения к какой-либо сущности.

Umair Shah Yousafzai 20.08.2018 16:40

Репозитории Doctrine требуют ссылки на объект. Все как есть. Вы создаете класс, который не расширяет EntityRepository, а просто вставляете диспетчер сущностей или объект подключения к базе данных.

Cerad 20.08.2018 16:42

@Cerad: На самом деле в этом репозитории нет объекта, с которым можно было бы связать это. Я хочу иметь собственный класс, в котором я могу хранить необработанные запросы на основе sql, которые получают разные типы вещей из базы данных? И можно ли легко получить доступ к этому классу в контроллере?

Umair Shah Yousafzai 20.08.2018 16:50

В этом нет особого смысла. Базовый EntityRepository из пакета Doctrine ORM требует, чтобы вы передали ему экземпляр ClassMetadata. Но из какого объекта вы бы передали это здесь, если ваш репозиторий ни с чем не связан? Глядя на то, что делает ваш класс репозитория, я бы просто не расширял класс EntityRepository и только вставлял экземпляр Connection, который вам нужен для выполнения SQL-запросов.

xabbuh 20.08.2018 16:53

@UmairShahYousafzai Оба ответа ниже иллюстрируют концепцию наличия репозиториев, отличных от Doctrine. Ни один из них не дает хороших примеров, но концепции действительны. Чего вам не хватает, так это хорошего понимания того, как внедрять сервисы в методы действий контроллера. Множество примеров в документации. Не используйте больше $ this-> getDoctrine (), и жизнь станет намного проще.

Cerad 20.08.2018 17:02

Спасибо вам обоим, @Cerad и @xabbuh. На самом деле я последовал предложению @xabbuh, ввел Connection и выполнил свою работу, и теперь все выглядит отлично. Спасибо

Umair Shah Yousafzai 20.08.2018 17:08
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
0
7
698
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Вы не должны расширять EntityRepository См. Это для более подробной информации: У вас есть собственный репозиторий, не связанный с сущностью в Symfony 2 / Doctrine 2?

class CustomRepository
{
    private $em;
    private $rsm;

    /**
     * NativeQuery constructor.
     * @param EntityManagerInterface $em
     */
    public function __construct(EntityManagerInterface $em)
    {
        $this->em = $em;
        $this->rsm = new ResultSetMapping();
    }

    private function setResultFields($resultFieldsArray)
    {
        foreach ($resultFieldsArray as $columnName => $alias) {
            if (is_string($columnName)) {
                $this->rsm->addScalarResult($columnName, $alias);
            } else {
                $this->rsm->addScalarResult($alias, $alias);
            }
        }
    }

    public function executeQuery($query, $resultFieldsArray)
    {
        $this->setResultFields($resultFieldsArray);
        $exec = $this->em->createNativeQuery($query, $this->rsm);
        return $exec->execute();
    }


    app_bundle_custom_respository:
    class: AppBundle\Repository\CustomRepository
            arguments:
                $em: '@doctrine.orm.default_entity_manager'        
            public: true




/**
 * @Route("/test", name = "test")
 * @return \Symfony\Component\HttpFoundation\Response
 */
public function test()
{
    $result = $this->container->get('app_bundle_custom_respository')->executeQuery('SELET * FROM table1', ['id', 'title', 'etc']);

Спасибо за ответ, но я ввел соединение DBAL и выполнил свою работу.

Umair Shah Yousafzai 20.08.2018 17:10
Ответ принят как подходящий

Я ввел DBAL Connection и выполнил работу, потому что моей единственной целью было использование Connection для выполнения необработанных запросов sql.

<?php

namespace AppBundle\Repository;

use Doctrine\DBAL\Connection;

class CustomRepository
{
    /**
    *
    * @var Connection
    */
    private $connection;
    public function __construct(Connection $dbalConnection)  {
        $this->connection = $dbalConnection;    
    }

    /**
     * Get the latest blog posts
     *
     * @return mixed
     */
    public function getLatestBlogPosts()
    {
        $sql = "SELECT wp_posts.ID, wp_posts.post_title, wp_posts.post_content, wp_posts.guid FROM wp_posts WHERE  post_type = 'post' AND  post_status = 'publish' ORDER BY post_date DESC LIMIT 2";
        $stmt = $this->connection->prepare($sql);
        $stmt->execute();
        $recentBlogs = $stmt->fetchAll();
        foreach ($recentBlogs as $k => $recentBlog) {
            $sql = "SELECT meta_value as thumbnail_info FROM wp_postmeta WHERE post_id= (SELECT meta_value FROM wp_postmeta WHERE meta_key= '_thumbnail_id' AND post_id = " . $recentBlog['ID'] . ") AND meta_key = '_wp_attachment_metadata'";
            $stmt = $this->connection->prepare($sql);
            $stmt->execute();
            $img = $stmt->fetchAll();
            if (isset($img[0]['thumbnail_info'])) {
                $thumbnail_data = unserialize($img[0]['thumbnail_info']);
                $upload_directory = explode('/', $thumbnail_data['file']);
                $recentBlogs[$k]['img'] = "/blog/wp-content/uploads/$upload_directory[0]/$upload_directory[1]/".$thumbnail_data['sizes']['medium']['file'];
            }
        }
        return $recentBlogs;
    }
}

Другие вопросы по теме