Front end form not generating Dataobject

Hello there,

I’m trying to create a front end form for simple posts, it’s just a prototype to test the workflow, but I can’t get any DataObject to be created, it’s like the “generatePost” function is never called. I even have the print(“generatePost”) line that should appear if the function was called but it never appears.

I did this previously in SS3 but with all the namespaces and “use Library”, I’m not sure I’m doing it right in SS4. As I spent the whole morning trying to understand what I did wrong, I thought maybe someone here could find why this is not working

So I have my PostObject.php

<?php

namespace App\Hub; 

use SilverStripe\ORM\DataObject;
use SilverStripe\Security\Permission;
use SilverStripe\Security\Member;

class PostObject extends DataObject {
        
    private static $db = [
        'Title' => 'Varchar',
        'EmbedCode' => 'Varchar',
        'IsActive' => 'Boolean(0)'
    ];

    private static $has_one = [
        'Member' => Member::class 
    ];   

    public function getCMSFields(){
        $fields = parent::getCMSFields();        
        return $fields;
    } 
} 

and I have a front end form to create a PostObject
but nothing happens when I click Submit outside of being redirected to ./app/AddPostForm/

<?php

namespace App\Hub;

use PageController;
use SilverStripe\CMS\Controllers\ContentController;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\Form;
use SilverStripe\Forms\FormAction;
use SilverStripe\Forms\RequiredFields;
use SilverStripe\Forms\TextField;
use SilverStripe\Forms\TextareaField;


class HubPageController extends PageController 
{

    private static $allowed_actions = [
        'Posts' => true,
        'AddPostForm',
        'generatePost'
    ];

    public function Posts()
    {
        return PostObject::get();
    }

    public function AddPostForm()
    {
        
        $postForm = Form::create(
            $this,
            __FUNCTION__,
            FieldList::create(
                TextField::create('Title', 'Title of post'),
                TextareaField::create('URL', 'URL')
            ),
            FieldList::create(
                FormAction::create('generatePost', 'Submit')
            ),
            RequiredFields::create('Title')
        );

        return $postForm;

    }

    public function generatePost($data, $form)
    {
        $post = PostObject::create();
        print("generatePost");
        $post->Title = $data['Title'];
        $post->EmbedCode = $data['URL'];
        $form->saveInto($post);
        $post->write();

        $form->sessionMessage('Thanks for posting!','Good');

        return $this->redirectBack();
    }

}

From what I understand, the FormAction::create() doesn’t work as it should. I can write whatever I want instead of generatePost, it doesn’t trigger any error, and when I come back to generatePost the function is not called either, like it does nothing at all.

How do you include the form in the templates? Do you have the $AddPostForm tag somewhere?

Apart from that, the only thing I added is a private static $url_segment = 'post'; to the controller and a new route to the YAML because I do not use the CMS.

<?php

use SilverStripe\Control\Controller;
use SilverStripe\Forms\FieldList;
use SilverStripe\Forms\Form;
use SilverStripe\Forms\FormAction;
use SilverStripe\Forms\RequiredFields;
use SilverStripe\Forms\TextField;
use SilverStripe\Forms\TextareaField;
use SilverStripe\ORM\DataObject;
use SilverStripe\Security\Member;

class PostObject extends DataObject {
    private static $db = [
        'Title' => 'Varchar',
        'EmbedCode' => 'Varchar',
        'IsActive' => 'Boolean(0)'
    ];

    private static $has_one = [
        'Member' => Member::class
    ];
}

class PostController extends Controller
{
    private static $url_segment = 'post';

    private static $allowed_actions = [
        'AddPostForm',
        'generatePost'
    ];

    public function AddPostForm()
    {
        return Form::create(
            $this,
            __FUNCTION__,
            FieldList::create(
                TextField::create('Title', 'Title of post'),
                TextareaField::create('URL', 'URL')
            ),
            FieldList::create(
                FormAction::create('generatePost', 'Submit')
            ),
            RequiredFields::create('Title')
        );
    }

    public function generatePost($data, $form)
    {
        $post = PostObject::create();
        $post->Title = $data['Title'];
        $post->EmbedCode = $data['URL'];
        $form->saveInto($post);
        $post->write();

        $form->sessionMessage('Thanks for posting!','Good');

        return $this->redirectBack();
    }

}

@ntd @kaftka @GuySartorelli

Ok, so I checked the file system and what happens is that composer in the command line of the VPS created files under the Root user, when I add files via SFTP it’s another username Ubuntu. So instead of trying to bypass how OVH set up their Linux servers, I will just code everything in MAMP then when the Web app is ready for production, I’ll send everything to the VPS in one go. But yeah, the code works properly in MAMP and it’s definitely a cache issue but as you can’t use Root user even if composer creates files as Root user, I’ll just skip the madness by developing locally

Your code works fine here.

Thanks for checking! I still didn’t make it work on my side, the data object doesn’t appear in the back end.

Is there anything on the page when you are redirected to /AddPostForm? (404 content not found, an error)

Did you do a flush in the browser (?flush=1)

The code looks fine otherwise

@ntd @kaftka I have a tag $AddPostForm, the form appears and when I click submit, I have a Page not found under /AddPostForm though no other error message. I flushed the cache through SSH several times. I have everything in the App\Hub namespace, not sure if that affects the way the form is handled.

Try flushing in the browser rather than cli (append ?flush=1 to your url).
Once done, load the page again without the flush and test the form (otherwise your redirectBack will flush again which is annoying).

Your namespace should be fine.

This exact code is working for me as well (without the change recommended by @ntd). Not sure what’s going wrong on your end but it isn’t the code.

What version of silverstripe/framework are you using? (You can use composer show silverstripe/framework | grep versions to see this)

It’s giving me “versions : * 4.9.3”