Foros del Web » Programando para Internet » PHP » Symfony »

Problema con Formulario tipo "collection"

Estas en el tema de Problema con Formulario tipo "collection" en el foro de Symfony en Foros del Web. Hola Amigos! Estoy peleándome con el componente form de Symfony2 (utilizo Silex) y tras bastante Googlear y probar muchas cosas, he decidido exponer aquí mi ...
  #1 (permalink)  
Antiguo 05/07/2013, 02:16
 
Fecha de Ingreso: febrero-2010
Mensajes: 36
Antigüedad: 14 años, 2 meses
Puntos: 0
Pregunta Problema con Formulario tipo "collection"

Hola Amigos!

Estoy peleándome con el componente form de Symfony2 (utilizo Silex) y tras bastante Googlear y probar muchas cosas, he decidido exponer aquí mi problema, por si alguien me pudiera iluminar.

Estoy programando una web de compras, y a la hora de mostrar el carrito necesito que a cada item se le asocie un formulario en el que el cliente pueda modificar la cantidad del item comprado y eliminarlo también.

Si lo hago con php a pelo no hay problema, es un problema bastante fácil, pero con el componente de Symfony no sé que debo hacer, en principio pienso que es un formulario de tipo Collection, ya que cada uno de los items necesita su widget.

La clase que hice es la siguiente:

Código PHP:

class Quantity extends AbstractType{

    public 
$cart;
    public 
$id = array();
    public 
$cantidad = array();


    function 
__construct($cart)
    {

    
$this->cart $cart;

   foreach (
$this->cart as $id => $cantidad) {

    
$this->id[] = $id;
    
$this->cantidad[] = $cantidad;

    }

    }

    public function 
buildForm(FormBuilderInterface $builder, array $options){

        
$builder->add('id''collection', array(
            
'type'   => 'hidden''options' => array(
             
'attr' => array('value' => (string)$this->id),
        )));

                
$builder->add('quantity''collection', array(
            
'type'   => 'integer''options' => array(
             
'attr' => array('value' => (int)$this->cantidad),
        )));

                        
$builder->add('delete''collection', array(
            
'type'   => 'integer''options' => array(
             
'attr' => array('value' => 0),
        )));
     }


    public function 
getName(){
        return 
"quantityform";
    }


Como veis le paso en el constructor un array que es el carrito, recuperado de la sesión, con los items y la cantidad de cada item, para poder pintarlos correctamente en la plantilla.

En el controlador tengo esto:

Código PHP:

        $cart 
$app['session']->get('cart');

        
$quantityForm $app['form.factory']->create(new Quantity($cart)); 
Y en la plantilla twig tengo lo siguiente:

Código PHP:


{% for producto in cesta.productos %}

{{ 
form_widget(quantityForm.id) }}
{{ 
form_widget(quantityForm.quantity) }}
{{ 
form_widget(quantityForm.delete) }}
{{ 
form_rest(quantityForm) }}

{% endfor %} 
Desgraciadamente solo se muestra el primer item, los demás ya no aparecen. Si alguien tiene alguna idea se lo agradecería enormemente. Un saludo!

Última edición por Fennesz; 05/07/2013 a las 02:24
  #2 (permalink)  
Antiguo 05/07/2013, 06:39
Avatar de masterpuppet
Software Craftsman
 
Fecha de Ingreso: enero-2008
Ubicación: Montevideo, Uruguay
Mensajes: 3.550
Antigüedad: 16 años, 3 meses
Puntos: 845
Respuesta: Problema con Formulario tipo "collection"

Se supone que tienes dos entidades, que representarían al carrito y a un item del carrito, supongamos que son Cart y CartItem(cada Cart tiene una coleccion de CartItem) y por cada una de estas entidades tienes un FormType, supongamos también que son CartType y CartItemType, el primero tendría el collection de CartItemType que a su ves tendría las cantidades, a grandes rasgos seria algo así:

Código PHP:
Ver original
  1. //CartType
  2. ...
  3. $builder->add('items', 'collection', new CartItemType())
  4. ...
Código PHP:
Ver original
  1. //CartItemType
  2. ...
  3. ->add('quantity', 'integer', array('attr' => array('min' => 1)))
  4. ...


Saludos.
__________________
http://es.phptherightway.com/
thats us riders :)
  #3 (permalink)  
Antiguo 05/07/2013, 07:47
 
Fecha de Ingreso: febrero-2010
Mensajes: 36
Antigüedad: 14 años, 2 meses
Puntos: 0
Respuesta: Problema con Formulario tipo "collection"

Hey, gracias por la respuesta masterpuppet. Esa fase ya la he superado, aunque no lo hice como tu me sugieres. Lo dejé como estaba pero cree una clase Entity Cart, con propiedades id, quantity y delete (el nombre de los forms) y funciona perfecto.

Lo que ahora no logro obtener es pasarle unos datos para que pinte las cantidades, e ids del cart.

