1

I am trying to run a background job in a controller but wondering if its actually possible. I'm not sure about namespacing and could do with some guidance on whether the job should be running in the plugins service or not. I get errors like: Class 'modules\importGeoJson\BaseJob' not found. I cant really tell from docs or find a clear example on this.

namespace 
namespace\pluginname\controllers;
use Craft;
use craft\web\Controller;
use craft\web\View;
use craft\elements\Entry;
use craft\db\Query;
use craft\base\Element;
use craft\db\QueryAbortedException;

use craft\helpers\App;

class DefaultController extends Controller{
   //etc
  public function StartJob{
        \craft\helpers\Queue::push(new importGeoJson(), 10);
  }
}

namespace modules\jobs;

class importGeoJson extends BaseJob
{
  public function execute($queue)
    {
    }
}
2

Class 'modules\importGeoJson\BaseJob' not found

You're getting this error because you're trying to extend the craft\queue\BaseJob, but you're not importing (aliasing) that class. In general, a simple class identifier will be assumed to belong to the current namespace. So since your class is namespaced to modules\jobs, the BaseJob class identifier resolves to modules\jobs\BaseJob, which doesn't exist, so you get an error.

To fix this, either import the class with a use statement or use a fully-qualified class name:

// option 1: import
use craft\queue\BaseJob

class ImportGeoJson extends BaseJob {}
// option 2: fully-qualified class name
class ImportGeoJson extends \craft\queue\BaseJob

If you use a fully qualified class name, including the leading backslash (\) is important – without it, the class name becomes relative to the current namespace again!


Not sure if you're just simplifying for your example code, but you should definitely avoid putting more than one class in one file, and especially avoid multiple namespaces in a single file. Your module will soon grow unwieldy and hard to maintain. Take a look at PSR-4, which provides a good structure to map class names to folders and files. For example, I would use the namespace modules\jobs\queue for your ImportGeoJson job, which means you can place it in the file modules\jobs\queue\ImportGeoJson.php.

2
  • 1
    Thanks - PHP oop is into my strong point but avoiding two classes and splitting into services and job seems the way forward. Im using in a plugin as opposed to module as I want the job fired from admin action. Have the task firing now so just gotta figure out the actual work of the job!
    – joomkit
    Sep 21 at 9:20
  • @joomkit If your issue is solved now, would you mind marking my answer as accepted? Thanks!
    – MoritzLost
    Sep 24 at 14:30
1

For anyone strugglng with this. I split the process into a service and a job.

It seems you also have to register your job/services classes in main plugin file first:

 $this->setComponents([
            'Importgeojson' => Importgeojson::class, // job
            'MapitapiService' => MapitapiService::class // service
        ]);

then call the service from your plugin controller like:

    Mapitapi::$plugin->mapitapiService->doBackGroundJob();

then in your service method (doBackGroundJob) start the queue job

$queue = Craft::$app->getQueue();
$jobId = $queue->push(new Importgeojson());

and in your job file (eg as above - 'Importgeojson'), you have you job class with same name were you do the work of the job:

class Importgeojson extends BaseJob
{
    // Public Properties
    // =========================================================================

    /**
     * @var string
     */
    public $someAttribute = 'Some Default';

    // Public Methods
    // =========================================================================

    /**
     * @inheritdoc
     */
    public function execute($queue)
    {
        // Do work here
    }

    // Protected Methods
    // =========================================================================

    /**
     * @inheritdoc
     */
    protected function defaultDescription(): string
    {
        return Craft::t('mapitapi', 'Importgeojson');
    }
}
1
  • You don't need to set register the job as a component, since you're instantiating it manually anyway. Just make sure to namespace the class correctly and put it in the right place, it should work fine then!
    – MoritzLost
    Sep 21 at 9:21

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.