[owncloud-devel] Injecting services and variables to App constructors and calling them

Bernhard Posselt dev at bernhard-posselt.com
Wed Aug 5 17:43:34 GMT 2015


Full file? Is your project on Github?

Apart from that I can only highlight the tutorial at
https://doc.owncloud.org/server/8.1/developer_manual/app/tutorial.html

My advice: Use automatic injection (ownCloud 8+), that is remove
everything in the registerServices function and let ownCloud figure out
everything else. The way this works is that it uses reflection to get
the type hints in your constructor (and variable names for scalar types)
and passes the stuff in that is needed. Also controllers are resolved
automatically as in: settings#index instantiates
OCA\YourApp\SettingsController by default, no need to write extra code
like in versions prior to 7.

More information on how it works in detail is here
https://doc.owncloud.org/server/8.1/developer_manual/app/container.html#use-automatic-dependency-assembly-recommended

On 08/05/2015 07:18 PM, Josef Meile wrote:
> Sorry, I saw an error in the constructor of my Application class, it should
> be:
>
>     public function __construct($appId, array $urlParams=array()) {
>         parent::__construct($appId, $urlParams);
>
>         $this->appId = $appId;
>         $this->registerServices();
>         $this->registerHooks();
>         $this->registerSettings();
>     }
>
> Anyway, the problems are still there. I would appreciate if somebody gives
> me a clue.
>
> -----Original Message-----
> From: Josef Meile [mailto:jmeile at hotmail.com] 
> Sent: Mittwoch, 5. August 2015 19:15
> To: devel at owncloud.org
> Subject: Injecting services and variables to App constructors and calling
> them
>
> Dear all
>
> I have developed the AgreeDisclaimer App and it is working as it should;
> however, I got the feedback from another developer that I should avoid this
> things:
> 1) \OC::$server calls
> 2) Using "\OCP\Util::writeLog" for the logger or "\OCP\Util::getL10N" for
> translating things
>
> The recommendation was to inject them into the constructors. I have tried to
> do this, and in some cases I succeeded, but in others don't. First, I tried
> to inject the L10N service in my controller:
>
> class SettingsController extends Controller {
>     private $trans;
>
>     public function __construct($AppName, IRequest $request, IL10N $trans) {
>         parent::__construct($AppName, $request);
>         $this->trans = $trans;
>     }
>
>    /* Some more code comes here */
>
> }
>
> Then I called the constructor as follows in Application.php:
> class Application extends App {
>     private $appId;
>
>     public function __construct($appId, array $urlParams=array()) {
>         parent::__construct('agreedisclaimer', $urlParams);
>
>         $this->appId;
>         $this->registerServices();
>         $this->registerHooks();
>         $this->registerSettings();
>     }
>
>     public function registerServices() {
>         $container = $this->getContainer();
>
>         $container->registerService('L10N', function($c) {
>             return
> $c->query('ServerContainer')->getL10N($c->query('AppName'));
>         });
>
>         $container->registerService('SettingsController', function($c) {
>             return new SettingsController (
>                 $c->query('AppName'),
>                 $c->query('Request'),
>                 $c->query('L10N')
>             );
>         });
>     }
>
>    /* Some more code comes here */
> }
>
> Then I tried to use the $trans variable in a method of my controller as
> follows:
>     public function getFile($userLang, $defaultLang, $basePath, $fileExt,
>             $getContent = false, $maxFileSize = 2, $getFallbackLang = true)
> {
>
>        /* Some code comes here */
>
>             $errorMsg = $this->trans->t('%s doesn\'t exist.',
>                 $userLangFile . '<br/>') . ' ' .
>                 $this->trans->t('Please contact the webmaster');
>
>        /* Some more code comes here */
>     }
>
> I got an error exactly on that line:
> "Call to a member function t() on a non-object at
> \var\www\html\owncloud\apps\agreedisclaimer\controller\settingscontroller.ph
> p#227"
>
> The function getFile gets called from another function called "getFiles",
> which is a route called through an ajax request:
>     function getFiles($isAdminForm = false, $defaultLang = null) {
>
>        /* Some code comes here */
>
>         $fileInfo = $this->getFile($userLang, $defaultLang,
> $txtFileBasePath,
>             'txt', true, $maxTxtFileSize, $getFallbackLang);
>
>        /* Some more code comes here */
> }
>
> And here the routes:
> <?php
> return ['routes' => [
>     ['name' => 'settings#get_settings',
>      'url' => '/settings/get_all', 'verb' => 'GET'],
>     ['name' => 'settings#get_files',
>      'url' => '/settings/get_files', 'verb' => 'GET'], ]];
>
> I think that the problem is that "getFiles is a route, so it doesn't really
> needs an object instance to the SettingsController class. It is some kind of
> static function, so, that's why "$this" can't be used. My original code is
> using:
> \OCP\Util::getL10N($appId)->t('%s doesn\'t exist.', $userLangFile . '<br/>')
>
> and it works. But it isn't the way of doing it according to the Developers
> manual, so, how can I solve this problem?
>
> The second problem I'm facing: on the class "Application", I defined a
> private variable called "$appId". I would like to inject it to the admin
> page, but I don't know how to do this. First I registered the admin page on
> the "Application" class:
>
> \OCP\App::registerAdmin($this->appId, 'admin');
>
> Then in the "agreedisclaimer/admin.php" file, I render the template:
> agreedisclaimer/templates/admin.php
>
> \OCP\User::checkAdminUser();
> $data = [];
> $templateResponse = new TemplateResponse($appId, 'admin', $data, 'blank');
> return $templateResponse->render();
>
> How can I get the Application object from "agreedisclaimer/admin.php" and
> push the $appId variable into the $data array? Here again, my workaround was
> a static class variable instead of a private one:
>
> class Application extends App {
>   const APP_ID = 'agreedisclaimer';
>
>        /* Some more code comes here */
> }
>
> Then I called it like: Application::APP_ID, but this isn't the way it should
> be. How can I avoid using this static constant?
>
> Thanks in advanced.
>
> Best regards
> Josef
>
> _______________________________________________
> Devel mailing list
> Devel at owncloud.org
> http://mailman.owncloud.org/mailman/listinfo/devel



More information about the Devel mailing list