附加文件停止工作octobercms电子邮件ajax表单

时间:2017-12-05 11:56:23

标签: javascript php jquery ajax octobercms

以下设置一直有效,直到它停止,现在我很困惑。 我在OctoberCMS中创建了一个带文件附件的联系表单,如下所示

{{ form_ajax('ContactForm::onSend', { files: 'true',  flash: 'true', 'data-request-files':true, 'data-request-validate': true }) }}
    <input type="hidden" name="handler" value='onSave'>
    <fieldset class="form">
        <input type="name" name="name" placeholder="Imię i nazwisko" required>
        <input type="email" name="email" placeholder="E-mail" required>
        <input type="phone" name="phone" placeholder="Telefon">
        <input type="text" name="subject" placeholder="Temat" >
        <textarea name="theMessage" placeholder="Zapytanie" required style="width: 100%; height: 140px;"></textarea>
        <input type="file" name="fileAttachment" id="fileAttachment" class="inputfile"  data-multiple-caption="wybrano {count}" /><label for="fileAttachment">wybierz plik </label><span class='attachmentName'></span>

    </fieldset>
        <button type="submit" class="send" data-attach-loading>Wyślij</button>
    </fieldset>

{{ form_close() }}

发送电子邮件的组件

<?php namespace Depcore\Parts\Components;
use Cms\Classes\ComponentBase;

use Mail;
use Lang;
use Flash;
use Input;
use Validator;
use ValidationException;
use Redirect;
use System\Models\File;

class ContactForm extends ComponentBase
{
    public function componentDetails()
    {
        return [
            'name'        => 'depcore.parts::lang.components.contactFormTitle',
            'description' => 'depcore.parts::lang.components.contactFormDescription'
        ];
    }

    public function defineProperties()
    {
        return [
              'emailTo' => [
                    'title' => 'depcore.parts::components.emailAddress',
                    'description' => 'depcore.parts::components.destinationEmailDescription',
                    'default' => 'zamowienia@kludi.pl',
                    'validationPattern' => "\A[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\z",
                    'ValidationMessage' => ''
            ]
        ];
    }

    public function onSend(){

        $data = post();
        $vars = [
            'name' => Input::get('name'),
            'subject' => Input::get('subject'),
            'phone' => Input::get('phone'),
            'theMessage' => Input::get('theMessage'),
            'fileAttachment' => Input::file('fileAttachment'),
        ];

        $rules = [
                'name' => 'required',
                'email' => 'required|email'
            ];

        $validator = Validator::make($data, $rules);

        if ($validator->fails())
            throw new ValidationException( $validator );
        else {

        Mail::send('depcore.parts::mail.message', $vars, function( $message )  use  ( $vars )  {

            // $message->to($this->property('emailTo'));
            $message->to('adam@depcore.pl');

            if ($vars['fileAttachment']) {
                $file = (new File())->fromPost($vars['fileAttachment']);
                $message->attach($file['path']);
            }

            $message->subject($vars['subject']);
            Flash::success('Wiadomość została wysłana.');
        });

      }
    }

}

据我所知,Input::file('fileAttachemnt')总是返回null,所以我认为它可能是JavaScript框架的一个问题(?)。

这是一个奇怪的事情让我在使用该项目时感到意外,现在我陷入困境。

1 个答案:

答案 0 :(得分:1)

从您的代码中看起来错误地使用了错误的方法

 $vars = [
        'name' => Input::get('name'),
        'subject' => Input::get('subject'),
        'phone' => Input::get('phone'),
        'theMessage' => Input::get('theMessage'),
        'fileAttachment' => Input::get('fileAttachment'), <-- here
 ];

您的代码正在使用此

  