Lo hice pásandole en el constructor el cart en forma de array, todo perfecto, pero o me muestra "Array" en el value, o si hago un foreach me muestra solo el último valor. Alguna idea de como pasar datos al builder?

Tengo esto, (las dos posibilidades. No funciona ni con el bucle en el constructor, ni con él en el builder). Alguien tiene una idea?

Gracias

Código PHP:

namespace srcForm
;

use 
SymfonyComponentValidatorConstraints as Assert;
use 
SymfonyComponentFormAbstractType;
use 
SymfonyComponentFormFormBuilderInterface;

class 
Quantity extends AbstractType{

    public 
$cart;
    public 
$id = array();
    public 
$cantidad = array();


    function 
__construct($cart)
    {

    
$this->cart $cart;

   foreach (
$this->cart as $id => $cantidad) {

    
$this->id[] = $id;
    
$this->cantidad[] = $cantidad;

    }

    }

    public function 
buildForm(FormBuilderInterface $builder, array $options){




   foreach (
$this->id as $id) {

        
$builder->add('id''collection', array(
            
'type'   => 'hidden''options' => array(
             
'attr' => array('value' => (string)$id),
        )));
    }
        
$builder->add('quantity''collection', array(
            
'type'   => 'integer''options' => array(
             
'attr' => array('value' => (int)$this->cantidad),
        )));

        
$builder->add('delete''collection', array(
            
'type'   => 'integer''options' => array(
             
'attr' => array('value' => 0),
        )));



     }


    public function 
getName(){
        return 
"quantityform";
    }


  #4 (permalink)  
Antiguo 05/07/2013, 10:00
Avatar de masterpuppet
Software Craftsman
 
Fecha de Ingreso: enero-2008
Ubicación: Montevideo, Uruguay
Mensajes: 3.550
Antigüedad: 16 años, 3 meses
Puntos: 845
Respuesta: Problema con Formulario tipo "collection"

Que tal Fennesz,

El tema es que el planteo no es correcto, si te apegas a los estandares del fw todo es mas sencillo te sugiero que lo hagas de la forma correcta y tengas dos entidades con dos form types, de todas formas tal cual lo tienes estas pisando en cada iteración los elementos, debería bastar con algo asi :

Código PHP:
Ver original
  1. protected $cart;
  2.  
  3. public function __construct($cart)
  4. {
  5.     $this->cart = $cart;
  6. }
  7.  
  8. public function buildForm(FormBuilderInterface $builder, array $options)
  9. {
  10.     $builder->add('id', 'collection', array(
  11.          'type'  => 'hidden',
  12.          'data'  => array_keys($this->cart)
  13.     ));
  14.     ...
  15. }


Código TWIG:
Ver original
  1. {{ form(form) }}

Saludos.
__________________
http://es.phptherightway.com/
thats us riders :)
  #5 (permalink)  
Antiguo 08/07/2013, 03:43
 
Fecha de Ingreso: febrero-2010
Mensajes: 36
Antigüedad: 14 años, 2 meses
Puntos: 0
Respuesta: Problema con Formulario tipo "collection"

Pues llevas razón, si quiero seguir los fundamentos del framework, debo respetarlo todo, aunque la verdad, es que no acabo de comprender el componente de formularios. Veo que tu controlas bastante, así que voy a abusar de tu conocimiento XD. Espero que dios te lo pague con una novia muy guapa XD

Supongo que debo crear dos entidades, una CartEntity y otra CartItemEntity, pero si te digo la verdad no sé como relacionarlas, esto en Symfony, con Doctrine, si se hacerlo fácilmente.

Las entidades serían así:

Código PHP:

class CartEntity
{
    protected 
$cart;

    protected 
$items;

    public function 
getCart()
    {
        return 
$this->cart;
    }
    public function 
setCart($cart)
    {
        
$this->cart $cart;
    }

    public function 
getItems()
    {
        return 
$this->items;
    }

    public function 
setItems($items)
    {
        
$this->items $items;
    }



Código PHP:

class CartItemsEntity
{

    protected 
$id;

    protected 
$quantity;


    public function 
getId()
    {
        return 
$this->id;
    }

    public function 
setId($id)
    {
        
$this->id $id;
    }

    public function 
getQuantity()
    {
        return 
$this->quantity;
    }

