Matzn Posted May 9, 2022 Share Posted May 9, 2022 Hi, how I can access parent modules config fields? It is also not possible to use the parent methods include this fields. Example: I need field "api_user" in Child class. class Parent extends WireData implements Module { public function getApiUser() { return $this->api_user; } } class ParentConfig extends ModuleConfig { public function getInputfields() { $inputfields = parent::getInputfields(); $f = $this->modules->get('InputfieldText'); $f->attr('name', 'api_user'); $f->label = 'API User'; $f->required = true; $inputfields->add($f); return $inputfields; } } class Child extends Parent implements Module { //null $apiUser = $this->api_user; //null $apiUser = $this->getApiUser(); } Link to comment Share on other sites More sharing options...
Zeka Posted May 9, 2022 Share Posted May 9, 2022 Hi @Matzn <?php namespace ProcessWire; class ParentModule extends WireData implements Module, ConfigurableModule { public static function getModuleInfo() { return [ 'title' => 'Parent Module', 'version' => 1, ]; } const defaultValue = '12345'; public function __construct() { $this->set('api_user', self::defaultValue); // set default value in construct } public function getApiUser() { return $this->api_user; } public static function getModuleConfigInputfields(array $data) { if(!isset($data['api_user'])) $data['api_user'] = self::defaultValue; $form = new InputfieldWrapper(); $f = wire('modules')->get('InputfieldText'); $f->name = 'api_user'; $f->label = 'API USER'; $f->value = $data['api_user']; $form->add($f); return $form; } } <?php namespace ProcessWire; class ChildModule extends ParentModule { public static function getModuleInfo() { return [ 'title' => 'ChildModule', 'version' => 1 ]; } public function __construct() { parent::__construct(); bd($this->getApiUser()); bd($this->wire()->modules->getModuleConfigData('ParentModule')); } } Take a look at the construct method of ChildModule. Without calling parent::__construct you will not be able to get what you want. Also you can use $this->wire()->modules->getModuleConfigData('ParentModule') to get config data of module. 4 Link to comment Share on other sites More sharing options...
Matzn Posted May 9, 2022 Author Share Posted May 9, 2022 Hey @Zeka, thanks. If i understood, now get the const "1234" from parent class. But wat i need is the admin field from modul (screenshot). Some magic with ParentConfig class must do. But what? Link to comment Share on other sites More sharing options...
ryan Posted May 9, 2022 Share Posted May 9, 2022 @Matzn Are you wanting a parent/child class relationship, or are parent and child modules separate modules where you want the child module to pull a value from the parent module? If you just want to pull a configuration value from "ParentModule" to use somewhere in "ChildModule" (or anywhere else) then you don't need to have a parent/child relationship between the modules and can instead just pull the value you need: $api_user = $modules->getConfig('ParentModule', 'api_user'); On the other hand, if you really do want a parent/child relationship between the module classes, and they will be two separate installed modules, then it is possible. Many Inputfield and Fieldtype modules use this approach. For instance, InputfieldCKEditor extends InputfieldTextarea, and InputfieldTextarea extends InputfieldText. The reason is that they all have similar configuration needs, as they are all inputs for text. InputfieldCKEditor builds upon the configuration of InputfieldTextarea and InputfieldTextarea builds upon the configuration of InputfieldText. When it's possible that someone might attempt to install the ChildModule without having first installed the ParentModule then it's recommended to keep your module-info in a separate php (or json) file like ModuleName.info.php, at least for the modules that require another (i.e. ChildModule requires ParentModule). This ensures that if ChildModule is on the file system, but ParentModule isn't, PW can identify the requirements for the ChildModule without having to load its class file. (If it loaded its class file, then it would result in an error since ChildModule extends ParentModule, and ParentModule isn't present, so that's why we want to avoid that). Let's say we've got this ParentModule: // ParentModule.module.php class ParentModule extends WireData implements Module, ConfigurableModule { public function __construct() { $this->set('api_user', ''); // establish default value parent::__construct(); } public function getModuleConfigInputfields(InputfieldWrapper $inputfields) { $f = $this->wire()->modules->get('InputfieldText'); $f->attr('name', 'api_user'); $f->label = 'API User'; $f->required = true; $f->val($this->get('api_user')); $inputfields->add($f); } } And it also has this ParentModule.info.php file to define module info. Since ParentModule doesn't extend another module, it could also be in a static getModuleInfo() method if you preferred it, but we'll stick to the file for this example: // ParentModule.info.php <?php namespace ProcessWire; $info = array( 'title' => 'Parent module', 'version' => 1, 'summary' => 'Parent module description', ); Here's a child module that extends ParentModule and also adds an "api_key" to the configuration: // ChildModule.module.php class ChildModule extends ParentModule implements Module, ConfigurableModule { public function __construct() { $this->set('api_key', ''); // default value parent::__construct(); } public function getModuleConfigInputfields(InputfieldWrapper $inputfields) { parent::getModuleConfigInputfields($inputfields); $f = $this->wire()->modules->get('InputfieldText'); $f->attr('name', 'api_key'); $f->label = 'API Key'; $f->required = true; $f->val($this->get('api_key')); $inputfields->add($f); } public function test() { $this->message("API user is $this->api_user and key is $this->api_key"); } } …and the ChildModule's info file is below. Note the "requires" that says it requires ParentModule: // ChildModule.info.php <?php namespace ProcessWire; $info = array( 'title' => 'Child module', 'version' => 1, 'summary' => 'Child module description', 'requires' => 'ParentModule', ); Zeka's example above is also a good one, but just adding my example as another variation. 3 Link to comment Share on other sites More sharing options...
Matzn Posted May 9, 2022 Author Share Posted May 9, 2022 @Zeka @ryan Hui, now i am confused... Yes, I want a parent/child class relationship like php class extend. I'm writing modules as on this page discribed: ProcessWire 2.5.5 – New module configuration The modul file(excerpt) //file: parent.modul class Parent extends WireData implements Module { public static function getModuleInfo() { return array( 'title' => 'Network Adcell', 'version' => 1, 'summary' => 'Loading Data from Affiliate Network.', 'singular' => true, 'autoload' => false, ); } public function getToken() { $data = $this->_request( 'user', 'getToken', [ 'userName' => $this->api_user, 'password' => $this->api_key, ] ); return $data->data->token; } public function test() { $data = [ 'userName' => $this->api_user, 'password' => $this->api_key, ]; return $data; } } The parent modul config file: //file: ParentConfig.php class ParentConfig extends ModuleConfig { public function getInputfields() { $inputfields = parent::getInputfields(); $f = $this->modules->get('InputfieldText'); $f->attr('name', 'api_user'); $f->label = 'API User'; $f->required = true; $inputfields->add($f); $f = $this->modules->get('InputfieldText'); $f->attr('name', 'api_key'); $f->label = 'API Key'; $f->notes = 'Der API Key muss im Adcell Backend erstellt werden.'; $f->required = true; $inputfields->add($f); return $inputfields; } } The parent modul is an old modul that i can't/wan't thouch. So i think i extend the parent class with new methods. The child modul (excerpt) class Child extends Parent implements Module { public static function getModuleInfo() { return array( 'title' => 'Import Adcell programs', 'version' => 1, 'summary' => 'Import new joined programs and offers.', 'singular' => true, 'autoload' => false, 'requires' => 'Parent modul' ); } public function addProgram() { /* this will get: * array(2) { * ["userName"]=>NULL * ["password"]=>NULL * } */ $token = $this->test(); //some further code } } In child modul if call "$this->test();" get null, because (i think) the ParentConfig will not extend/call what ever. Also is $this->api_user=null and $this->api_key=null. A simple solution is to add a constant/property to parent modul, but i wan't touch this file. I hope we don't talk past each other? Link to comment Share on other sites More sharing options...
Matzn Posted May 9, 2022 Author Share Posted May 9, 2022 Maybe I also have mistakes in thinking and a processwire class can't extend like php. Is that so? I get the parent methodes and properties like: class Child extends Parent implements Module { public function myMethode() { $myParentModul = wire('modules')->get('Parent'); $token = $myParentModul->test(); } } Link to comment Share on other sites More sharing options...
ryan Posted May 9, 2022 Share Posted May 9, 2022 @Matzn ProcessWire classes are just PHP classes, so there would be no difference. Note that I don't think you can have a class named "Parent" as I think that might be a reserved word in PHP. I wouldn't bother trying to do an external configuration class. Start with an internal getModuleConfigInputfields() method, and when all works, then consider moving it to an external one if needed. Make sure your module implements the ConfigurableModule interface, indicated at the top of the class. I also think maybe you shouldn't try to extend your Parent module/class and instead should just write another module that pulls from the Parent module what it needs. Module inheritance is useful in many situations but it's not clear to met that this is one of those situations, though I could be wrong. Quote I get the parent methodes and properties like: This is fine the way you are doing it, but note that your class "Child" need not extend "Parent" given the approach you are using. Your "Child" module could just extend WireData instead, and the code in your myMethode() would do exactly the same thing. 2 Link to comment Share on other sites More sharing options...
Matzn Posted May 9, 2022 Author Share Posted May 9, 2022 @ryan No, i m using other class names. My IDE helps me for wrong syntax. It was not possible for me to get the properties api_user and api_key in a child class. No matter which variant I tried (intern or extern modul config im testing). The values were not available in the children's class. Why, i don't know, maybe i do some ? Link to comment Share on other sites More sharing options...
Matzn Posted May 10, 2022 Author Share Posted May 10, 2022 @Zeka @ryan I tested again and found that the "ModuleConfigInputfields" are not inherited. This means that the parent methods not can be call from child class, if "ModuleConfigInputfields" are used in parent class. To get "ModuleConfigInputfields" for inherited modul/class must get first the module like: wire()->modules->get('modulname); Here's the proof: <?php //template file namespace ProcessWire; $m1= $modules->get("TestModule"); print_r($m1->getField()); $m2 = $modules->get("TestModuleChild"); print_r($m2->getField()); //output Array ( [field 1] => parent module property 1 [field 2] => Parent Module field 2 ) Array ( [field 1] => parent module property 1 [field 2] => default field 2 ) TestModule.module TestModuleChild.module Link to comment Share on other sites More sharing options...
ryan Posted May 10, 2022 Share Posted May 10, 2022 @Matzn Your TestModuleChild.module is overriding the getModuleConfigInputfields() of the TestModule.module and replacing it. In PHP, if you want the parent method to run, then you need to either omit the method completely in your child class, or call the method parent::method() so that it will run (like what you are doing with your __construct method). What you are doing currently is replacing the method with one that has no code in it. What I think you are wanting is this in your TestModuleChild.module: public function getModuleConfigInputfields(InputfieldWrapper $inputfields) { parent::getModuleConfigInputfields($inputfields); } After doing the above, now it will inherit the code of the parent class. And after calling that parent::method() maybe you want to add another configuration setting to it, i.e. public function getModuleConfigInputfields(InputfieldWrapper $inputfields) { parent::getModuleConfigInputfields($inputfields); $f = $this->wire()->modules->get('InputfieldText'); $f->attr('name', 'test_field'); $f->label = 'Test field'; $f->val($this->test_field); $inputfields->add($f); } But if you don't want to add anything new to the getModuleConfigInputfields() then just leave the method out of your TestModuleChild.module completely, and it will inherit automatically. Also, module configuration data should be defined with runtime calls, so I recommend you remove this: public $field_1 = "parent module property 1"; and replace it with this in your __construct(): $this->set('field_1', 'parent module property 1'); I see you are using static getModuleInfo() methods in your classes. In cases where you've got one module extending another, unless the child module literally does an include() at the top of the parent module's file, then you should define your child module's info in a ModuleName.info.php file like I described in my previous message (including the 'requires' statement), and omit the getModuleInfo() static method. Otherwise, if PHP/PW happens to include() the child module before the parent module, you'll get a fatal class error. By using a separate ModuleName.info.php, PW can learn about the module without having to load the class file, and it can see from your 'requires' statement that it needs to load the parent module before your child module, ensuring no fatal errors. If you can't do this, or don't want to, then make sure your child module does an include() or require() of the parent module's file, somewhere before your "class TestModuleChild ...". 3 Link to comment Share on other sites More sharing options...
Matzn Posted May 10, 2022 Author Share Posted May 10, 2022 Thank you for your description. You're right if some syntax isn't 100% correct. But what I mean is the thing is that I can't call a parent function from a child function because the parent field value doesn't inherit. $m2 = $modules->get("TestModuleChild"); print_r($m2->getField());//function will not overwrite in child class The function result is (note field 2) [field 1] => parent module property 1 [field 2] => default field 2 I would have expected (note field 2), because i have input it on parent module (screenshot Parent Module) [field 1] => parent module property 1 [field 2] => Parent Module field 2 So I'm wondering if I can extend processwire class like a php class at all. At least not as a module extension. Link to comment Share on other sites More sharing options...
WillyC Posted May 10, 2022 Share Posted May 10, 2022 @Matzn that not.how obj inheritennce work { .clsses inherit code not runs time valus } class A{public $foo;} class B extends A{} $a=new A(); $a->foo='Foo'; $b=new B(); echo $a->foo; // 'Foo' echo $b->foo; // emptys.. nothing modules work.same { .mabe.u want this in you TestModuleChild ? } >>> public function __construct(){ $this->setArray($this->modules->getConfig('TestModule')); } 4 Link to comment Share on other sites More sharing options...
Matzn Posted May 10, 2022 Author Share Posted May 10, 2022 32 minutes ago, WillyC said: not runs time valus Now it makes sense. I thought "ModuleConfigInputfields" are classes constant. That now I understood, thanks. 2 Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now