Injeksi Symfony 2 EntityManager dalam layanan


96

Saya telah membuat layanan saya sendiri dan saya perlu memasukkan EntityManager doktrin, tetapi saya tidak melihat itu __construct()dipanggil di layanan saya, dan injeksi tidak berfungsi.

Ini kode dan konfigurasinya:

<?php

namespace Test\CommonBundle\Services;
use Doctrine\ORM\EntityManager;

class UserService {

    /**
     *
     * @var EntityManager 
     */
    protected $em;

    public function __constructor(EntityManager $entityManager)
    {
        var_dump($entityManager);
        exit(); // I've never saw it happen, looks like constructor never called
        $this->em = $entityManager;
    }

    public function getUser($userId){
       var_dump($this->em ); // outputs null  
    }

}

Ini services.ymldi bundel saya

services:
  test.common.userservice:
    class:  Test\CommonBundle\Services\UserService
    arguments: 
        entityManager: "@doctrine.orm.entity_manager"

Saya telah mengimpor .yml itu di config.ymlaplikasi saya seperti itu

imports:
    # a few lines skipped, not relevant here, i think
    - { resource: "@TestCommonBundle/Resources/config/services.yml" }

Dan ketika saya memanggil layanan di pengontrol

    $userservice = $this->get('test.common.userservice');
    $userservice->getUser(123);

Saya mendapatkan objek (bukan null), tetapi $this->emdi UserService adalah null, dan seperti yang telah saya sebutkan, konstruktor di UserService tidak pernah dipanggil

Satu hal lagi, Controller dan UserService berada dalam bundel yang berbeda (saya benar-benar membutuhkannya agar proyek tetap teratur), tetapi tetap saja: semuanya berfungsi dengan baik, saya bahkan dapat menelepon

$this->get('doctrine.orm.entity_manager')

dalam kontroler yang sama yang saya gunakan untuk mendapatkan UserService dan mendapatkan objek EntityManager yang valid (bukan null).

Sepertinya saya kehilangan bagian konfigurasi atau beberapa link antara UserService dan konfigurasi Doctrine.


Sudahkah Anda mencoba injeksi penyetel? Berhasil?
gremo

Jika dengan 'injeksi penyetel' yang Anda maksud menambahkan metode penyetel untuk EntityManager pada layanan saya dan memanggil pengontrol dengan $ this-> get ('doktrin.orm.entity_manager') sebagai parameter, maka ya, saya sudah mencoba dan berhasil. Tetapi saya sangat suka menggunakan injeksi yang tepat melalui konfigurasi
Andrey Zavarin

2
Maksud saya ini: symfony.com/doc/current/book/… bagaimanapun __constructorjuga kesalahannya.
gremo

Um, daripada saya belum mencoba injeksi penyetel. __construct memperbaiki masalah, tapi bagaimanapun, terima kasih atas bantuan Anda!
Andrey Zavarin

Jawaban:


112

Metode konstruktor kelas Anda harus dipanggil __construct(), bukan __constructor():

public function __construct(EntityManager $entityManager)
{
    $this->em = $entityManager;
}

2
Hai, dalam contoh ini, bagaimana saya bisa mengubah koneksi dari default ke yang lain?
ptmr.io

Benar, tetapi akan lebih baik jika Anda menggunakan antarmuka. public function __construct(EntityManagerInterface $entityManager)
Pelukan D

65

Untuk referensi modern, di Symfony 2.4+, Anda tidak dapat lagi memberi nama argumen untuk metode Injeksi Konstruktor. Menurut dokumentasi Anda akan meneruskan:

services:
    test.common.userservice:
        class:  Test\CommonBundle\Services\UserService
        arguments: [ "@doctrine.orm.entity_manager" ]

Dan kemudian mereka akan tersedia dalam urutan mereka terdaftar melalui argumen (jika ada lebih dari 1).

public function __construct(EntityManager $entityManager) {
    $this->em = $entityManager;
}

8
Anda dapat melakukan: app / console container: debug Dan mencari tahu layanan apa yang Anda jalankan juga.
Hard Fitness

18

Catatan pada Symfony 3.3 EntityManager disusutkan. Gunakan EntityManagerInterface sebagai gantinya.

namespace AppBundle\Service;

use Doctrine\ORM\EntityManagerInterface;

class Someclass {
    protected $em;

    public function __construct(EntityManagerInterface $entityManager)
    {
        $this->em = $entityManager;
    }

    public function somefunction() {
        $em = $this->em;
        ...
    }
}

1
Untuk berjaga-jaga jika ada yang tersandung dan bingung: EntityManager jelas belum disusutkan. Menggunakan antarmuka membantu dengan kabel otomatis dan disarankan tetapi sama sekali tidak diperlukan. Dan antarmukanya sudah ada sejak lama. Tidak ada yang benar-benar baru di sini.
Cerad

Inilah jawabannya. Namun, harap lakukan referensi: stackoverflow.com/questions/22154558/…
tfont

Perbarui ke solusi saya sendiri. Cara yang tepat sekarang adalah dengan menggunakan Entitas dan Repositori. Pengelola Entitas sudah secara alami dimasukkan ke dalam repositori. Anda dapat melihat contohnya di sini: youtu.be/AHVtOJDTx0M
Robert Saylor

7

Sejak 2017 dan Symfony 3.3 Anda dapat mendaftarkan Repositori sebagai layanan , dengan segala kelebihan yang dimilikinya.

Periksa posting saya Cara menggunakan Repositori dengan Doctrine as Service di Symfony untuk penjelasan yang lebih umum.


Untuk kasus khusus Anda, kode asli dengan penyetelan akan terlihat seperti ini:

1. Gunakan dalam layanan atau Kontroler Anda

<?php

namespace Test\CommonBundle\Services;

use Doctrine\ORM\EntityManagerInterface;

class UserService
{
    private $userRepository;

    // use custom repository over direct use of EntityManager
    // see step 2
    public function __constructor(UserRepository $userRepository)
    {
        $this->userRepository = $userRepository;
    }

    public function getUser($userId)
    {
        return $this->userRepository->find($userId);
    }
}

2. Buat repositori kustom baru

<?php

namespace Test\CommonBundle\Repository;

use Doctrine\ORM\EntityManagerInterface;

class UserRepository
{
    private $repository;

    public function __construct(EntityManagerInterface $entityManager)
    {
        $this->repository = $entityManager->getRepository(UserEntity::class);
    }

    public function find($userId)
    {
        return  $this->repository->find($userId);
    }
}

3. Daftarkan layanan

# app/config/services.yml
services:
    _defaults:
        autowire: true

    Test\CommonBundle\:
       resource: ../../Test/CommonBundle
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.