XF 2.2 Classes and parent::

Robert9

Well-known member
I try to understand the parent thing; here I am now:


A method defines something like in entities:

Code:
    public static function getStructure(Structure $structure)
    {
        $structure = parent::getStructure($structure);

        add something to $structure

        return $structure;
    }

This is like: Hey give me the basket with the fruits, I put an apple inside and give the basket back.




Then I found methods called with a value

Code:
public function actionIndex(ParameterBag $params)
    {
        $view = parent::actionIndex($params);

       do something

       return $view;

        {

I have not tested it yet, but I imagine that the original class runs until the return?
Then we fetch the $params, do something and give it back?
Then we use the return in the original class?



When I print_r such a var; i get one million values;
but I only want to extend the $viewParams before they are returned to the template
 
Real world example:


Code:
namespace XF\Pub\Controller;

class Account extends AbstractController
{


    public function actionUpgrades()
    {
        
        ...

        $viewParams = [
            'available' => $available,
            'purchased' => $purchased,
            'profiles' => $profiles
        ];
        $view = $this->view('XF:Account\Upgrades', 'account_upgrades', $viewParams);
        return $this->addAccountWrapperParams($view, 'upgrades');


Everything i want to do now is to extend $viewParams with

'test' => 'test',


I can do this with a class_extension, then I copy the complete class and add


Code:
        $viewParams = [
            'available' => $available,
            'purchased' => $purchased,
            'profiles' => $profiles,
           'test' => 'test',
        ];


But would it be possible to do that with parent:: also?
Can I fetch {whatever} in my class_extension and give it back?
Can I fetch $viewParams, extend it and give it back?
But from where I get it? When?

Just before the return (would make sense to me, but finally I have no idea how this works)
 
I have not tested it yet, but I imagine that the original class runs until the return?
Then we fetch the $params, do something and give it back?
Then we use the return in the original class?
When actionIndex is called on an extension, the parent method is called and the same parameters are passed to it as the extension. At this point, the $view variable contains what the parent method returned. We can do whatever we want with it and then return that value.
But would it be possible to do that with parent:: also?
Can I fetch {whatever} in my class_extension and give it back?
Can I fetch $viewParams, extend it and give it back?
But from where I get it? When?
The view controller method returns an XF\Mvc\Reply\View instance. It has get/setParam(s) methods, you need to use them. Also, don't forget to check that the XF\Mvc\Reply\View instance is returned, as other replies may not have these methods, which will cause errors.

You can see an example in the documentation:
 
Funny, this one I dont understand at all:


Code:
namespace JUM\PaymentProviders\XF\Pub\Controller;

class Account extends XFCP_Account
{

    /**
     * @return \XF\Mvc\Reply\AbstractReply|\XF\Mvc\Reply\Error|\XF\Mvc\Reply\Message|\XF\Mvc\Reply\View
     */
    public function actionUpgrades()
    {
        /** @var \JUM\PaymentProviders\XF\Entity\User $visitor */
        $visitor = \XF::visitor();

        if (!$visitor->canUseAccountUpgrades())
        {
            return $this->noPermission();
        }

        return parent::actionUpgrades();
    }
}

Is this the same like adding theses code the original class?

Code:
        $visitor = \XF::visitor();

        if (!$visitor->canUseAccountUpgrades())
        {
            return $this->noPermission();
        }

But when it is done?
Wenn the number is low we do that at the beginning?
<extension from_class="XF\Pub\Controller\Account" to_class="JUM\PaymentProviders\XF\Pub\Controller\Account" execute_order="10" active="1"/>
Wenn the number is high we do that at the end?
Is the end the row before the return?

What is the "number" for the original class?
 
Is this the same like adding theses code the original class?
Yes.
But when it is done?
Before the parent method is called. In this case, an error is returned instead of the original reply.
Wenn the number is low we do that at the beginning?
<extension from_class="XF\Pub\Controller\Account" to_class="JUM\PaymentProviders\XF\Pub\Controller\Account" execute_order="10" active="1"/>
Wenn the number is high we do that at the end?
This is the order in which the class extension is executed. One class can have many extensions, which will be executed in order. The lower the number, the earlier the extension is executed relative to others.
What is the "number" for the original class?
None.
 
Can you please take my example from #2

The parent class defines

Code:
$viewParams = [
            'available' => $available,
            'purchased' => $purchased,
            'profiles' => $profiles
        ];


All I need to do is to extend that; because I need some option_values in the template
(I tried to use $xf.options.something in the template, but it failed)


When my extension class runs before the parent class ...
and i define $viewParams, then $viewParams is overwritten by the parent class, right?

So i need to do maybe something like:

run extension_class, call parent class, let parent class work, after we have defined $viewParams;
take this $viewParams, extend it, give it back, run the rest of the parent class?

But this could be possible only if the return is a special point, where we stop and care for extension classes?

extension
call parent with parent::
runs parent until the the return
$lala=parent has now all values we have done in parent.
extend $lala->$viewParams
return $lala to parent
parent returns to template with the extended $viewParams

Is this the way?
Is the magic knowledge that $lala=$parent::parent_function has all the values we have before we return the parent_function to show a template for example?
 
When my extension class runs before the parent class ...
and i define $viewParams, then $viewParams is overwritten by the parent class, right?
No. Your method has other context so you can't override any variable in parent method.

You need to do something like this:
PHP:
public function actionUpgrades()
{
    $reply = parent::actionUpgrades();

    if ($reply instanceof \XF\Mvc\Reply\View)
    {
        $reply->setParam('yourTemplateVariableName', 'someValue');
    }

    return $reply;
}
 
I repeat:

I fetch the parent.
Instance of View means: Hey, do we put our things to a template?
Then hurry, hurry and add some more vars to the story!

Cool.


I repeat again:

If something is a definition like structure in an entity, i can fetch it and extend it and give it back.

If something is a normal function i can replace it,

or if it is a function that ends in showing a template, i can add more values to the $params passed to the template.

Clever.

And I cant change anything in a function in parent itself.
I can replace the whole function, i can add params to a view.


What else can I do with the parent stuff, please?
 
Last edited:
@NikitOS

But when it is done?
Before the parent method is called.


Today I had to solve this:


New addon > creates thread > postDate should be in the past.

post is set in /service/thread/creator > finalSetup

I have extended the class;
the reply=parent function

echo post_date

and hurra; there was a postDate, but this means that the original class/parent class method was running befor i have done replay=parent.
You had written "before".


Finally I have solved the problem like this:

my new addon,
set global

extend finalSetup with:
if global is set, set postDate to past date.


Is there another way to tell my extended class, that we come from another add-on and not from XF without using a global var?
 
@Robert9, I'm not sure I understood what you meant. Do you need to change the date of a post while saving it? Why is another add-on needed?
 
I have asked: When it is done.
Your answer: Before the parent method is called. In this case, an error is returned instead of the original reply.

For me it seems (after some print_r), that the parent is done before.
 
The code is executed when it is called. If the code is before the parent method is called, it will be executed before the parent method is executed. If after — after. The result seen through print_r may not reflect the moment at which the code was executed.
 
I don't really understand the confusion about calling a parent method - it's just a method call like any other method call.
The difference is that the code is taken from the parent class (instead of the instantiated class).

The parent code runs whenever it is called - either before your code:
PHP:
$result = parent::whatever();
// my code here that does smth.

Or after your code:
PHP:
// my code here that does smth.
$result = parent::whatever();

Or myaybe you got code before and after the parent:
PHP:
// my code here that does smth.
$result = parent::whatever();
// my other code here that does smth.

No matter where the parent method is called, the parent code only runs as as long as the method call runs; the parent method call doesn't even have to be the same method- you could call any parent method (that is callable, private methods for example can't be called from a child).

Understanding inheritance, scopes, access is IMHO really OOP basics ...

Complete simple example
PHP:
<?php

class ParentClass
{
        protected function echoHello(): void
        {
                echo('Hello');
        }

        protected function echoWorld(): void
        {
                echo('World');
        }

        public function run(): void
        {
                echo("Method run called in parent!\n");
        }
}

class ChildClass extends ParentClass
{
        public function echoWorld(): void
        {
                echo('Everybody');
        }

        public function run(): void
        {
                parent::run();

                parent::echoHello();
                echo(' ');
                parent::echoWorld();
                echo("\n");

                $this->echoHello();
                echo(' ');
                $this->echoWorld();
                echo("\n");
        }
}

(new ChildClass())->run();

yields
Code:
Method run called in parent!
Hello World
Hello Everybody
 
Last edited:
Top Bottom