CakePHP 3.x - 编辑:日期在提交时具有空字段,尽管它们已经存在

CakePHP 3.x - Edit: Dates having empty fields upon submission despite them already existing

我有三个table:

在 Sessions table 中,我有一个使用 Daterangepicker jQuery 脚本的日期字段。

<input class='form-control' type="text" name="daterange" id="daterange"
                                   placeholder='Session dates'/>

在 MySQL 中,我的会话 table 中有两个属性,分别称为 date_startdate_end。当有人使用 'daterange' 输入时,他们能够使用从 Daterangepicker 构建的日历到 select 两个日期。 Upon choosing those two dates, those two dates become date_start and date_end, and when choosing new dates, those dates are saved successfully.

但是,这个特定的表单是编辑视图,而不是添加,我的问题是如果我不更改 daterange 表单输入然后提交表单,它无法成功保存任何内容并且表示属性 date_start 和 date_end 为空,需要填写(它们在 MySQL 中不是空值)。我使用 Javascript 脚本将现有日期范围输入到字段中,如下所示:

<script>
$(document).ready(function () {
    var daterange = '<?= h($booking->session->date_start->i18nFormat('dd/MM/YYYY') . ' - ' . $booking->session->date_end->i18nFormat('dd/MM/YYYY'));?>';
    $('#daterange').val(daterange);
});
</script>

例如,如果 date_start = 2017-02-02date_end = 2017-02-03,那么 daterange 表单输入将在转换为我的本地日期格式后显示:

02/02/2017 - 03/02/2017

$booking 指的是控制器中设置为视图的语句:

$booking = $this->Bookings->get($id,[
    'contain'=>['Sessions']
]);

当我打印 $booking->session['date_start']$booking->session['date_end'] 时,我可以看到日期。在 CakePHP 变量中,我还可以正确地看到日期。提交的时候才看到请求数据是空的,patchEntity的debug也一样显示。

例如,如果在使用编辑表单之前说 date_start = 2017-02-02 和 date_end = 2017-02-03,然后执行 pr($booking->session['date_start']) ,我会打印 2/2/2017(本地日期格式)。

此外,这些是隐藏的 date_startdate_end 输入,如果 daterange 输入被填充,它们会自动填充。

<?php
echo $this->Form->hidden('session[date_start][year]', ['id' => 'start_year']);
echo $this->Form->hidden('session[date_start][month]', ['id' => 'start_month']);
echo $this->Form->hidden('session[date_start][day]', ['id' => 'start_day']);
echo $this->Form->hidden('session[date_end][year]', ['id' => 'end_year']);
echo $this->Form->hidden('session[date_end][month]', ['id' => 'end_month']);
echo $this->Form->hidden('session[date_end][day]', ['id' => 'end_day']);
?>

以及执行此操作的相应 Daterangepicker JS:

<script type="text/javascript">
$(function () {
    $('input[name="daterange"]').daterangepicker({
        autoUpdateInput: false,
        locale: {
            cancelLabel: 'Clear'
        },
        format: "DD/MM/YYYY",
        startDate: new Date(new Date().getTime() + 24 * 60 * 60 * 1000),
        endDate: new Date(new Date().getTime() + 24 * 60 * 60 * 1000),
        minDate: new Date(new Date().getTime() + 24 * 60 * 60 * 1000)
    });

    $('input[name="daterange"]').on('apply.daterangepicker', function (ev, picker) {
        $(this).val(picker.startDate.format('DD/MM/YYYY') + ' - ' + picker.endDate.format('DD/MM/YYYY'));
        $("#start_year").val(picker.startDate.format('YYYY'));
        $("#start_month").val(picker.startDate.format('MM'));
        $("#start_day").val(picker.startDate.format('DD'));
        $("#end_year").val(picker.endDate.format('YYYY'));
        $("#end_month").val(picker.endDate.format('MM'));
        $("#end_day").val(picker.endDate.format('DD'));
    });

    $('input[name="daterange"]').on('cancel.daterangepicker', function (ev, picker){
        $(this).val('');
    });
});
</script>

