Я пытаюсь получить доступ к настраиваемому репозиторию, который содержит настраиваемые необработанные 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: Спасибо, но предоставленная вами ссылка предназначена для репозиториев, которые используются для расширения ваших текущих сущностей, но мой репозиторий не имеет никакого отношения к какой-либо сущности.
Репозитории Doctrine требуют ссылки на объект. Все как есть. Вы создаете класс, который не расширяет EntityRepository, а просто вставляете диспетчер сущностей или объект подключения к базе данных.
@Cerad: На самом деле в этом репозитории нет объекта, с которым можно было бы связать это. Я хочу иметь собственный класс, в котором я могу хранить необработанные запросы на основе sql, которые получают разные типы вещей из базы данных? И можно ли легко получить доступ к этому классу в контроллере?
В этом нет особого смысла. Базовый EntityRepository из пакета Doctrine ORM требует, чтобы вы передали ему экземпляр ClassMetadata. Но из какого объекта вы бы передали это здесь, если ваш репозиторий ни с чем не связан? Глядя на то, что делает ваш класс репозитория, я бы просто не расширял класс EntityRepository и только вставлял экземпляр Connection, который вам нужен для выполнения SQL-запросов.
@UmairShahYousafzai Оба ответа ниже иллюстрируют концепцию наличия репозиториев, отличных от Doctrine. Ни один из них не дает хороших примеров, но концепции действительны. Чего вам не хватает, так это хорошего понимания того, как внедрять сервисы в методы действий контроллера. Множество примеров в документации. Не используйте больше $ this-> getDoctrine (), и жизнь станет намного проще.
Спасибо вам обоим, @Cerad и @xabbuh. На самом деле я последовал предложению @xabbuh, ввел Connection и выполнил свою работу, и теперь все выглядит отлично. Спасибо






Вы не должны расширять 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 и выполнил свою работу.
Я ввел 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;
}
}