Forms and Controllers

Improvements?

Let us know by posting here.

From Dashboard to Front-end Customization

Concrete CMS's Express, introduced in version 8, offers a way to build complex database objects using Concrete attributes. Central to this is the Express Form, used for adding and updating data in express objects.

Creating an Express Form

In the Concrete Dashboard, you create an Express Form by grouping form controls into field sets.

Fieldset Creation

Dashboard Forms

These forms, primarily for site authors, editors, and administrators, are aesthetically pleasing and functional within the Concrete dashboard.

Dashboard Form

Express Forms in Front-end

Express extends beyond the Dashboard. Using the form block on your site, you can create Express objects. Since version 8.1, it's possible to use the Form block to deploy existing Express forms on the front-end.

Frontend Form 1 Frontend Form 2

Beyond Default Functionality

While the default forms integrate well with Twitter Bootstrap or basic styles, Concrete CMS facilitates customization of form appearance, adding advanced processing, validation, or notification logic for submissions.

Terminology and Glossary

Understanding Express Forms in Concrete CMS requires familiarity with specific terms:

Form

Express Form: An object tied to an Express entity, created via Dashboard or package installation, combining attribute keys and controls into field sets.

Context

Context object indicates the form's rendering or access context, including:

  • Front-end Form
  • Standard View
  • Dashboard View
  • Dashboard Form

Implemented via Concrete\Core\Express\Form\Context\ContextInterface.

Form Controller

Controls Express Form behaviors:

  • Notification
  • Processing
  • Object Persistence
  • Context Object Delivery

Uses various methods to alter form processes, with a default controller Concrete\Core\Express\Controller\StandardController. Any controller must implement Concrete\Core\Express\Controller\ControllerInterface.

Form Control View

Class holding data about a form control, including template loading.

Form Control Renderer

A PHP class for rendering specific form controls, specified by the control view.

Context Registry

Concrete\Core\Form\Context\Registry\ContextRegistryInterface object, provided by form controller, mapping abstract contexts to PHP objects for theming flexibility.

Processor

Concrete\Core\Express\Form\Processor\ProcessorInterface object, from form controller, for handling form validation and successful submission responses.

Entry Manager

Concrete\Core\Express\Entry\EntryManagerInterface object, managing object persistence and attribute updates.

Notifier

Concrete\Core\Express\Entry\Notifier\NotifierInterface object, from form controller, for sending express form notifications.


These terms are key to customizing the design of an Express form.

Advanced Express Controller Customization

Express Form Controller in Concrete CMS enables extensive customizations including:

  • Custom validation logic
  • Custom submission notifications
  • Custom response handlers for form submission
  • Custom code execution for object save, update, or delete

Custom Controller Creation and Attachment

Create and attach a custom controller to your Express entity. Follow instructions in Customizing Form and Attribute Markup with Custom Contexts for setup.

Implementing Custom Validation

Custom Form Processor

  1. Create FormProcessor.php in packages/my_site/src/MySite/Express/Form/Processor/. Extend it from StandardProcessor.
  2. Modify FormController.php to return this custom processor.

    namespace MySite\Express\Form\Processor;
    use Concrete\Core\Express\Form\Processor\StandardProcessor;
    
    class FormProcessor extends StandardProcessor {}
    
    // In FormController.php
    public function getFormProcessor() {
        return $this->app->make('\MySite\Express\Form\Processor\FormProcessor');
    }
    

Custom Validator

  1. Create FormValidator.php in packages/my_site/src/MySite/Express/Form/Validator/. Extend it from StandardValidator.
  2. Update FormProcessor.php to return this custom validator.

    namespace MySite\Express\Form\Validator;
    use Concrete\Core\Express\Form\Validator\StandardValidator;
    
    class FormValidator extends StandardValidator {}
    
    // In FormProcessor.php
    public function getValidator(Request $request) {
        return new \MySite\Express\Form\Validator\FormValidator($this->app, $this->app->make('error'), $request);
    }
    
  3. Modify FormValidator for desired validation by adding routines implementing RoutineInterface.

Custom Responses

Customize deliverResponse in FormProcessor for alternative responses like JSON.

public function deliverResponse(Entry $entry, $requestType, RedirectResponse $response = null) {
    $data['success'] = 1;
    return new \Symfony\Component\HttpFoundation\JsonResponse($data);
}

Custom Notification

Implement dynamic, conditional notification for Express Form submissions.

  1. Create FormNotifier.php in packages/my_site/src/MySite/Express/Entry/Notifier/. Extend it from StandardNotifier.
  2. Customize FormController.php to use FormNotifier.

    namespace MySite\Express\Entry\Notifier;
    use Concrete\Core\Notification\Notifier\StandardNotifier;
    
    class FormNotifier extends StandardNotifier {}
    
    // In FormController.php
    public function getNotifier(NotificationProviderInterface $provider = null) {
        return parent::getNotifier($provider);
    }
    
  3. Implement custom notification logic in MyFormSubmissionEmailNotification.php, determining recipients based on form inputs.

Custom Code on Entry Lifecycle Events

  1. Create EntryManager.php in packages/my_site/src/MySite/Express/Entry/. Extend it from BaseEntryManager.
  2. Update FormController.php to return EntryManager.

    namespace MySite\Express\Entry;
    use Concrete\Core\Express\Entry\Manager as BaseEntryManager;
    
    class EntryManager extends BaseEntryManager {}
    
    // In FormController.php
    public function getEntryManager(Request $request) {
        return new EntryManager($this->app->make(EntityManager::class), $request);
    }
    
  3. Customize EntryManager methods (addEntry, deleteEntry, saveEntryAttributesForm) for specific actions during entry lifecycle events.