Jezzta667's avatar

Converting Carbon instance to d/m/Y for form input (v4.2)

I am trying to add a date field to a form in Laravel 4.2. This field is saved as a property on the $companyBranch object which is then saved to a table in MySQL in the dateTime format.

$companyBranch->date_active

I have added:

protected $dates = ['date_active'];

to the model which is pulling the date from the database and converting to a Carbon object just fine. This is working perfectly in the view using:

{{ $companyBranch->date_active->format('d/m/Y')}}

However, in the create page, the $companyBranch is converted to an array to populate the form:

return View::make('company-branches.create', array(

    'companyBranch' => $companyBranch->toArray()

));

In the form in edit mode, the input (text) field is populated with the raw string from the database:

2012-11-30 00:00:00

This is because the $companyBranch->date_active value is converted to carbon and then converted back to a string when the $companyBranch is sent to the View using:

'companyBranch' => $companyBranch->toArray()

This is the code for the form and it is utilising Form::model:

<div class="form-group">
    {{ Form::label('date_active', 'Date Active', array('class' => 'col-sm-2 control-label')) }}
    <div class="col-sm-10">
        {{ Form::text( 'date_active', null, array('class' => 'form-control', 'placeholder' => 'DD/MM/YYYY')) }}
    </div>
</div>

I have tried for hours to figure this out but I can't get a clear answer. I have tried adding:

protected $dateFormat = 'd/m/Y';

to the model but I think I have figured out that this is for Laravel 5 only.

Can anyone please help me convert the carbon instance to a formatted string BEFORE it is sent to an array and then to the form?

I saw another post in this forum by someone trying to solve the same problem and at the close of the thread, he stated the following:

"The difference was that Form:model() calls getAttributeValue() while otherwise toArray() is called.

Anyway, I solved the problem overriding Carbon's default date format:"

Carbon\Carbon::setToStringFormat('Y.m.d');

If this is the solution, where exactly can I do this?

Additionally, Ideally I would be able to use a Form::date input field to input the date in a dd/mm/yyyy format which would then convert to a timestamp for storage in the database.

Would I just be better of forgetting about storing as a date type and just store it as text??

Thanks a lot and apologies for my newbness.

0 likes
19 replies
PovilasKorop's avatar

From your code it's unclear where $dateActive comes from, but it should be something like Carbon::create($old_date)->format('d/m/Y')

mstnorris's avatar

@Jezzta667

public function edit($companyId, $id)
    {
        $company = Company::findOrFail($companyId);
        $companyBranch = CompanyBranch::findOrFail($id);
        $breadcrumbs = self::makeBreadcrumb($company, $companyBranch);
        $breadcrumbs[] = array(
            'url'   => "",
            'title' => "Edit Branch"
        );
        
        return View::make('company-branches.create', array(
            'company'           => $company,
            'companyBranch'     => $companyBranch->toArray(),
            'breadcrumbs'       => $breadcrumbs,
            'companies'         => Company::getSelectArray(),
            'leaveLoadingTypes' => CompanyBranch::$leaveLoadingTypes,
            'date_active'       => $dateActive->format('d/m/Y'); // this right here
        ));
    }

Which dates do you want to format? I don't see it anywhere above?

Let's take date_active for example, as long as you've set it up correctly on your model, by adding the dates property like so:

protected $dates = ['date_active'];

Then you'll be able to do:

$dateActive->format('d/m/Y');
bobbybouwmann's avatar

Take a look at the Carbon documentation before you continue. You can for instance create and format dates the way you want $date = Carbon::createFromFormat('d/m/y', '03/11/2015'); // 2015-11-03 00:00:00 $date->format('Y-m-d'); // 2015-11-03

Documentation: http://carbon.nesbot.com/docs/

Jezzta667's avatar

Oh my goodness this place is amazing. I hadn't even finished editing my post and I've got 4 replies. I will continue to edit to get this up to speed with how it should look on this forum. Please see my updated post which I hope has all the relevant data. :)

mstnorris's avatar

@Jezzta667 if your field data type within the database is a timestamp then Carbon will be able to parse it with ease.

Can anyone please help me convert the carbon instance to a formatted string BEFORE it is sent to an array and then to the form?

$formattedDate = Carbon::createFromFormat('Y-m-d H:i:s', $active_date)->format('d/m/Y');

Also, as you're new here; firstly, welcome, and secondly, check out some Guidelines I put together to help you format your code, and questions to get a better conversation going.

Jezzta667's avatar

@mstnorris

Thank you for the suggestions. I have tried to update appropriately.

When I do your suggestion:

$formattedDate = Carbon::createFromFormat('Y-m-d H:i:s', $companyBranch->date_active)->format('d/m/Y');

in the controller I get this:

Symfony \ Component \ Debug \ Exception \ FatalErrorException (E_UNKNOWN)
HELP
syntax error, unexpected ';'
mstnorris's avatar

You have an extra ";" somewhere else in your code. What line and what file is it complaining about?

Are you using an IDE as this will help you catch syntax errors.

Jezzta667's avatar

@mstnorris I am just using Sublime Text and Homestead on Ubuntu. You were right. It is working now but how on Earth do I then apply that value to $companyBranch->date_active so it will then be sent to the form in that format?

