laravel-mongodb icon indicating copy to clipboard operation
laravel-mongodb copied to clipboard

Carbon/DateTime is not being converted when I save it in an array

Open marcu87 opened this issue 8 years ago • 6 comments

Hi,

So my problem is that a Carbon date is not automatically converted to a MongoDate (like it says in the docs) if I store that date inside an array.

My code is this:

$product->stock = [
    'amount'       => $amount,
    'lastUpdate' => Carbon::now(),
];

$product->save();

and I get this on my document for the lastUpdate field:

lastUpdate:Object
date:"2017-07-27 09:42:00.000000"
timezone_type:3
timezone:"UTC"

It works just fine if I do this:

'lastUpdate' => new \MongoDB\BSON\UTCDateTime(new \DateTime('now'))

becomes:

lastUpdate:2017-07-27 11:49:47.000

The documentation says that my code should work:

Eloquent allows you to work with Carbon/DateTime objects instead of MongoDate objects. Internally, these dates will be converted to MongoDate objects when saved to the database. If you wish to use this functionality on non-default date fields you will need to manually specify them as described here: http://laravel.com/docs/eloquent#date-mutators

and it actually does... but not inside an array.

By the way, I also defined this:

    protected $dates = [
        'stock.lastUpdate',
    ];

So is this a bug? Or I am doing something wrong?

marcu87 avatar Jul 27 '17 09:07 marcu87

so do i. when i use Carbon:now() for created_at,It will save a array just like: created_at: [ "date" => "2018-01-11 15:49:21.000000", "timezone_type" => 3, "timezone" => "PRC", ], in fact, I want to save a MongoDate to it.

dark-wind avatar Jan 11 '18 09:01 dark-wind

How to define $dates attribute for array of documents. For example I want following structure.

versions => [
  [
    updated_at => 'some date',
    created_at => 'some_date'
  ],
  [
    updated_at => 'some date',
    created_at => 'some_date'
  ],
]

Is there any way to achieve this without explicitly converting date like below

versions => [
  [
    updated_at => new \MongoDB\BSON\UTCDateTime(new \DateTime('now')),
    created_at => new \MongoDB\BSON\UTCDateTime(new \DateTime('now'))'
  ],
  [
    updated_at => new \MongoDB\BSON\UTCDateTime(new \DateTime('now'))',
    created_at => new \MongoDB\BSON\UTCDateTime(new \DateTime('now'))
  ],
]

prashant-pokhriyal avatar Feb 05 '18 08:02 prashant-pokhriyal

I seem solved this problem.It's very useful to add a data attribute. This is my model file

<?php

namespace Modules\Project\Entities;

use Jenssegers\Mongodb\Eloquent\Model;
use Jenssegers\Mongodb\Eloquent\SoftDeletes;

//use Illuminate\Database\Eloquent\Model;
//use Illuminate\Database\Eloquent\SoftDeletes;

class Project extends Model
{
    protected $connection = 'mongodb';

    use SoftDeletes;

    protected $dates = ['start_date_at', 'online_date_at'];

}

dark-wind avatar Feb 07 '18 10:02 dark-wind

How to define $dates attribute for array of documents. For example I want following structure.

versions => [
  [
    updated_at => 'some date',
    created_at => 'some_date'
  ],
  [
    updated_at => 'some date',
    created_at => 'some_date'
  ],
]

Is there any way to achieve this without explicitly converting date like below

versions => [
  [
    updated_at => new \MongoDB\BSON\UTCDateTime(new \DateTime('now')),
    created_at => new \MongoDB\BSON\UTCDateTime(new \DateTime('now'))'
  ],
  [
    updated_at => new \MongoDB\BSON\UTCDateTime(new \DateTime('now'))',
    created_at => new \MongoDB\BSON\UTCDateTime(new \DateTime('now'))
  ],
]

Hey, did you get the solution for such attributes? I am also facing the same

"history" : [ { "action" : "initiate", "offer_price" : 450000.0, "action_by" : "buyer", "action_date" : ISODate("2021-03-12T06:20:51.000Z") }, { "action" : "counter", "offer_price" : 470000.0, "action_by" : "seller", "action_date" : ISODate("2021-03-12T06:22:18.000Z") },

How can I define action_date?

itvika avatar Mar 12 '21 11:03 itvika

+1 - no matter what I do, only created_at and inserted_at are saved as strings.

MeerKatDev avatar Apr 12 '21 16:04 MeerKatDev

I solved my problem creating a new model for the child object...

class ArticleReport extends Model
{
    protected $collection = 'articleReports';
    public function reports(){
        return $this->embedsMany(FlagReport::class);
    }    
}

class FlagReport extends Model {
    protected $primaryKey = null; //Remove id
    protected $dates = [
        "datetime"
    ];
}

Then, I can use it like this:

$report = new ArticleReport();

$flagReport = new FlagReport();
$flagReport->userId = $userId;
$flagReport->flag = $flag;
$flagReport->datetime = Carbon::now();

$report->reports()->associate($flagReport);

$report->save();

cacharrin avatar Jul 26 '21 18:07 cacharrin

It looks to me like $dates was replaced with $casts, and so I resolved the issue by replacing it with this in my model class: protected $casts = ['last_updated' => 'datetime', 'started' => 'datetime', 'finished' => 'datetime'];

avatarofhope2 avatar Mar 29 '23 18:03 avatarofhope2

As mentioned, $casts is the solution.

GromNaN avatar Aug 28 '23 15:08 GromNaN