Last active
May 25, 2023 08:39
-
-
Save webdevilopers/5b0e90031b6a0c5da3bc to your computer and use it in GitHub Desktop.
Inject Entity and Repository into Service with Symfony2
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| use Plusquam\Bundle\ContractBundle\Service\Invoice; | |
| class ContractAdminController extends Controller | |
| { | |
| /** | |
| * Invoice action | |
| * | |
| * @return Response | |
| */ | |
| public function invoiceAction(Request $request) | |
| { | |
| // ... | |
| // $invoice = $this->get('contract.invoice'); | |
| $invoice = new Invoice($contract, $em->getRepository('PlusquamContractBundle:Contract')); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <?php | |
| namespace Plusquam\Bundle\ContractBundle\Service; | |
| use Doctrine\ORM\EntityRepository; | |
| class Invoice | |
| { | |
| private $repository; | |
| private $contract; | |
| private $filters; | |
| private $timeAndExpense; | |
| public function __construct($contract, EntityRepository $repository) { | |
| $this->contract = $contract; | |
| $this->repository = $repository; | |
| } | |
| public function setFilters($filters) | |
| { | |
| $this->filters = $filters; | |
| } | |
| public function getTimeAndExpense() | |
| { | |
| return $this->repository->getTimeAndExpenseByContract($this->filters); | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| services: | |
| contract.repository: | |
| class: Doctrine\ORM\EntityRepository | |
| factory_service: doctrine.orm.entity_manager | |
| factory_method: getRepository | |
| arguments: | |
| - Plusquam\Bundle\ContractBundle\Entity\Contract | |
| contract.invoice: | |
| class: Plusquam\Bundle\ContractBundle\Service\Invoice | |
| arguments: | |
| - "@contract.repository" |
Author
Author
Looking at this latest comment by @Ocramius I think using the constructor AND the setter is no good choice:
Optional dependencies Do Not Exist!
http://ocramius.github.io/extremely-defensive-php/#/51
But still: how to solve this?
May I ask what approach you ended up taking with this?
I am in the process of writing a manager service which will need the Doctrine Entity Manager and a specific repository and pondering whether I should just inject the entity manager and then retrieve the repository from within the service or inject both independently.
My current thinking is that I should inject them both independently because:
- It would remove the need to perform checking and halt execution of certain methods within the service if the repository didn't exist
- Injecting both separately makes it clearer what the service needs to function from a black box perspective
- Symfony would handle the missing parameters (if that were the case) within the application bootstrap cycle
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I totally get your point @benoit2011 !
This example seemed a very special case to me. First of all it looks strange looking at the consctruction e.g. in the controller code:
Normally you expect the complete
Invoiceservice to work when passing the contract without knowing that you require a repository. Calling the entityManager here to get the repo looks stange.I think it looks much better if you did something like:
new Invoice($contractId)new Invoice($contractValueObject)Then the
Invoiceservice would have theentityManager(NOT THE repo) injected.And finally the
entityManagercan do both what we need in the constructor:ContractgetTimeAndExpenseByContractLooking at my example I don't even think that
finding theContractis required.I only need:
Contract(value) objectI think nowerdays value objects are a good use case to verify objects - just like they can be used in constructors of models resp. entities.
Maybe @mathiasverraes or @matthiasnoback have another hint for us? :)