Zum Inhalt springen

Dependency Injection in einer Service Klasse

Erstellt am 2. Dezember 2012 · 7 Antworten · letzte Antwort am 5. Dezember 2012

Tags: Frage

Unbekannter Benutzer ·

Hallo zusammen,

ich habe folgendes Problem.
Seit 4.7.6 muss man ja die DI (die auch absolut Sinn macht) verwenden.

Um eine Datei zu vimeo hochzuladen und danach zu überprüfen ob das video (die renditions) fertig sind, habe ich einen Scheduler-Task erstellt und zwei Service-Klassen die diese Arbeit übernehmen.

Die Service-Klassen habe ich im folgenden Pfad erstellt:

myExt\Classes\Service\Upload.php
myExt\Classes\Service\CheckUpload.php

Seit kurzem bekomme ich folgenden Fehler:
" mod_fcgid: stderr: PHP Fatal error: Call to a member function replaceObject() on a non-object in /var/www/mydomain.com/httpdocs/typo3_src-4.7.7/typo3/sysext/extbase/Classes/Persistence/Repository.php on line 222, referer: http://www.mydomain.com/typo3/mod.php?M=tools_txschedulerM1&CMD=stop&tx_scheduler[uid]=3"

Laut dieser Maillingliste http://lists.typo3.org/pipermail/typo3-project-typo3v4mvc/2012-November/013095.html scheint dies jetzt auch mein Problem zu sein.

Mein Problem ist, ich hatte versucht via DI auf das Repository zuzugreifen. Leider hat dies nicht funktioniert. (Im Rest meiner Ext [Classes\Controller\...] verwende ich DI, dort geht es ohne Probleme)

(Classes\Service\Vimeo\UploadVideoToVimeoService.php)

class Tx_MyExtension_Service_Vimeo_UploadVideoToVimeoService {
	
   /**
	 * videoRepository
	 *
	 * @var Tx_MyExtension_Domain_Repository_VideoRepository
	 */
	protected $videoRepository;

	/**
	 * injectVideoRepository
	 *
	 * @param Tx_MyExtension_Domain_Repository_VideoRepository $videoRepository
	 * @return void
	 */
	
	public function injectVideoRepository(Tx_MyExtension_Domain_Repository_VideoRepository $videoRepository) {
		$this->videoRepository = $videoRepository;
	}
[...]

  public function UploadVideoToVimeoCommand() {

     $videoToUpload = $this->videoRepository->getVideosToUploadToVimeo();

  }
}

Über die alte Methode:

public function UploadVideoToVimeoCommand() {
  $this->videoRepository = t3lib_div::makeInstance('Tx_MyExt_Domain_Repository_VideoRepository');
  $videoToUpload = $this->videoRepository->getVideosToUploadToVimeo();
}

hat es bis 4.7.5 funktioniert.

Jetzt muss ich es wohl definitiv über DI lösen. Komme hier aber nicht weiter. Kann mir jemand sagen, was ich jetzt genau tun muss, damit es über DI funktioniert? Ich bin mit DI/ObjectManager noch nicht so firm... #paralyzed#

Vielen Dank!

Unbekannter Benutzer ·

Ich glaube er hat DI schon verstanden wenn ich den Code oben sehe. Kapale hast du alle Caches gelöscht? Im Prinzip müsste es so gehen. Die Frage ist, wo deine Service Class instanziert wird. Die darf natürlich auch nicht über t3lib_div::makeInstance instanziert sein sondern per ObjectManager oder injection.

Unbekannter Benutzer ·

Hallo Danke für die schnelle Antwort und sorry das ich mich heute erst melde!

Im Prinzip ist mir DI bekannt und ich verwende es auch sonst in meinen anderen Controller Klassen. Zu 100% verstanden habe ich es aber sicher noch nicht, sonst könnte ich das Problem wahrscheinlich alleine lösen. 😉

