MODx second runProcessor returns response of the first one

664 views Asked by At

Hi and thanks in advance for any help! So the problem is: I run 2 different processors in plugin - i'm creating a user (security/user/create) and creating additional information object (my custom class). The problem is that second processor always returns response of the first one. If i remove the first processor call - it's fine. The problem was the same when i tried to do the same in the second processor itself.So the code:

$response = $modx->runProcessor('security/user/create',$_REQUEST);
$resp=$modx->runProcessor('mgr/userdata/create',$_REQUEST,array("processors_path"=>$custom_path));
$modx->log(MODx::LOG_LEVEL_ERROR,print_r($resp->response,true));

Returns:

 [2014-11-21 01:01:44] (ERROR @ /index.php) Array
(
    [success] => 
    [message] => 
    [total] => 1
    [errors] => Array
        (
            [0] => Array
                (
                    [id] => username
                    [msg] => This username is already used!
                )

        )

    [object] => Array
        (
        )

)

What kind of witchcraft is it and how to make it work?

2

There are 2 answers

0
rogaldh On BEST ANSWER

Processors at MODX are using common $modx->error object. At log we have error while user creating. Second processor catch it and can't be done successfully.

And it's all because $modx->error is common for all processors at one flow. The easiest way is to use $modx->error->reset after first processor call.

But what if we go deeper?

Do you want to create user and related data for him? Ok. But what if user creating will be successfull and your custom data creating fails? In the end we have inconsistent data. That is real headache.

For me the best way is in creating custom processor that extends security/user/create processor. There is special beforeSave method. So you can understand when user creating is successfull and then create your custom data. That's really awesome. Example (it's processor from one of my projects and it's not about user creating. But meaning is the same):

class modWebOrdersOrdersBulkComplectationCompleteProcessor extends modWebOrdersOrdersUpdateProcessor{


public function beforeSave(){

    $canSave = parent::beforeSave();
    if($canSave !== true){
        return $canSave;
    }    

    // if we are here user creating has no errors.

    // method for my additional logic. If i have errors there user won't be created
    $ok = $this->transactionCreate();
    if($ok !== true){
        return $ok;
    }


    return true;
}

protected function transactionCreate(){          

    // i'm usually works with related objects and use especially aggregates/composites relations. So if user has related data profile it will be saved when `save` method will be called for $this->object.

    $_Transaction = $this->modx->newObject('BillingProductTransaction', array(
        'createdby' => $this->modx->user->id,
        'cause'=>   2
    ));

    $this->object->Transaction = $_Transaction;

    // but anyway you can run your subprocessor there. But there are some cons
    // 1. $this->modx->error is common. if you make multiple runProcessor call there you can get some weird problems with logic. (error->reset() is hack not feature)
    // 2. when your project architecture grows logic based on relations becomes more maintainable.

    return true;
}
0
okyanet On

Are you sure it's getting to the second processor? Trying logging both:

$response = $modx->runProcessor('security/user/create',$_REQUEST);
$modx->log(MODx::LOG_LEVEL_ERROR,print_r($response->response,true));

$resp=$modx->runProcessor('mgr/userdata/create',$_REQUEST,array("processors_path"=>$custom_path));
$modx->log(MODx::LOG_LEVEL_ERROR,print_r($resp->response,true));