总结:除非我使用相应的表单输入主动更改日期,否则现有日期由于某种原因被清空,并且提交无法保存任何表单。

更新: 到目前为止,我尝试了两件事:根据 ahoffner 的建议,如果在控制器中为空,则取消设置 date_startdate_end,这不工作。我还尝试删除隐藏的表单输入。这允许我在日期未更改的情况下提交,但如果我更改了它们,虽然表单仍会成功提交,但日期不会更改。

更新 2: 根据 ahoffner 的要求,下面是 $this->request->data()。在这个特定的提交中,我将 amount 更改为 300,并且没有修改日期。结果保存失败

Array
(
    [session] => Array
        (
            [studio_id] => 2
            [date_start] => Array
                (
                    [year] => 
                    [month] => 
                    [day] => 
                )

            [date_end] => Array
                (
                    [year] => 
                    [month] => 
                    [day] => 
                )

            [session_genre] => test
            [engineer_id] => 2
            [no_people] => 3
            [studio_usage] => test
            [otherpeople_req] => 
            [special_req] => 
            [status] => confirmed
        )

    [optionsRadios] => manydays
    [singledate] => 
    [daterange] => 09/02/2017 - 10/02/2017
    [firstname] => 
    [lastname] => 
    [email] => 
    [phoneno] => 
    [textbox] => 
    [amount] => 300
)

Bookingtable的初始化函数如下:

public function initialize(array $config)
    {
        parent::initialize($config);

        $this->table('bookings');
        $this->displayField('id');
        $this->primaryKey('id');

        $this->addBehavior('Timestamp');

        $this->belongsTo('Artists', [
            'foreignKey' => 'artist_id',
            'joinType' => 'INNER'
        ]);
        $this->hasMany('Payments', [
            'foreignKey' => 'booking_id'
        ]);
        $this->hasOne('Sessions', [
            'foreignKey' => 'booking_id'
        ]);
    }

It's only when submitting, and seeing the request data that they're empty..

当您将数组代替实体值传递给 patchEntity 时,odd/special 事情可能会发生。

$this->request->data() 的输出所示,date_start 设置的值 & 最后,一个数组包含:

Array
(
    [year] =>
    [month] =>
    [day] =>
)

当调用 patchEntity 时,它会尝试将 $booking->session->date_startdate_end 设置为该数组 (['year' => '', 'month' => '', 'day' => ''])。

CakePHP 将在调用 patchEntity 或 newEntity 时更新提供的每个数组键 的实体值。即使值是空的,或者在这种情况下,包含一个 non-empty 数组 - 它仍然会尝试更新该键的值。

由于该字段上的类型可能是 date - 它最终会在编组值时尝试将其类型转换为 date-formatted 字符串。如果这些键都是空白的,looking at the source, 它基本上只是删除该数组,将其转换为 null。如果这些键有值,它会将它们转换为日期字符串(如“2017-02-02”)。

同样,解决此问题的一种方法是确保不将带有空键的数组传递给 patchEntity,使用这种格式的请求数据看起来更像是:

$data = $this->request->data();

if(empty($data['session']['date_start']['year']) || empty($data['session']['date_start']['month']) || empty($data['session']['date_start']['day'])) {
    unset($data['session']['date_start']);
}

if(empty($data['session']['date_end']['year']) || empty($data['session']['date_end']['month']) || empty($data['session']['date_end']['day'])) {
    unset($data['session']['date_end']);
}

$booking = $this->Bookings->patchEntity($booking, $data);

然而,这些在提交时为空白可能是有原因的 - 当它们不应该放在第一位时。解决这个问题也会解决这个问题,因为他们最终不会制作这个空白数组。根据示例代码检查这些字段的值($("#start_year").val() 等),这些字段不应为空。 'apply.daterangepicker' 函数是否按预期调用?是否按预期应用了值(picker.startDate.format('YYYY') 等)?