Nur als Background-Info: Die Anforderung war, Videos auf den Server (eigener Webserver) hoch laden zu können und diese von dort aus:
a) Herunterladen können
b) Automatisch zu Vimeo hochgeladen werden und dann auf der Webseite als embedded Video zur Verfügung stehen.

Damit der Upload zum Server vom Nutzer unabhängig ist, habe ich den Upload über den Scheduler gelöst.

Der Scheduler ruft dann meine Service Class zum Upload des Videos zu vimeo auf.

Hier der CommandController welcher die Service Class aufruft. Nach deiner letzten Nachricht gehe ich davon aus, dass auch hier das Problem liegt. (Cache hatte ich mehrfach gelöscht).

<?php
/**
 *
 *
 * @package MyExt
 * @license http://www.gnu.org/licenses/gpl.html GNU General Public License, version 3 or later
 *
 */
class Tx_MyExt_Command_VimeoCommandController extends Tx_Extbase_MVC_Controller_CommandController {
    
	/**
	 * Upload a Video To Vimeo 
	 * 
	 * @param string $fixBug
	 * @return void
	 */
	public function UploadVideoToVimeoCommand($fixBug) {
		
		$upload = new Tx_MyExt_Service_Vimeo_UploadVideoToVimeoService;
		$upload->UploadVideoToVimeoCommand();
	}

	/**
	 * Checks if vimeo is ready with transcoding the video 
	 * 
	 * @param string $fixBug
	 * @return void
	 */
	
	public function CheckVimeoVideoReadyCommand($fixBug) {

		$check = new Tx_MyExt_Service_Vimeo_CheckVimeoTranscodingReadyService;
		$check->CheckVimeoVideoReadyService();

	}
	
	
	
}?>

Ich bin mir zwar relativ sicher, dass ich es auch hier mit DI versucht hatte, will es aber nicht beschwören.

Vielen Dank für deine Unterstützung!

froemken ·

Hallo kapale,

vielleicht hast Du es überlesen, aber kitsunet hat schon den richtigen Weg beschrieben: Du darfst Deine Klasse nicht mit t3lib_div::makeInstance und auch nicht mit "new" aufrufen. Aber genau das hast Du getan!
Nur wenn der ObjectManager Deine Klasse instanziiert, wird mit Hilfe der ReflectionClasses Deine Klasse ausgelesen. Dabei wird überprüft, ob es Methoden gibt, die mit "inject" anfangen. Ist das der Fall, werden die verknüpften Klassen "vorgeladen". Dieser Prozess des Auslesens geschieh nicht, wenn Du Deine Klassen mit makeInstance oder new instanziierst.

Vorschlag:
$objectManager = t3lib_div::makeInstance('Tx_Extbase_Object_ObjectManager');
$upload = $objectManager->get('Tx_MyExt_Service_Vimeo_UploadVideoToVimeoService');
$upload->UploadVideoToVimeoCommand();

Jetzt wird Deine Klasse über den OM aufgerufen und die injectMethoden sollten mit geladen werden.

Stefan

Unbekannter Benutzer ·

Super! Danke kitsunet und froemken!

Jetzt habe ich noch eine letzte abschließende Frage zum Verständnis hierzu.

Wann muss ich den OM explizit verwenden?
In meinen anderen Action Controller Klassen habe ich ihn nicht explizit verwenden müssen. Dort geschieht es wohl automatisch...

Danke noch einmal für die tolle Hilfe!

froemken · · Beste Antwort

Hallo kapale,

geh mal in die Datei:
typo3/sysext/extbase/Classes/MVC/Dispatcher.php
rein. Ganz unten findest Du eine Methode: resolveController. Da steht:

$controller = $this->objectManager->get($controllerObjectName);

Siehst Du? Auch Dein ActionController wird über den ObjectManager aufgerufen. Somit werden natürlich auch alle Deine Methoden mit "inject" geladen.

Stefan