El API de CakePHP: FormHelper::input

No hay mejor manera aprender a usar un framework como CakePHP que ver el código fuente.En esta oportunidad revisaré la función input del FormHelper.

De una discusión del grupo CakePHP-esp me ha surgido la idea para este post (y dependiendo de la audiencia, podría convertirlo en una serie).

CakePHP 1.2 presenta, en su helper Form, una función muy poderosa para crear los campos de un formulario.

function input($fieldName, $options = array())

El primer parámetro de esta función debe ser el nombre del campo de la tabla que deseamos solicitar al usuario. Por ejemplo:

Teniendo una tabla person con un campo name VARCHAR(140) NOT NULL

echo $form->input("name");

Generará un campo input de tipo texto cuya longitud máxima es 140 y será requerido.

Ahora bién, toda ese conocimiento lo saca Cake de la base de datos. Sin embargo, la función ofrece al desarrollador un el segundo parámetro con el cual modificar el resultado. El parámetro $options, el cual debe ser un arreglo asociativo (los índices son strings):

  • type – permite modificar el tipo de campo a crear, los valores para este índice pueden ser: checkbox, radio, text, password, file, select, time, date, datetime y textarea
    • Si no se indica, CakePHP trata de adivinarlo a partir de la definición del campo en la base de datos.
    • Si no se indica y el nombre del campo es psword, passwd, o password, type será password.
    • Si en el controlador se hace una llamada a Controller::set con una variable cuyo nombre sea el plural del campo, cake utilizará type=’select’ (se puede forzar a que sea ‘radio’).
      Por ejemplo:

      //Controlador:
      $this->set("names", array("nombre", "nombre 1"));
      // Vista:
      echo $form->input("name");
      echo $form->input("name", array("type" => "radio"));
  • options – arreglo de pares para popular campos de seleccion (select, checkbox y radio). Si este campo se indica pero type no, entonces será ’select’. El ejemplo anterior, se puede hacer sin modificar el controlador, de la siguiente manera:
    // Vista:
    echo $form->input("name",
        array(
            "type" => "select", // también sirve "radio"
            "options" => array("nombre", "nombre1")
        )
    );
  • maxlength – este campo permite limitar el número de caracteres que puede insertar el usuario en el campo (por supuesto, sólo es válido si type es ‘input’).
  • timeFormat – permite definir el formato en el que se introducirá el tiempo (campos de tipo ‘time’ o ‘datetime’ sólamente).
    • Los valores posibles son 24, 12 o NONE
  • dateFormat – permite definir el formato en el que se introducirán las fechas (campos de tipo ‘datetime’ y ‘date’ sólamente)
    • Los valores posbiles DMY, MDY, YMD o NONE
  • selected – opción (el valor, no el texto visible) pre-seleccionada (sólo en campos de tipo ’select’).
    • Los campos de tipo ‘date’, ‘datetime’ y ‘time’ también aceptan este índice. El valor debe expresarse en formato estandar de fechas: ‘Y-m-d’, ‘Y-m-d H:M:S’ o ‘H:M:S’
    • Para fechas y tiempos, selected puede ser un arreglo asociativo. Los índices válidos son: day, month, year, hours, minutes, seconds y meridian (am o pm)
  • multiple – sólo para campos select. Indica si es un select mútiple o no (true, false).
    • Si el select es múltiple, selected puede ser un arreglo con varias entradas para cada valor seleccionado)
  • empty – sólo para campos select. Indica si el select tendrá un primer valor vacío.
  • label – permite al desarrollador seleccionar el texto que identifica al campo.
    • El valor de este índice también puede ser un arreglo asociativo cuyos índices pueden ser: text y otros atributos html propios del tag label (for, class, id, style, etc).
  • div - permite definir las características del div que rodea al input y al label.
    • Si se indica false, cake no crea el div.
    • Si se indica un string, se selecciona como valor del atributo class (en lugar de type que se usa normalmente).
    • Si es un un arreglo asociativo, se admiten los siguientes índices:
      • class -  sustituye en el atributo class el valor por defecto (type).
      • tag – nombre del tag a usar en lugar de div (p, span, etc…)
      • otros atributos html para el div.
  • id – atributo id del input. Cake cambia automáticamente el atributo for del label.
    • Utilizar algo distinto a un string es malo para la accesibilidad ya que hace que el atributo for del label falle.
  • before – texto que aparecerá antes del label
  • between – texto que aparecerá después del label.
  • after – texto que aparecerá después del input.

Esas son todas los parámetros que pude detectar luego de ver por un ráto el tan temido API de CakePHP. Si encuentras que algún  dato es incorrecto notificamelo en los comentarios.

Si te pareció interesante esta entrada y te gustaría que haga una serie, deja un comentario también indicando qué funciones te parecen interesantes.