输入:: 获取(&#39; fileAttachemnt&#39);

在现实中应该是这个

  

输入::的文件(&#39; fileAttachemnt&#39);

可能是您更新了代码并且没有注意到;)

更新

好吧我猜是文件门面代码(新文件())存在问题 不要使用它而是我们可以直接使用文件,因为你也没有保存该文件,

可以替换代码并检查一次

$file = (new File())->fromPost($vars['fileAttachment']);
$message->attach($file['path']);
  

$file = $vars['fileAttachment'];
$pathToFile = $file->getPathname();
$fileName = $file->getClientOriginalName();
$mime = $file->getMimeType()
$message->attach($pathToFile, ['as' => $fileName, 'mime' => $mime]);

然后检查它,它应该工作。

MORE UPDATE

我添加了ajax框架的修改版本(添加了js代码段),代码取自10月cms官方git repo,并且刚删除了它的一部分,因此它可以覆盖现有代码而不会发生冲突。

我建议,拿这个代码和创建ajax-fw-override.js文件然后在你的页面上包含文件或者只是复制布局并将其添加到最底部,任何它应该如何来十月默认ajax {%framework%} ,因此它可以覆盖其请求

这不是一个好的解决方案,但考虑到您无法更新您的cms版本,我们可以使用它。 (通过制作重复的布局,我们确保它不会影响其他任何地方)。

我使用控制台在您的网站上对其进行了测试,但它确实有效。所以,看看它,让我知道。

&#13;
&#13;
+ function($) {
  "use strict";

  var Request = function(element, handler, options) {
    var $el = this.$el = $(element);
    this.options = options || {};

    /*
     * Validate handler name
     */
    if (handler === undefined) {
      throw new Error('The request handler name is not specified.')
    }

    if (!handler.match(/^(?:\w+\:{2})?on*/)) {
      throw new Error('Invalid handler name. The correct handler name format is: "onEvent".')
    }

    /*
     * Prepare the options and execute the request
     */
    var $form = options.form ? $(options.form) : $el.closest('form'),
      $triggerEl = !!$form.length ? $form : $el,
      context = {
        handler: handler,
        options: options
      }

    $el.trigger('ajaxSetup', [context])
    var _event = jQuery.Event('oc.beforeRequest')
    $triggerEl.trigger(_event, context)
    if (_event.isDefaultPrevented()) return

    var loading = options.loading !== undefined ? options.loading : null,
      isRedirect = options.redirect !== undefined && options.redirect.length,
      useFlash = options.flash !== undefined,
      useFiles = options.files !== undefined

    if (useFiles && typeof FormData === 'undefined') {
      console.warn('This browser does not support file uploads via FormData')
      useFiles = false
    }

    if ($.type(loading) == 'string') {
      loading = $(loading)
    }

    /*
     * Request headers
     */
    var requestHeaders = {
      'X-OCTOBER-REQUEST-HANDLER': handler,
      'X-OCTOBER-REQUEST-PARTIALS': this.extractPartials(options.update)
    }

    if (useFlash) {
      requestHeaders['X-OCTOBER-REQUEST-FLASH'] = 1
    }

    /*
     * Request data
     */
    var requestData,
      inputName,
      data = {}

    $.each($el.parents('[data-request-data]').toArray().reverse(), function extendRequest() {
      $.extend(data, paramToObj('data-request-data', $(this).data('request-data')))
    })

    if ($el.is(':input') && !$form.length) {
      inputName = $el.attr('name')
      if (inputName !== undefined && options.data[inputName] === undefined) {
        options.data[inputName] = $el.val()
      }
    }

    if (options.data !== undefined && !$.isEmptyObject(options.data)) {
      $.extend(data, options.data)
    }

    if (useFiles) {
      requestData = new FormData($form.length ? $form.get(0) : null)

      if ($el.is(':file') && inputName) {
        $.each($el.prop('files'), function() {
          requestData.append(inputName, this)
        })

        delete data[inputName]
      }

      $.each(data, function(key) {
        requestData.append(key, this)
      })
    } else {
      requestData = [$form.serialize(), $.param(data)].filter(Boolean).join('&')
    }

    /*
     * Request options
     */
    var requestOptions = {
      url: window.location.href,
      crossDomain: false,
      context: context,
      headers: requestHeaders,
      success: function(data, textStatus, jqXHR) {
        /*
         * Halt here if beforeUpdate() or data-request-before-update returns false
         */
        if (this.options.beforeUpdate.apply(this, [data, textStatus, jqXHR]) === false) return
        if (options.evalBeforeUpdate && eval('(function($el, context, data, textStatus, jqXHR) {' + options.evalBeforeUpdate + '}.call($el.get(0), $el, context, data, textStatus, jqXHR))') === false) return

        /*
         * Trigger 'ajaxBeforeUpdate' on the form, halt if event.preventDefault() is called
         */
        var _event = jQuery.Event('ajaxBeforeUpdate')
        $triggerEl.trigger(_event, [context, data, textStatus, jqXHR])
        if (_event.isDefaultPrevented()) return

        if (useFlash && data['X_OCTOBER_FLASH_MESSAGES']) {
          $.each(data['X_OCTOBER_FLASH_MESSAGES'], function(type, message) {
            requestOptions.handleFlashMessage(message, type)
          })
        }

        /*
         * Proceed with the update process
         */
        var updatePromise = requestOptions.handleUpdateResponse(data, textStatus, jqXHR)

        updatePromise.done(function() {
          $triggerEl.trigger('ajaxSuccess', [context, data, textStatus, jqXHR])
          options.evalSuccess && eval('(function($el, context, data, textStatus, jqXHR) {' + options.evalSuccess + '}.call($el.get(0), $el, context, data, textStatus, jqXHR))')
        })

        return updatePromise
      },
      error: function(jqXHR, textStatus, errorThrown) {
        var errorMsg,
          updatePromise = $.Deferred()

        if ((window.ocUnloading !== undefined && window.ocUnloading) || errorThrown == 'abort')
          return

        /*
         * Disable redirects
         */
        isRedirect = false
        options.redirect = null

        /*
         * Error 406 is a "smart error" that returns response object that is
         * processed in the same fashion as a successful response.
         */
        if (jqXHR.status == 406 && jqXHR.responseJSON) {
          errorMsg = jqXHR.responseJSON['X_OCTOBER_ERROR_MESSAGE']
          updatePromise = requestOptions.handleUpdateResponse(jqXHR.responseJSON, textStatus, jqXHR)
        }
        /*
         * Standard error with standard response text
         */
        else {
          errorMsg = jqXHR.responseText ? jqXHR.responseText : jqXHR.statusText
          updatePromise.resolve()
        }

        updatePromise.done(function() {
          $el.data('error-message', errorMsg)

          /*
           * Trigger 'ajaxError' on the form, halt if event.preventDefault() is called
           */
          var _event = jQuery.Event('ajaxError')
          $triggerEl.trigger(_event, [context, errorMsg, textStatus, jqXHR])
          if (_event.isDefaultPrevented()) return

          /*
           * Halt here if the data-request-error attribute returns false
           */
          if (options.evalError && eval('(function($el, context, errorMsg, textStatus, jqXHR) {' + options.evalError + '}.call($el.get(0), $el, context, errorMsg, textStatus, jqXHR))') === false)
            return

          requestOptions.handleErrorMessage(errorMsg)
        })

        return updatePromise
      },
      complete: function(data, textStatus, jqXHR) {
        $triggerEl.trigger('ajaxComplete', [context, data, textStatus, jqXHR])
        options.evalComplete && eval('(function($el, context, data, textStatus, jqXHR) {' + options.evalComplete + '}.call($el.get(0), $el, context, data, textStatus, jqXHR))')
      },

      /*
       * Custom function, requests confirmation from the user
       */
      handleConfirmMessage: function(message) {
        var _event = jQuery.Event('ajaxConfirmMessage')

        _event.promise = $.Deferred()
        if ($(window).triggerHandler(_event, [message]) !== undefined) {
          _event.promise.done(function() {
            options.confirm = null
            new Request(element, handler, options)
          })
          return false
        }

        if (_event.isDefaultPrevented()) return
        if (message) return confirm(message)
      },

      /*
       * Custom function, display an error message to the user
       */
      handleErrorMessage: function(message) {
        var _event = jQuery.Event('ajaxErrorMessage')
        $(window).trigger(_event, [message])
        if (_event.isDefaultPrevented()) return
        if (message) alert(message)
      },

      /*
       * Custom function, focus fields with errors
       */
      handleValidationMessage: function(message, fields) {
        $triggerEl.trigger('ajaxValidation', [context, message, fields])

        var isFirstInvalidField = true
        $.each(fields, function focusErrorField(fieldName, fieldMessages) {
          fieldName = fieldName.replace(/\.(\w+)/g, '[$1]')

          var fieldElement = $form.find('[name="' + fieldName + '"], [name="' + fieldName + '[]"], [name$="[' + fieldName + ']"], [name$="[' + fieldName + '][]"]').filter(':enabled').first()
          if (fieldElement.length > 0) {

            var _event = jQuery.Event('ajaxInvalidField')
            $(window).trigger(_event, [fieldElement.get(0), fieldName, fieldMessages, isFirstInvalidField])

            if (isFirstInvalidField) {
              if (!_event.isDefaultPrevented()) fieldElement.focus()
              isFirstInvalidField = false
            }
          }
        })
      },

      /*
       * Custom function, display a flash message to the user
       */
      handleFlashMessage: function(message, type) {},

      /*
       * Custom function, redirect the browser to another location
       */
      handleRedirectResponse: function(url) {
        window.location.href = url
      },

      /*
       * Custom function, handle any application specific response values
       * Using a promisary object here in case injected assets need time to load
       */
      handleUpdateResponse: function(data, textStatus, jqXHR) {

        /*
         * Update partials and finish request
         */
        var updatePromise = $.Deferred().done(function() {
          for (var partial in data) {
            /*
             * If a partial has been supplied on the client side that matches the server supplied key, look up
             * it's selector and use that. If not, we assume it is an explicit selector reference.
             */
            var selector = (options.update[partial]) ? options.update[partial] : partial
            if ($.type(selector) == 'string' && selector.charAt(0) == '@') {
              $(selector.substring(1)).append(data[partial]).trigger('ajaxUpdate', [context, data, textStatus, jqXHR])
            } else if ($.type(selector) == 'string' && selector.charAt(0) == '^') {
              $(selector.substring(1)).prepend(data[partial]).trigger('ajaxUpdate', [context, data, textStatus, jqXHR])
            } else {
              $(selector).trigger('ajaxBeforeReplace')
              $(selector).html(data[partial]).trigger('ajaxUpdate', [context, data, textStatus, jqXHR])
            }
          }

          /*
           * Wait for .html() method to finish rendering from partial updates
           */
          setTimeout(function() {
            $(window)
              .trigger('ajaxUpdateComplete', [context, data, textStatus, jqXHR])
              .trigger('resize')
          }, 0)
        })

        /*
         * Handle redirect
         */
        if (data['X_OCTOBER_REDIRECT']) {
          options.redirect = data['X_OCTOBER_REDIRECT']
          isRedirect = true
        }

        if (isRedirect) {
          requestOptions.handleRedirectResponse(options.redirect)
        }

        /*
         * Handle validation
         */
        if (data['X_OCTOBER_ERROR_FIELDS']) {
          requestOptions.handleValidationMessage(data['X_OCTOBER_ERROR_MESSAGE'], data['X_OCTOBER_ERROR_FIELDS'])
        }

        /*
         * Handle asset injection
         */
        if (data['X_OCTOBER_ASSETS']) {
          assetManager.load(data['X_OCTOBER_ASSETS'], $.proxy(updatePromise.resolve, updatePromise))
        } else {
          updatePromise.resolve()
        }

        return updatePromise
      }
    }

    if (useFiles) {
      requestOptions.processData = requestOptions.contentType = false
    }

    /*
     * Allow default business logic to be called from user functions
     */
    context.success = requestOptions.success
    context.error = requestOptions.error
    context.complete = requestOptions.complete
    requestOptions = $.extend(requestOptions, options)
    requestOptions.data = requestData

    /*
     * Initiate request
     */
    if (options.confirm && !requestOptions.handleConfirmMessage(options.confirm)) {
      return
    }

    if (loading) loading.show()
    $(window).trigger('ajaxBeforeSend', [context])
    $el.trigger('ajaxPromise', [context])

    return $.ajax(requestOptions)
      .fail(function(jqXHR, textStatus, errorThrown) {
        if (!isRedirect) {
          $el.trigger('ajaxFail', [context, textStatus, jqXHR])
        }
        if (loading) loading.hide()
      })
      .done(function(data, textStatus, jqXHR) {
        if (!isRedirect) {
          $el.trigger('ajaxDone', [context, data, textStatus, jqXHR])
        }
        if (loading) loading.hide()
      })
      .always(function(dataOrXhr, textStatus, xhrOrError) {
        $el.trigger('ajaxAlways', [context, dataOrXhr, textStatus, xhrOrError])
      })
  }

  Request.DEFAULTS = {
    update: {},
    type: 'POST',
    beforeUpdate: function(data, textStatus, jqXHR) {},
    evalBeforeUpdate: null,
    evalSuccess: null,
    evalError: null,
    evalComplete: null
  }

  /*
   * Internal function, build a string of partials and their update elements.
   */
  Request.prototype.extractPartials = function(update) {
    var result = []

    for (var partial in update)
      result.push(partial)

    return result.join('&')
  }

  // REQUEST PLUGIN DEFINITION
  // ============================

  var old = $.fn.request

  $.fn.request = function(handler, option) {
    var args = arguments

    var $this = $(this).first()
    var data = {
      evalBeforeUpdate: $this.data('request-before-update'),
      evalSuccess: $this.data('request-success'),
      evalError: $this.data('request-error'),
      evalComplete: $this.data('request-complete'),
      confirm: $this.data('request-confirm'),
      redirect: $this.data('request-redirect'),
      loading: $this.data('request-loading'),
      flash: $this.data('request-flash'),
      files: $this.data('request-files'),
      form: $this.data('request-form'),
      update: paramToObj('data-request-update', $this.data('request-update')),
      data: paramToObj('data-request-data', $this.data('request-data'))
    }
    if (!handler) handler = $this.data('request')
    var options = $.extend(true, {}, Request.DEFAULTS, data, typeof option == 'object' && option)
    return new Request($this, handler, options)
  }

  $.fn.request.Constructor = Request

  $.request = function(handler, option) {
    return $(document).request(handler, option)
  }

  // REQUEST NO CONFLICT
  // =================

  $.fn.request.noConflict = function() {
    $.fn.request = old
    return this
  }

  // REQUEST DATA-API
  // ==============

  function paramToObj(name, value) {
    if (value === undefined) value = ''
    if (typeof value == 'object') return value

    try {
      return JSON.parse(JSON.stringify(eval("({" + value + "})")))
    } catch (e) {
      throw new Error('Error parsing the ' + name + ' attribute value. ' + e)
    }
  }

}(window.jQuery);
&#13;
&#13;
&#13;