    public function 
setQuantity($quantity)
    {
        
$this->quantity $quantity;
    }


Los formularios quedarían así:

Código PHP:

namespace srcForm
;

use 
SymfonyComponentValidatorConstraints as Assert;
use 
SymfonyComponentFormAbstractType;
use 
SymfonyComponentFormFormBuilderInterface;
use 
srcFormCartItemType;

class 
CartType extends AbstractType{

    public 
$cart;

    function 
__construct($cart)
    {

    
$this->cart $cart;

    }

    public function 
buildForm(FormBuilderInterface $builder, array $options){

        
$builder->add('items''collection', array( 'type'   => new CartItemType($this->cart),));

     }

    public function 
getName(){
        return 
"cartform";
    }



Código PHP:

namespace srcForm
;

use 
SymfonyComponentValidatorConstraints as Assert;
use 
SymfonyComponentFormAbstractType;
use 
SymfonyComponentFormFormBuilderInterface;

class 
CartItemType extends AbstractType{

    public 
$cart;
    public 
$id;
    public 
$cantidad;


    function 
__construct($cart)
    {

    
$this->cart $cart;

   foreach (
$this->cart as $id => $cantidad) {

    
$this->id[] = $id;
    
$this->cantidad[] = $cantidad;

    }

    }

    public function 
buildForm(FormBuilderInterface $builder, array $options){

        
$builder->add('id''hidden', array(
             
'attr' => array('value' => array_keys($this->id)),
        ));

        
$builder->add('quantity''integer', array(
             
'attr' => array('value' => array_keys($this->cantidad)),
        ));

     }


    public function 
getName(){
        return 
"cartitemform";
    }


En el controlador le paso a la entity el carrito en una sesión, y luego a su vez al form.

Código PHP:

$cart 
$app['session']->get('cart');
$cart_entity = new CartEntity();
$cart_entity->setCart($cart);

$form $app['form.factory']->create(new CartType($cart), $cart_entity); 

Código PHP:

 
{{ form_widget(form) }} 
Pero no obtengo nada, como no llego a entenderlo del todo, no sé en que estoy fallando. Si alguien puede ayudarme le estaré muy agradecido. Gracias


Cita:
Iniciado por masterpuppet Ver Mensaje
Que tal Fennesz,

El tema es que el planteo no es correcto, si te apegas a los estandares del fw todo es mas sencillo te sugiero que lo hagas de la forma correcta y tengas dos entidades con dos form types, de todas formas tal cual lo tienes estas pisando en cada iteración los elementos, debería bastar con algo asi :

Código PHP:
Ver original
  1. protected $cart;
  2.  
  3. public function __construct($cart)
  4. {
  5.     $this->cart = $cart;
  6. }
  7.  
  8. public function buildForm(FormBuilderInterface $builder, array $options)
  9. {
  10.     $builder->add('id', 'collection', array(
  11.          'type'  => 'hidden',
  12.          'data'  => array_keys($this->cart)
  13.     ));
  14.     ...
  15. }


Código TWIG:
Ver original
  1. {{ form(form) }}

Saludos.

Última edición por Fennesz; 08/07/2013 a las 03:51
  #6 (permalink)  
Antiguo 08/07/2013, 06:17
Avatar de masterpuppet
Software Craftsman
 
Fecha de Ingreso: enero-2008
Ubicación: Montevideo, Uruguay
Mensajes: 3.550
Antigüedad: 16 años, 3 meses
Puntos: 845
Respuesta: Problema con Formulario tipo "collection"

Aquí tienes un ejemplo https://github.com/Sylius/SyliusCartBundle, de hecho puedes utilizar directamente el bundle ;)
__________________
http://es.phptherightway.com/
thats us riders :)
  #7 (permalink)  
Antiguo 09/07/2013, 02:55
 
Fecha de Ingreso: febrero-2010
Mensajes: 36
Antigüedad: 14 años, 2 meses
Puntos: 0
Respuesta: Problema con Formulario tipo "collection"

Te lo agradezco pero la verdad es que no aclara mi duda. He estado "buceando" bastante últimamente por github, viendo ejemplos de formularios, de como hacen las relaciones, y de como pasan valores por defecto y aún tengo más dudas que antes XD.

En algunos casos veo que a la hora de crear el formulario le pasan el segundo parámetro (es un parámetro de entidad?) y en otras ocasiones no. También he visto que para pasarle un valor al formulario algunos lo hacen a través del constructor, y otros a través del segundo parçametro, el que se supone que es la entidad.

Luego tampoco me queda claro como relacionar dos entidades, me refiero a Silex sin ORM, en el caso de un formulario de tipo colecction, que tiene dos formularios y cada uno su entidad relacionada. En fin, en la documentación siempre vienen ejemplos, que son de agradecer, pero que suelen mostrar los casos más sencillos, y a la hora de enfrentarte a problemas de la "vida real" la cosa se complica. Es lo malo de esta clase de fw, algo tan sencillo como un form, que en php plano es un problema de 5 minutos, se convierte en un dolor de cabeza. En todo caso, muchas gracias a los que ayudan!


Cita:
Iniciado por masterpuppet Ver Mensaje
Aquí tienes un ejemplo [url]https://github.com/Sylius/SyliusCartBundle[/url], de hecho puedes utilizar directamente el bundle ;)

Etiquetas: formularios, symfony2
Atención: Estás leyendo un tema que no tiene actividad desde hace más de 6 MESES, te recomendamos abrir un Nuevo tema en lugar de responder al actual.
Respuesta




La zona horaria es GMT -6. Ahora son las 05:23.