I know this is not entirely revolutionary, but I saw a whole plugin dedicated to it, which I found to be quite overkill (when a simple blog post will most likely do!).

For symfony 1.3 and 1.4, it should go something like this:

   // In sfActions
    chdir(sfConfig::get('sf_root_dir')); // Trick plugin into thinking you are in a project directory
    $task = new sfMyVerySpecialTask($this->dispatcher, new sfFormatter());
    $task->run(array('argument_name' => 'argument'), array('option_name' => 'option'));

If you don’t have access to the dispatcher object in your current context, you can call $context->getEventDispatcher() on an sfContext instance. If you don’t have access to an instance of this class, you can always call the singleton sfContext::getInstance() to retrieve one. Be forewarned, however. Calling the singleton will throw an exception in the event that no context exists! I would advise wrapping the task in a if(sfContext::hasInstance()) statement. This will gracefully degrade running this task, rather than throwing an exception.

9 comments

  • Olivier - February 23, 2010

    expect that with sfContext::getInstance() you kill kittens. Please use $this->getContext() within an action (and do not call a task from the model !)

  • valter779 - April 14, 2010

    is there a way to run task from unit/functional test ?

  • Brent Shaffer - April 29, 2010

    In your test bootstraps (unit or functional), you should be retrieving an instance of ProjectConfiguration:

    // Functional Tests
    $configuration = ProjectConfiguration::getApplicationConfiguration($app, ‘test’, isset($debug) ? $debug : true);

    //Unit Tests:
    $configuration = ProjectConfiguration::hasActive() ? ProjectConfiguration::getActive() : new ProjectConfiguration(realpath($_test_dir . ‘/..’));

    You can then use this to create and run your task:

    $task = new sfFooTask($configuration->getEventDispatcher(), new sfFormatter());
    $task->run($argumentsArray, $optionsArray));

    I hope this helps!

  • Dennis Gearon - July 13, 2010

    Great! Thanks for the help. I’ll be able to use my super duper task now, from a test harness. Oh boy, (deep sigh), getting closer to understanding the Symfony framework and now they’re going to change it!!! Oh well, it’ll have some similar features.

  • Dennis Gearon - July 16, 2010

    found out one thing that this approach WON’T do . . drop and recreate the database repetatively for testing with PHPUnit. Apparently, those actions are not transactionalble, or act like it with Postgres/Symfony/Apache/PHPUnit. See my blog post to learn ‘easier that I had to’ how to get around that issue.

    http://php-rest-i18n.blogspot.com/2010/07/testing-symfony-apps-with-phpunit.html
    I DID use the method above for reloading the fixture files, and it worked great.

  • Prasad - August 28, 2010

    Hey, thanks a ton for this !!

    But the problem I’m facing that my action cannot find the template it requires. Is that because of the chdir?
    Error: The template “onboardSuccess.php” does not exist or is unreadable in “”.

    Appreciate any help

  • Brent Shaffer - August 29, 2010

    I’ve encountered this too, and I believe it does have to do with the chdir. In my experience, trying to chdir back to the previous directory does not work. What I’ve done in this case is split my task into functions I can call individually from where I was previously calling the task. This will skip the need to chdir altogether.

    Please let me know if you find a better solution to this problem. Thanks!

  • Laurent - September 23, 2010

    after running task :
    $this->redirect(‘/appli.php/…’); // you can pass option in url

  • Laurent - September 24, 2010

    However, in my case, I wanted to run the task several times, but I noticed that the launch of the second task remembered the first. This has its limits

Add comment