Love Fuel?    Donate

FuelPHP Forums

Ask your question about FuelPHP in the appropriate forum, or help others by answering their questions.
HMVC in CLI
  • Hi there,

    I've come across something I thought I understand but not.

    What I was trying to do is do couple HMVC requests in one of task files so it looks like this:

    for($i;$i<10;$i++){
         \Request::forge( '/attr/sync/'.$i )->execute();
    }

    First one goes fine, but then I get:

    Uncaught exception DomainException: Form instance already exists, cannot be recreated. Use instance() instead of forge() to retrieve the existing instance.

    So the question is: is it doable this way (I could use cron for it or possibly curl requests but I was curious what is going on there)
  • Harro VertonHarro Verton
    Accepted Answer
    That is not related to the HMVC request, but to your controller implementation.

    Your controller code creates a new form instance with either a fixed name, or with the default name. Since HMVC processes run in the same PHP context, only one of these instances may exist.

    You could use

    $obj = Form::instance() or Form::forge();

    which retrieves the existing default instance, and creates on if the default does not exist. Obviously, you need to be careful if you re-use an existing object.

    Alternatively, create named instances, based on your $i (which I assume is a parameter for the sync action:

    $obj = Form::forge('form-'.$i); // creates form-0 to form-9

    Downside of this is that you'll end up with 10 form objects in memory.
     
    If neither of these are an option, you can overload the Form class in your app/classes, and add a method to delete a cached instance, so your controller can remove it once it is finished with it, and the name can be reused in a subsequent request.
  • Hi Harro,

    Thank you for your feedback, it's all makes more sense now.

    This part is a little bit confusing as the error says something about the Form class (but in fact, I'm not using Form class anywhere in the application ).

    I've tested with a simple controller and all HMVC works fine. What is really causing that isssue is the validation class I use.

    So im my case, Inside the main object I have method configue_validators() initialised in the constructor of that class, which creates two separate validator objects and configure them. First instance is used for validating main objects properties ( entry data input ), second is initialised and configured by this method, but retrieved in one of subsequent objects by instance() (there might be hundrets of these objects). This all works fine, until called via HMVC.

    Now, I've done some tests to find out solution to this problem but it seems to be a bit more complicated.
    In my example implementation it looks like this:

    setup_validators(){
            $this->attr_validator            = \Validation::forge('attr');
            $this->attr_validator->add('ts_id', 'TSID')
                                        ->add_rule('required');
            (...)

    }

    After playing a bit with it I think there is some issue with this Factory/Singleton (not sure if there is any formal name for this pattern) implementation (or my understanding of it is somehow wrong).

    So in my test example:
    $this->validator = \Validation::forge('attr');

    Above works fine until HMVC.

    Changing to \Validation::instance('attr); does not create an instance, until I create one by \Validation::forge('attr) earlier, but then HMVC will fail.

    So basically, instance does not return an object if not initialised earlier

            $this->attr_validator            = \Validation::instance('attr');
            var_dump( $this->attr_validator );

    Gives:
    bool(false)

    TBH, I don't really get the idea of splitting this into Instance/Forge as it seems that single Instance should be enough and Forge just private/protected scope.

    Edit:

    After reading the docs a bit more I understand this is expected behaviour, however this leaves me with only last option to delete an instance, but I think that method should be part of standard implementation
  • Harro,

    It looks like it is not that easy to remove that specific instance.
    Do you have any example implementation of this ?
  • Ok I've managed to come up with solution, but it required to inheritate from Fieldset Class in order to remove validation. Implementing such functionality on both classes would result much cleaner solution IMO.

    class ExtFieldset extends Fieldset
    {
       
        public static function remove( $name )
        {
            if( !empty( self::$_instances[$name] )){
                unset( self::$_instances[$name] );
            }
        }
       
    }


  • Harro VertonHarro Verton
    Accepted Answer
    Ideally, everything request related should be maintained at the request level, and not global. Implementing it however would mean a major rewrite. 

    I'll try to find a workaround for this issue.

    As to the extension, I suggest you follow https://fuelphp.com/docs/general/extending_core.html#/extend_and_replace so you the new method comes available in the standard Fieldset class.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

In this Discussion