Recibe otros artículos como este automáticamente
Suscríbete vía RSS a aikon.com.ve || ¿Qué es RSS?

Twitea este artículo y sígueme en twitter @joaquin_win

Tags: , ,

Comentarios

» 57 Personas han comentado sobre “El API de CakePHP: FormHelper::input”

  1. Carlos:

    Puedes poner un ejemplo con select?
    Por ejemplo, una opción de select con datos estaticos.. (“activo”, “inactivo”)

    gracias de antemano

  2. Joaquín Windmüller:

    Hola Carlos,

    Pensé que con el ejemplo en la sección *type* estaba claro. De todos modos he agregado el ejemplo que pides.

    Saludos

  3. cristo:

    Muy bueno tu aporte. Te pregunto: se puede modificar el nombre del archivo ahi mismo. como?
    Necesito hacer un sitio donde se pueda subir fotos, estoy usando el upload behaviour, y cuanto hay dos fotos que se llaman igual no me las sube. Entonces si le puedo modificar el nombre antes de que actue el behaviour…
    Muchas gracias.. espero haber sido claro.

  4. Joaquín Windmüller:

    Cristo,

    Lo que preguntas no se puede lograr con el FormHelper, probablemente debas hacerlo a nivel del modelo: tal vez modificando los datos (y los archivos) en beforeSave.

    Saludos

  5. Paco:

    Hola Joaquín,

    En relación con la interesante descripción que has dado quisiera plantear la siguiente cuestión:

    Tenemos 2 tablas:
    ‘notas’ (id, titulo, texto, tema_id) que contiene descripciones que me interesan: y
    ‘temas’ (id, tema) que contiene la clasificación de los textos que inserto en ‘notas’: recetas de cocina, electrónica, mecánica, etc.

    Por lo tanto, tema_id en ‘notas’ es foreign key procedente de id en ‘temas’.

    En los formularios de creación y edición de ‘notas’, por cada nota se pide: título de la nota (titulo), texto de la nota (texto) y tema (tema_id).

    Para facilitarle la vida al usuario, al insertar el tema de la nota, queremos mostrarle un desplegable que visualice los temas: recetas de cocina, electrónica, mecánica, etc., le permita seleccionar uno y guarde en la tabla una fila pero con la foreign key numérica que tenemos en ‘temas’.

    Es decir visualizamos la lista de temas pero lo que guardamos es la id del tema.

    La descripción que has dado me sugiere que en CakePHP habría que utilizar un ’select’, pero ¿cómo se le indica a CakePHP que visualice la lista de temas y lo que guarde sea el id del tema?.

    Este asunto parece esencial para evitar tener que recordar id asociados a temas.

    Gracias por adelantado.

  6. Joaquín Windmüller:

    En el controlador debes hacer
    $this->set('temas', $this->Nota->Tema->find('list'));

    Esto va a hacer disponible en la vista la variable $temas que tiene la lista de temas en el formato adecuado para que al guardar se guarde el id en el campo ‘tema_id’.

    Saludos

  7. Cómo llenar las listas de selección en CakePHP:

    [...] poco les hablé sobre FormHelper::input de CakePHP y en los comentarios recibí la pregunta de cómo lograr rellenar con valores de la base de datos [...]

  8. paco:

    Gracias por tu respuesta. Efectivamente, el ejemplo sobre ‘notas’ y ‘temas’ ha funcionado.

    He acabado usando Bake, que produce el form directamente. Es asombroso el ahorro de tiempo de codificación ‘a mano’.

  9. Joaquín Windmüller:

    Hola Paco,

    Me alegra que haya te funcionado. Y genial que utilices bake, te ahorra mucho tiempo en código que no es necesario escribir y escribir! Terminas con un codigo PHP más uniforme y manejable.

    Te agradezco también por inspirar una entrada al respecto de cómo llenar las listas de selección en CakePHP.

    Saludos

  10. felipe fernandez:

    Hablando de bake, ¿alguien conoce alguna herramienta como el bake pero gráfica?

  11. Joaquín Windmüller:

    Felipe, si usas mac: http://www.widgetpress.com/modelbaker

  12. yoxs:

    Hola.Esta muy buena la información pero
    tengo una consulta tengo el siguiente form,
    input(‘RedeemItem.description’,array(‘type’=>’textarea’,’size’ => ‘100′,’maxlength’=>225));?>

    pero no cumple la condición del maximo de texto, que puedo hacer? Gracias

  13. Joaquín Windmüller:

    Hola yoxs,

    Los textarea no tienen un atributo que pueda determinar la maxima longitud del texto (es una limitacion de HTML, no de CakePHP). La opcion basica es usar una regla de validacion para que cake notifique al usuario del la limitacion. La otra opcion – adicional – es usar javascript, por ejemplo: http://www.shiningstar.net/articles/articles/javascript/dynamictextareacounter.asp

  14. yoxs:

    ok si ya le implemente javascript que habia encontrado antes, es que pense que si existia la opcion, pero muchas gracias.Estare consultando por aca si no hay problema.

  15. Joaquín Windmüller:

    No hay problema, bienvenido! :)

  16. yoxs:

    Es más estoy buscando manipular el objeto select, como se le asignan el array de atributos, es que necesito uno que muestre numeros de 1 a 20 es para seleccionar cantidad de productos, y luego el numero elegido pase a otra vista.Imagino que podars ayudarme y de ante mano te lo agradesco.

  17. yoxs:

    jejej seria bievenida

  18. Joaquín Windmüller:

    Entonces me corrijo: bienvenida! jajaja

    En el segundo parametro de la funcion puedes pasar el parametro ‘options’ => array(1,2,…,20) y eso deberia generar el select con 20 opciones.

    tambien sirve: ‘options’ => range(1,20)

  19. yoxs:

    muchas gracias, ya lo estaba haciendo de manera muy tediosa jeje.
    Una consulta más, tengo un bonton que me lleva a otra vista y necesito que lleve el id de un articulo, cuando hacia una lista de links solo bastaba con mandarlo asi :

    link($re['RedeemItem']['title'],’/admin/redeem_items/view_redeem/’.$re['RedeemItem']['id']); ?>

    Pero ahora es un boton el que me lleva a esa vista y necesito que lleve el id de ese producto en especifico. No se si me entiendes.

  20. Joaquín Windmüller:

    Tienes 2 opciones:

    1) Cambiar el url al que apunta el form:
    http://api.cakephp.org/class/form-helper#method-FormHelpercreate

    En este caso la accion recibiria el valor como un parametro de la funcion.

    2) Agregar un campo hidden
    input(‘id’, array(‘type’ => ‘hidden’, ‘value’ => $id))

    En este caso el valor viene en $this->data

  21. yoxs:

    sip, ya tenia eso. lo que hice fue ponerlo aqui.y funciono sin embargo gracias.

    $form->create(‘RedeemItem’, array(‘action’=>’redeem_confirm/’.$item['RedeemItem']['id']))?>

    Muy buena pagina me habia costado encontrar una. je

  22. yoxs:

    hola nose si viene al caso, es que necesito un consejo sobre el metodo round()

    pues tengo valores que aveces vienen 3.00 por ejemplo, y quiero que muestre los ceros pero, apesar de que lo pongo asi:

    cuando trae ceros no los coloca. Si los decimales son difrentes de cero no hay problema.

  23. yoxs:

    asi lo pongo.

    round($total,2)

  24. Joaquín Windmüller:

    Revisa esto: http://www.phpreferencebook.com/tag/sprintf/

  25. yoxs:

    gracias use numeric_format().

  26. Zully:

    Hola tengo una duda… yo tengo maquetado el diseño de un formulario pero cada input tiene una clase definida… por ejemplo

    Intento que al usar cakePHP salga lo mismo en los formularios pero no lo he conseguido… puedes ayudarme con eso? te lo agradeceré mucho..
    Saludos

  27. Joaquín Windmüller:

    Hola Zully, no puedes postear html en los comentarios… disculpa esa.

    En el segundo parámetro ($opsitons) puedes usar:

    ‘div’ => array(‘class’ => ‘miclase’)

    Saludos

  28. yoxs:

    Hola de nuevo. Disculpa la molestia me gustaria un consejo de como hacer un objeto(calendario) que simplemente me de la fecha en un campo de texto para poder generar una busqueda de un historial. Lo estaba intentando con un codigo en javascript pero se me complico, si me pudieran dar algun consejillo. Gracias

  29. yoxs:

    Ya lo solucione,,,,de todos modos gracias.

  30. yoxs:

    tengo el siguiente error.

    Fatal error: Call to a member function numbers() on a non-object in C:\wamp\www\gold-pay\app\views\elements\transaction_history.thtml on line 8

    y sucede al mover la linea que crea un form.es extraño

  31. Joaquín Windmüller:

    Que tienes en la linea 8 de transaction_history.thtml?

    Por cierto, deberias empezar a usar CakePHP 1.2 :)

  32. yoxs:

    echo $paginator->numbers();

  33. Joaquín Windmüller:

    $paginator es null o lo sobreescribiste con algo…

    Puede ser que no has llamado $this->paginate en el controlador

  34. yoxs:

    algo como esto?

    $data = $this->paginate(‘Transaction’);
    $this->set(compact(‘data’));

    ya lo habia puesto es que lo extraño es que en esa vista nose usa, lamenos eso creo

  35. Joaquín Windmüller:

    Pega tu codigo del la accion aca (y cualquier cosa que creas importante): http://bin.cakephp.org/

  36. yoxs:

    listo

  37. Joaquín Windmüller:

    cual es el url que genero?

  38. yoxs:

    oooooo….creo que ya

  39. yoxs:

    $totals = $this->find( ‘all’, array(
    ‘conditions’ => array(
    ‘OR’ => array(‘Transaction.user_id ‘ => 1, ‘transaction_type_id ‘ => 12),
    ‘Transaction.status ‘ => ‘cancel’

    ),
    ‘fields’ => array(‘Transaction.transaction_type_id’,'TransactionType.name’, ‘SUM(Transaction.amount) as total’),
    ‘group’ => ‘Transaction.transaction_type_id’

    ));

    TENGO ESTA CONDICION ANTERIOR EN EL MODELO, COMO AGREGARIAS ESTA OTRA PARTE DE LA CONDICION,

    ES QUE NO PUEDO CON EL array_push().

    array(‘Transaction.date BETWEEN ? AND ?’ => array($dateMin,$dateMax)

    gracias

  40. Joaquín Windmüller:

    Hola Yoxs,

    Creo que en cake (1.2) lo indicas

    array(‘Transaction.date BETWEEN’ => array($dateMin, $dateMax)

    Nunca he usado el operador BETWEEN en cake, pero debe seguir el mismo estilo que el resto de los operadores en cake

  41. yoxs:

    sip es que no da error , epro parece no estar haciendo la consulta….mmmm voy a buscar entonces }
    gracias

  42. yoxs:

    sabes como poner en read-only, un form es que ‘disable’ no funciona pero al refrescar pierde la información.

    gracias y perdona las molestias

  43. Joaquín Windmüller:

    usa ‘readonly’ => true

  44. yoxs:

    muy amable, gracias :-)

  45. yoxs:

    se puede tener varios forms que se dijiran ala mismo metodo en el controlador pero que tengan diferentes botones y dos de esos forms contengan campos hidden. Sin importar que estos tengan el mismo nombre.

  46. Joaquín Windmüller:

    No puedes tener campos con el mismo nombre. Y si, puedes tener varios forms con la misma accion: solo que debes tener una manera de detectar las diferencias para hacer cosas distintas con cada uno (un campo hidden, o un parametro adicional en la accion – en cuyo caso ya no seria la misma accion)

  47. yoxs:

    mmmm sip, mejor lo hice con javascript…., enviandole los parametros por medio de un metodo.

    Por cierto sabes de algun metodo en javascript para generar la fecha, es que con la clase date hay que hacer varias condiciones para obtener la deseada.

  48. yoxs:

    ya las puse,,,,,gracias

  49. yoxs:

    hola, espero no molestar de causalidad sabes como puedo preguntar en una consulta en cakephp con el metodo find , si un campo es igual a nulo.:)

  50. yoxs:

    yap,,,

  51. Joaquín Windmüller:

    Hola Yoxs,

    Disculpa que no pude atenderte hoy, estuve todo el día offline. Te agradezco tu atención :) Debería hacer un chat sólo para ti :P

    Sería bueno que dejes las soluciones a tus dudas cuando las encuentres, así todos aprendemos.

  52. yoxs:

    jjeje es que me da verguenza:) porque son muy simples mis preguntas, y pues las respuestas pues imagino son fáciles por eso no pongo las soluciones,,,

    Por eso volvi jejej espero no moleste hoy,,, es uqe necesito poner el metodo onchange en el select pero es que no se en que array debo hacerlo.
    mmmm

  53. yoxs:

    ah estaria genial lodel chat jejej

  54. yoxs:

    creo que es es el tercer array verdad?

  55. yoxs:

    yap,,,,si ese era, para llamar un metodo de javascript y cambie el estado de otro combo.
    array(“onchange”=>”getIndex()”)

  56. Nicolas:

    Hola, quisiera preguntar en el caso de que yo tenga en mi form tenga una lista o un select de seleccion multiple y quiera guardar los seleccionados en una tabla como lo haria?…
    por ejemplo tengo una relacion N:N entre rubros y subrubros… donde obviamente un rubro puede tener muchos subrubros y un subrubro puede pertenecer a mas de un rubro… yo quiero tener para un rubro (en un formulario) una lista de seleccion multiple que me muestre todos los subrubros disponibles y asi podes serleccionar los subrubros que componen a ese rubro… es decir… para un rubro de la tabla rubro mostrar una lista con todos los subrubros y guardar los seleccionados en RxS (donde RxS es la tabla para la relacion muchos a muchos) como lo deberia hacer? alguna idea?

    espero que se haya entendido

    Atte

    Nicolas

  57. alfredo:

    estupendo el artículo, gracias por ayudar a la comunidad.

Deja tu respuesta

requerido

requerido

Nota: mantente dentro del tema y se respetuoso.