Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

uxweb's avatar
Level 20

Handle default values in forms

Hi everyone, i'm crafting an application using laravel 5 where i have a registration form that has some optional fields and by default are empty.

When posting the form, these fields are passed to a Model to persist the data in the DB. The model's db table have default values for this fields when no value is passed.

But when i pass the form input data to the model it crashes because of the values coming from the form's optional fields.

I'm not sure if there is a way to know when an optional field has a value or not, and when no value is set a default value must be assigned, and when value is assigned that value must override the default passed to the model.

Right now i solved by setting a default value to each optional html field on the form, but if the user deletes the default value from an optional field and submits the form, it crashes.

Hope you can give some ideas to solve this

Thanks!

0 likes
12 replies
foxted's avatar

Can we see your migration? And/or the error message you're having? If you have a field with a default value in database, this shouldn't be a problem to pass the input data to the model even if the fields aren't there.

uxweb's avatar
Level 20

Sure @foxted, the table migration is this:

Schema::create('maquinaria.reportes_hora', function(Blueprint $table)
  {
            $table->increments('id');
            $table->integer('id_obra')->unsigned();
            $table->integer('id_almacen')->unsigned();
            $table->date('fecha');
            $table->decimal('horometro_inicial', 6, 1)->nullable();
            $table->decimal('horometro_final', 6, 1)->nullable();
            $table->integer('kilometraje_inicial')->nullable();
            $table->integer('kilometraje_final')->nullable();
            $table->text('observaciones')->nullable()->default('');
            $table->boolean('aprobado')->default(false);
            $table->boolean('autorizado')->default(false);
            $table->string('usuario', 16);
            $table->timestamps();

            $table->unique(['id_obra', 'id_almacen', 'fecha']);
            $table->foreign('id_obra')->references('id_obra')->on('obras');
            $table->foreign('id_almacen')->references('id_almacen')->on('almacenes');
  });

I forgot to mention that i'm using SQL Server and the command pattern for this, here is the code that creates the new Model using the input data:

CommandHandler

$reporteHoras = ReporteHoras::registro(
            $command->fecha,
            $command->horometro_inicial,
            $command->horometro_final,
            $command->kilometraje_inicial,
            $command->kilometraje_final,
            $command->observaciones
        );

Request Rules

public function rules()
 {
  return [
            'fecha' => 'required',
            'horometro_inicial' => 'numeric',
            'horometro_final' => 'numeric',
            'kilometraje_inicial' => 'integer',
            'kilometraje_final' => 'integer',
  ];
 }

Model

