3

I'm attempting to create a module with a custom form that allows users to upload a file using a managed_file field. The name of my module is foundation_settings and the file structure is:

foundation_settings
  -foundation_settings.info.yml
  -foundation_settings.module
  -src
    -Form
      -FoundationForm.php

Inside FoundationForm.php I'm building the form with the following code:

public function buildForm(array $form, FormStateInterface $form_state) {
    $config = $this->config('foundation.settings');
        $form['icons'] = [
            '#type'            => 'details',
            '#title'           => t('Front Page Icons'),
            '#open'            => FALSE,
            'icon1'            => [
                '#type'           => 'fieldset',
                '#title'          => t('First Icon'),
                'icon1_file'        => [
                    '#type'            => 'managed_file',
                    '#name'            => 'icon1',
                    '#title'           => t('First Icon Image'),
                    '#default_value'   => $config->get('icon1_file'),
                    '#upload_location' => 'public://',
                ],
            ],
       ];
}

However I'm not sure how to handle the managed_file when the form is being submitted. In my submitForm function I have

public function submitForm(array&$form, FormStateInterface $form_state) {
    $imageid = $form_state->getValue('icon1_file');
    $file = file_load($imageid[0]);
        if (gettype($file) == 'object') {
            $file->status = FILE_STATUS_PERMANENT;
        }
        $this->config('foundation.settings')
             ->set('icon1_file', $form_state->getValue('icon1_file'))
            ->save();
            $file->save();
}

The upload and saving works okay but I keep receiving this error after submitting

The file used in the First Icon Image field may not be referenced.

How are you supposed to use managed_file field in custom form plugins?

8

I think the issue we had was understanding the data that the form was sending back to us when using the 'managed_file' type. This creates an entity of File and stores the image information directly into the table called 'file_managed' in your database, but also saves the file to your directories based upon where you send it. So take this code for example:

$form['mainslider_slide_one']['image_dir'] = [
    '#type'                 => 'managed_file',
    '#upload_location'      => 'public://module-images/home-slider-images/',
    '#multiple'             => FALSE,
    '#description'          => t('Allowed extensions: gif png jpg jpeg'),
    '#upload_validators'    => [
      'file_validate_is_image'      => array(),
      'file_validate_extensions'    => array('gif png jpg jpeg'),
      'file_validate_size'          => array(25600000)
    ],
    '#title'                => t('Upload an image file for this slide')
];

For the '#upload_location' we are telling the file to be stored in our public folder under the specified directory (sites/sitename/files/ directory). So now we have the actual file stored where we want, as well as data stored in the database.

When we receive the information back (under validation for instance) we have the following code:

public function validateForm(array &$form, FormStateInterface $form_state) {
    $managedFileId_imageOne = $form_state->getValue(['mainslider_slide_one' => 'image_dir']);

    if (empty($managedFileId_imageOne)) {
        $form_state->setErrorByName('test', 'No image found for image one');
    }
}

The result of $managedFileId_imageOne will either be an empty array (whereas I am sending an error message back) or an array of fid's. The fid is the location in the database. This is the information that we ended up saving into our settings file data. So when we pull the information into our program we are querying for the 'fid' located in the 'file_managed' table using the Entity::load method.

NOTE/UPDATE:

Don't forget that files uploaded in this manner are currently, by default, set to be temporary (status column in the "file_managed" table). You need to set the file to permanent to manually set status to 1 so they are not temporary. I believe this is functionality that is currently a bug and they are looking into possibly updating this in future releases.

Sample from Jasodeep

   $image = $form_state->getValue('image');
   $file = File::load( $image[0] );
   $file->setPermanent();
   $file->save();

Hope this helps at least get you on your way!

  • 2
    I had issues with the temporary state of the image in a custom config form! thanks for the info! – Renrhaf Mar 8 '18 at 5:48

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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