Sergio Benavides
Sergio Benavides
Laravel
Comparte:

Debo usar un loop while ? si es asi cómo puedo usarlo?

Hola a todos, tengo un formulario en el cual tengo un select con el plugin select2 y tengo la opción de tags: true, en este select envió nombre-valor-descripción(opcional), y el formato seria por ejemplo: john doe-15000 jane doe-12500-descripción opcional.
para que el usuario envié el formato correcto cree una regla de validación:
Input del formulario:
<div class="form-group col-md-6 {{ $errors->has('pagos') ? 'has-error' : '' }}">
    <label for="pagos">Pago / valor pago <i class="fa fa-info-circle" data-toggle="tooltip" data-placement="right" title="Ej: andres-50000 luis-78500"></i></label>
    <select class="form-control select2-pagos" multiple="multiple" name="pagos[]" data-placeholder="Dele un nombre al pago y su valor, separelos por '-'" style="width: 100%;">
      @if(is_array(old('pagos')))
        @foreach (old('pagos') as $pago)
            <option value="{{ $pago }}" selected="selected">{{ $pago }}</option>
        @endforeach
      @endif
    </select>
    @if ($errors->has('pagos'))
    <label class="control-label" for="pagos"><i class="fa fa-times-circle-o"></i>
      <strong>{{ $errors->first('pagos') }}</strong>
    </label>
    @endif
  </div>

Request
public function rules()
    {
        return [
            'cuadre_venta' => 'required|integer|min:0',
            'cuadre_base' => 'required|integer|min:0',
            'cuadre_propina' => 'required|integer|min:0',

            'pagos' => ['required', new ValidFormatPagos],
            'datafonos' => 'required',
        ];
    }
Regla 
public function passes($attribute, $values)
    {
      foreach ($values as $key => $value) {
        $pagoSeparados = explode('-',$value);
        // dd($values);
        if (count($pagoSeparados) == 2) {
          if (is_string($pagoSeparados[0]) && ctype_digit($pagoSeparados[1])) {
            return true;
          }
        }elseif (count($pagoSeparados) > 2) {
          if (is_string($pagoSeparados[0]) && ctype_digit($pagoSeparados[1]) && is_string($pagoSeparados[2]) != true) {
            return true;
          }
        }
      }
      return false;
    }

    /**
     * Get the validation error message.
     *
     * @return string
     */
    public function message()
    {
        return 'El formato para los pagos es incorrecto.';
    }
Primero recorro los valores que envian desde el form con un foreach
y los divido por el caracter "-" (0 => "John doe", 1 => "15000") entonces pregunto si el arreglo es igual a 2 es que viene nombre y valor, el nombre siempre sera en la pos 0 y el valor en la pos 1, entonces pregunto si el valor en la pos 0 es string y el valor en la pos 1 es  un int, si estas dos condiciones son verdaderas retorno true. hasta aquí todo va bien, si en el select envio ([john doe-15000] [Jane doe]) la validacion pasa ya que en la primera condición es verdadera pero la segunda no, cómo puedo hacer que evalue todos los tags y no solo el primero, lo siento si no fui claro en alguna parte puedes preguntarme y gracias de antemano a los que me puedan ayudar
Jorge García
Jorge García (2780 xp)
Hola Sergio, al parecer estás retornando true anticipadamente, por eso al validar esta parte [john doe-15000] [Jane doe] como el primer valor es correcto la validación pasa, y no llega a verificar el segundo valor que está incorrecto.
La verificación debería ir a la inversa de modo que devuelvas falso dentro de los 'if' y al final devuelvas verdadero una vez que todos los valores han sido verificados.
En este caso en particular creo que una solución más sencilla sería utilizando expresiones regulares, pero cuéntame si lo pudiste solucionar.

1
Sergio Benavides
Sergio Benavides (1352 xp)
aun no lo he resuelto, lo que quiero es una solución sencilla, cómo sería con expresiones regulares ? otra pregunta que me surge, si quisiera validar que el primer parámetro (nombre del pago) no fuera solo string, si no que tambien no fuera mayor a 50 tambien debería hacer esta lógica aquí ?
Jorge García
Jorge García (2780 xp)
Intenta con esto:
$isValid = false;

foreach ($string as $key => $value) {
    $pagoSeparados = explode('-',$value);
    if (count($pagoSeparados) == 2) {
        if (is_string($pagoSeparados[0]) && ctype_digit($pagoSeparados[1])) {
            $isValid = true;
        }
    }elseif (count($pagoSeparados) > 2) {
        if (is_string($pagoSeparados[0]) && ctype_digit($pagoSeparados[1]) && is_string($pagoSeparados[2]) != true) {
            $isValid = true;
        }
    } else {
        $isValid = false;
    }
}

return $isValid;
1
Sergio Benavides
Sergio Benavides (1352 xp)
asi me funciona perfecto, muchas gracias. Otra pregunta que me surge, si quisiera validar que el primer parámetro (nombre del pago) no fuera solo string, si no que también no fuera mayor a 50 también debería hacer esta lógica aquí ?
Jorge García
Jorge García (2780 xp)
Claro, tiene sentido hacerla aquí mismo
1