Uniform Undefined variable $form

Hi all,

In my current kirby 3 setup i tried to implement a form in a kirby block. I used the logging script from the provided examples so my block looks like this

<form method="POST">
	<input name="email" type="email" value="<?php echo $form->old('email') ?>">
	<textarea name="message"><?php echo $form->old('message') ?></textarea>
	<?php echo csrf_field() ?>
	<?php echo honeypot_field() ?>
	<input type="submit" value="Submit">
</form>

and my controller like this:

<?php

use Uniform\Form;

return function ($site, $pages, $page)
{
	$form = new Form([
		'email' => [
			'rules' => ['required', 'email'],
			'message' => 'Email is required',
		],
		'message' => [
			'rules' => ['required'],
			'message' => 'Message is required',
		],
	]);

	if (r::is('POST')) {
		$form->logAction([
			'file' => kirby()->roots()->site().'/messages.log',
		]);
	}

	return compact('form');
};

my web page no says

Block error: “Undefined variable $form” in block type: “myform”

which makes me think that the plugin is not installed properly. But i put all its contents to site/plugins/uniform as described. Anybody knows why $form can not be used?

the controller will forward the variable $form into the template but that does not make it available in the scope of a block. the uniform examples show code directly in a template

consider

  • storing that form variable by reference in the kirby()->session() or
  • moving the $form variable into the global variable scope

but

  • forwarding the $form variable as data to a block like we can do with snippets as a data param is not possible afaik

okay that sounds like a lot of work. I build every page on my website with kirby blocks in order to make them really flexible in layout and functions. Is there no way to implement a form in a block that talks to a controller? Maybe I can do it without the plugin, it’s a rather simple task: Let users input a string and safe that to a txt or better json file.

in controller
global $form = new Form([

in block

<form method="POST">
<?php $form = A:get($GLOBALS, 'form'); ?>

I think the logic should go into the block snippet, not into the global scope

…Or if you don’t like having that code in a template (because of principles), you could consider using a Block model instead of a controller.

// /site/plugins/block-models/index.php

use Kirby\Cms\App as Kirby;
use Kirby\Cms\Block;
use Uniform\Form;

class FormBlock extends Block {
    private ?Form $form = null;

    public function form(): Form {
        return $this->form ??= new Form([
            'email' => [
                'rules' => ['required', 'email'],
                'message' => 'Email is required',
            ],
            'message' => [
                'rules' => ['required'],
                'message' => 'Message is required',
            ],
        ]);
    }

    public function toHtml(): string {
        if (r::is('POST')) {
            $this->form()->logAction([
                'file' => kirby()->roots()->site().'/messages.log',
            ]);
        }
        return parent::toHtml();
    }
}

Kirby::plugin('my/blockModels', [
    'blockModels' => [
        'form' => FormBlock::class
    ]
]);

then inside of the block snippet you would refer to the form via

<?= $block->form()->old('email') ?>
1 Like

Thank you all for your input. I ditched uniform in favor of doing it the plain php way.
I don’t know what obstacles are in place that, but it would take out lot of headache if they could connect to controllers and access variables just like normal templates do. i love blocks!

You can pass a variable to a block snippet in the same way you can to any other snippet.

However, the question is if this makes sense. A block is supposed to be used multiple times across a page or even multiple different pages. So each time a block is used, you have a different form. A controller that handles a single form doesn’t really make sense in this context, I think.

I guess he’s referring to some kind of “block controller”: a function which would inject variables into the scope of a block snippet.
But hey, at this point I’d rather have a “snippet controller”.
But hey, the “snippet” component is actually extendable, one could make a plugin for this!
But hey, that already exists :smile: (I honestly didn’t know about this before)

4 Likes