public static function registro($fecha, $horometroInicial, $horometroFinal, $kilometrajeInicial, $kilometrajeFinal, $observaciones)
    {
        $reporteHoras = new static([
            'fecha' => $fecha,
            'horometro_inicial' => $horometroInicial,
            'horometro_final' => $horometroFinal,
            'kilometraje_inicial' => $kilometrajeInicial,
            'kilometraje_final' => $kilometrajeFinal,
            'observaciones' => $observaciones,
        ]);

I still don't know why when it receives the optional fields empty, this is the error i see:

Illuminate \ Database \ QueryException (HY000) SQLSTATE[HY000]: General error: 8114 General SQL Server error: Check messages from the SQL Server [8114] (severity 16) [(null)] (SQL: insert into [maquinaria].[reportes_hora] ([fecha], [horometro_inicial], [horometro_final], [kilometraje_inicial], [kilometraje_final], [observaciones], [id_obra], [id_almacen], [usuario], [updated_at], [created_at]) values (2014-01-02, 1, , , , , 1, 18, ubueno, 2014-09-24 13:37:30.000, 2014-09-24 13:37:30.000))

I can see that it is just setting anything (,,,,) for the values of that optional fields, any ideas?

Thanks!

uxweb's avatar
Level 20

@foxted, right now i have to check if the values coming from the form through the command are empty, if they are i set a default value:

$reporteHoras = ReporteHoras::registro(
            $command->fecha,
            empty($command->horometro_inicial) ? null : $command->horometro_inicial,
            empty($command->horometro_final) ? null : $command->horometro_final,
            empty($command->kilometraje_inicial) ? null : $command->kilometraje_inicial,
            empty($command->kilometraje_final) ? null : $command->kilometraje_final,
            empty($command->observaciones) ? null :$command->observaciones
);

I don't like how this looks, is there a better way to solve it?

Thanks

thepsion5's avatar

Why not do that in the command's constructor? It seems like a reasonable place for it.

1 like
uxweb's avatar
Level 20

@thepsion5, model doesn't do this by default?, if not, i think this is validation related to the model (model validation), doing the validation within the model would be right?

thepsion5's avatar

@uxweb The model just translates its values to the requisite database values.

i think this is validation related to the model (model validation), doing the validation within the model would be right?

Unless the model has different behavior for an empty string vs. null, then it shouldn't care, really.

That being said, do you know the empty strings are actually causing the SQL error? It looks like the quotes are stripped from the error message.

uxweb's avatar
Level 20

@thepsion5 Yeah, i've noticed about the quotes not beign showed in the error page, but i don't know if that is an issue with PDO or something like that. Internally they are beign passed to the db engine.

Another idea i have is that the Model is passing an empty string to the table fields that are of type decimal and integer, that will cause the next error "Error converting data type varchar to numeric", i just copied and pasted the query into the db engine.

But i really don't know how to solve this, would this be a bug in Laravel??

Before saving the model in the CommandHandler i ddied the Command object to inspect the values it contains and this was the result:

object(GhiSao\Maquinaria\RegistroReporteHorasCommand)[272]
object(GhiSao\Maquinaria\RegistroReporteHorasCommand)[272]
  public 'idAlmacen' => string '4094' (length=4)
  public 'fecha' => string '2014-01-12' (length=10)
  public 'horometro_inicial' => string '12' (length=2)
  public 'horometro_final' => string '' (length=0)
  public 'kilometraje_inicial' => string '' (length=0)
  public 'kilometraje_final' => string '' (length=0)
  public 'observaciones' => string '' (length=0)

All the values are of type string!

I noticed that if i explicitly cast the values to the same type used in the database table in the Command's constructor body everything works right, that way i don't have to use the empty validation done in the CommandHandler.

Command

public function __construct($idAlmacen, $fecha, $horometro_inicial, $horometro_final, $kilometraje_inicial, $kilometraje_final, $observaciones, $usuario )
    {
        $this->idAlmacen = $idAlmacen;
        $this->fecha = $fecha;
        $this->horometro_inicial = (float) $horometro_inicial;
        $this->horometro_final = (float) $horometro_final;
        $this->kilometraje_inicial = (int) $kilometraje_inicial;
        $this->kilometraje_final = (int) $kilometraje_final;
        $this->observaciones = (string) $observaciones;
        $this->usuario = $usuario ;
    }

And this is why empty strings are not passed anymore to the table fields which are decimal and integer, explicitly casting those values to float and integer makes them 0 or 0.0 and the error is not thrown anymore.

After the change, ddied the Command again and this was the result:

object(GhiSao\Maquinaria\RegistroReporteHorasCommand)[272]
  public 'idAlmacen' => string '4094' (length=4)
  public 'fecha' => string '2014-01-12' (length=10)
  public 'horometro_inicial' => float 12
  public 'horometro_final' => float 0
  public 'kilometraje_inicial' => int 0
  public 'kilometraje_final' => int 0
  public 'observaciones' => string '' (length=0)

So, i'm not pretty sure of what is going on here :s

Thanks for all your help!

thepsion5's avatar

Do you know the specific error message the database is giving you? The error you posted just says "Check messages from the SQL Server", which makes me think there's a separate function call or query you need to make to find out what exactly is preventing the query from working.

uxweb's avatar
Level 20

@thepsion5, yep, the error is: "Error converting data type varchar to numeric", which i think is because laravel sends an empty string value to the columns that are of type int or decimal, those columns are the optional ones which are not filled in the html form.

zot24's avatar

so what's the conclusion on this? I'm having a similar issue with Postgres trying to convert the empty strings "" to integer, what will do the best thing to do?. Cheers

jekinney's avatar

@zot24 Have to set the type before saving. In your case

 $this->empty_string = (int) $empty_string;

This insures you have a integer type going into your database, with an empty string PHP can't figure out what type it is. Many languages (Java, C#, VB) you must always declare the type no matter what, and of course PHP you don't HAVE to. But I argue for important data you should just to be sure.

1 like
JarekTkaczyk's avatar

@zot24 The easy way for getting rid of empty values is:

// this one will remove all the falsey values like '', 0, false, empty array etc
$input = array_filter($input);

// this one is explicit about empty string
$input = array_filter($input, function ($value) {
  return $value !== '';
});

You can adjust it for Commands or whatever way you are using.

2 likes

Please or to participate in this conversation.