2

Craft's Web Controller has a redirectToPostedUrl method. Copied here for the sake of discussion:

public function redirectToPostedUrl($object = null, string $default = null): YiiResponse
{
    $url = Craft::$app->getRequest()->getValidatedBodyParam('redirect');
    if ($url === null) {
        if ($default !== null) {
            $url = $default;
        } else {
            $url = Craft::$app->getRequest()->getPathInfo();
        }
    }
    if ($object) {
        $url = Craft::$app->getView()->renderObjectTemplate($url, $object);
    }
    return $this->redirect($url);
}

We can call this method from our plugin controllers to redirect to the posted URL in the redirect input field and use a dynamic {siteUrl} variable. In my template, I have a redirect value that uses {siteUrl}:

<input type="hidden" name="redirect" value="6026760a62b9c6007a4b5695a65acbabG2540f8cb3727b998a1c78da45db863f{siteUrl}?id={id}">

And in my Controller, I receive that value and redirect to that location:

return $this->redirectToPostedUrl($object);

That all works fine. I can pass my custom $object to this method and the {id} or any other part of the model I wish to process can appear in the URL.

My question is, where is {siteUrl} being made available to the redirectToPostedUrl method? In looking closer at renderObjectTemplate it never appears to specifically make global variables available. And, if I try other global variables such as {currentUser.id} nothing gets rendered. In Craft 2 I believe this method made environmentalVariables available for parsing but those are no longer supported in Craft 3.

So why and how does {siteUrl} work? Are there other variables that are available to be used in the redirect URLs too that we don't explicitly make available by passing them in via the $object argument?

1 Answer 1

2

When you take a deeper look into redirectToPostedUrl you'll see these lines. All they do is convert the Object into an array, so they fetch every property of the object and pass those to the template to use them directly. You have everything the Object has.

You can access those attributes via short syntax {title} which is the same as {{ object.title }}.

For example if you have an yii/model/MyFancyModel with the following attributes

[
    'id' => 4,
    'title' => 'foo',
    'someRelation => ['foo' => 'bar']
]

Craft will merge this array with ['object' => $object] and you have access to { id }, { title }, { someRelation.foo } as well as {{ object.id }} (and all others) as well as all other variables passed via variables the third attribute of the function, since redirectToPostedUrl doesn't pass a third argument these additional attributes are an empty array.

In your case { siteUrl } is nothing else than {{ object.siteUrl }} which is basically {{ entry.siteUrl }} that means the siteUrl of your Element. When you do { type.handle } (with an Entry) it will render the handle of your EntryType. When your Object is a user you can do { email } to display his/her email.

One more note: The attributes of the Model are fetched via Arrayable Trait if it has it. So it grabs all fields and extraFields gets those attributes. I can provide further explanations about fields and how they work exactly in detail if you like

1
  • Hey Robin. The thing is $object->siteUrldoes not exist on the model I'm passing to $this->redirectToPostedUrl($object); I don't know where it's coming from. If I kill the script and try to access $object->siteUrl directly, I get a yii\base\UnknownPropertyException Commented Feb 19, 2019 at 5:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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