If I then do something like this in the controller BEFORE the $companyBranch is sent to the view as an array:

$formattedDate = Carbon::createFromFormat('Y-m-d H:i:s', $companyBranch->date_active)->format('d/m/Y');
$companyBranch->date_active = $formattedDate;

I get

InvalidArgumentException

Unexpected data found. Unexpected data found. Data missing
mstnorris's avatar

That's because the date isn't in the format I showed above. The error is in this part here:

Carbon::createFromFormat('Y-m-d H:i:s', $companyBranch->date_active) // createFromFormat('Y-m-d H:i:s' ...

What you showed me above was "2012-11-30 00:00:00" which is equal to Y-m-d H:i:s, but if your $companyBranch->date_active is in a different format, then you'll need to adjust the formatting accordingly. See PHP Date for a list of options.

Can you show me what $companyBranch->date_active looks like

Jezzta667's avatar

@mstnorris

object(Carbon\Carbon)[375]
  public 'date' => string '2013-11-03 00:00:00.000000' (length=26)
  public 'timezone_type' => int 3
  public 'timezone' => string 'Australia/Sydney' (length=16)

Thanks so much for your help. I studied Laravel a few months ago but the backend of my app is a very small part of it so I've been focusing so much on the front end that my Laravel skills are very poor.

P.S Do you want me to keep tagging you?

mstnorris's avatar

Sure, you're welcome to :) No harm, I'll see it anyways even if you don't though.

2013-11-03 00:00:00.000000 // <-- it's this last bit you need to take care of
$formattedDate = Carbon::createFromFormat('Y-m-d H:i:s.u', $companyBranch->date_active)->format('d/m/Y'); // notice the ".u" at the end, which is the PHP microseconds

@Jezzta667 if it is a timestamp in your database then I don't believe you would have the microseconds. Please confirm whether you do or don't.

If you don't need it, and you do want it to be stored in the database as a timestamp, make sure you set your $table->timestamp('active_date'); in your table migration.

Jezzta667's avatar

@mstnorris My migration is as follows:

Schema::table('company_branches', function($table)
    {
        $table->dateTime('date_active')->nullable();
    });

This is the value: 2013-11-03 00:00:00

Would I be better off storing as a timestamp?

All I need is the d/m/Y date but figured it would be good practice to store as a proper date format in order to use Carbon etc. Would I be better off just storing as plain text. I would ideally like to use a date input for this field.

mstnorris's avatar
Level 55

@Jezzta667 why a DateTime? Do you need the microseconds?

All I need is the d/m/Y date but figured it would be good practice to store as a proper date format in order to use Carbon etc.

In that case definitely use a timestamp like I showed above, it will save you a lot of headaches.

Would I be better off just storing as plain text.

No. Use a timestamp.

Jezzta667's avatar

@mstnorris Thanks a lot for your help. Seems as though storing as a timestamp has made things easier.

However, I think that the main problem was the

protected $dates = ['date_active'];

line in the model was enforcing $companyBranch->date_active to not change to any other format.

I will now play around with grabbing the timestamp from the database, converting to Carbon so I can convert to d/m/Y to enter into the input field in the form and then converting back to a timestamp for storage in the database. A lot of work for something so simple... Oh well.

Thanks a lot for your time again.

mstnorris's avatar

The line protected $dates = ['date_active']; just means that it is automatically an instance of Carbon so do keep it in.

Then you don't have to do Carbon::createFromFormat... as it is already a Carbon instance.

Jezzta667's avatar

I finally got it working how I would like. I found it impossible to change the $companyBranch->date_active field to a string which could then be sent to the view when

return View::make('company-branches.create', array(
    'companyBranch' => $companyBranch->toArray(),
));

was called.

I ended up using a variable such as the following:

$dateActive = $companyBranch->date_active;
$formattedDate = Carbon::createFromFormat('Y-m-d H:i:s', $dateActive)->format('d/m/Y');

return View::make('company-branches.create', array(
    'companyBranch' => $companyBranch->toArray(),
    'dateActive' => $formattedDate
));

and then this in the form:

<div class="form-group">
    {{ Form::label('dateActive', 'Date Active', array('class' => 'col-sm-2 control-label')) }}
    <div class="col-sm-10">
        {{ Form::text('dateActive', $dateActive, array('class' => 'form-control', 'placeholder' => 'DD/MM/YYYY')) }}
    </div>
</div>

then in the store function I used:

$companyBranch->date_active = Carbon::createFromFormat('d/m/Y', Input::get('dateActive'));

with

protected $dates = ['date_active'];

public static $rules = array(
    'dateActive' => 'required|regex:/[0-9]{2}\/[0-9]{2}\/[0-9]{4}/ | date_format:"d/m/Y"',
);

in the model.

It took me a long time to figure out that to properly use and validate a dd/mm/yyyy date format, you need to use the above rule. Without the regex, a three digit year could be sent to the database which would then add all the zeros to the saved value. Why date_format:"d/m/Y" lets 3 digit years through, I can not fathom. Anyone who sees this who is trying to do this, also remember to add the regex BEFORE the date validation.

Thanks again @mstnorris

Please or to participate in this conversation.