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

Problemas + duda

Estas en el tema de Problemas + duda en el foro de Symfony en Foros del Web. Hola mi nombre es Sandra, soy nueva en el foro y les comento que no me gusta preguntar mucho ya que creo que: "el que ...
  #1 (permalink)  
Antiguo 25/02/2012, 17:38
 
Fecha de Ingreso: febrero-2012
Mensajes: 10
Antigüedad: 12 años, 2 meses
Puntos: 0
Problemas + duda

Hola mi nombre es Sandra, soy nueva en el foro y les comento que no me gusta preguntar mucho ya que creo que: "el que busca encuentra", pero esta vez busque y lo que encontré no me gusto o no me funciono, por eso este post

Lo que no pude realizar:
Subir múltiples archivos con un formulario, he podido subir un archivo con symfony 2 pero he buscado y probado de mil maneras para poder subir múltiples archivos con un formulario, es decir que el usuario pueda subir la cantidad de archivos que el desee.

Lo que he realizado lo hice siguiendo el tutorial how to handle file uploads with doctrine. Pero lo he intentado extender para subir múltiples archivos con el formulario pero sin éxito.

Mi pregunta es alguien a podido subir múltiples archivos con symfony 2. ¿Algún tutorial o ayuda que me puedan dar?


Duda:
En mi aplicación tengo un controlado Administrador y me gustaría mediante anotaciones poder restringir el acceso a todo el controlador mediante el ROLE del usuario, he encontrado como restringir el acceso por metodo pero en mi caso no tiene sentido ya que seria para cada metodo del controlador la misma anotacion, por eso busco la manera de asegurar el controlador directamente.

Cualquier ayuda sera agradecida.

Saludos!!
  #2 (permalink)  
Antiguo 25/02/2012, 18:12
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: Problemas + duda

Que tal Sandra,

Antes que nada bienvenida a FdW, ahora a por las preguntas :P, deberías postear el código para ver como lo estas trabajando, hay varias formas de resolverlo, personalmente utilizo el bundle SonataMediaBundle talves te sirva.

Con respecto a como asegurar el controlador entero, lo mas sencillo es hacerlo por la url http://symfony.com/doc/2.0/book/secu...c-url-patterns otra opción podría ser a atraves del sistema de eventos http://symfony.com/doc/2.0/book/internals.html#events.

Saludos.
__________________
http://es.phptherightway.com/
thats us riders :)
  #3 (permalink)  
Antiguo 25/02/2012, 18:33
 
Fecha de Ingreso: febrero-2012
Mensajes: 10
Antigüedad: 12 años, 2 meses
Puntos: 0
Respuesta: Problemas + duda

Muchas gracias masterpuppet tanto por la bienvenida y por la rápida respuesta, te comento que he mirado mirado la documentacion de SonataMediaBundle y parece muy interesante, mañana intentare usarla y te comento como me fue.
En cuando el tema de restringir el ingreseo te comento que lo hago como dice el primer link mediante el archivo security.yml, pero me gustaría hacerlo mediante anotaciones es por eso que planteo mi duda.

Muchas gracias masterpuppet!!!

Saludos.
  #4 (permalink)  
Antiguo 25/02/2012, 19:18
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: Problemas + duda

Mmmmm, mirando por arriba el bundle JMSSecurityExtraBundle, tanto en los annotations como en el listener siempre trabaja a nivel de método , no creo que puedas hacerlo a nivel de clase, esta mas bien dirigido a control granular, te sugiero que leas la doc del bundle, hay alguna razón en especial para hacerlo con annotations ?

Saludos.
__________________
http://es.phptherightway.com/
thats us riders :)
  #5 (permalink)  
Antiguo 25/02/2012, 19:57
 
Fecha de Ingreso: febrero-2012
Mensajes: 10
Antigüedad: 12 años, 2 meses
Puntos: 0
Respuesta: Problemas + duda

Me estas dejando mucha tarea!! jajajaa pero me encanta!! muchas gracias de nuevo!!, era simple curiosidad. Te comento que le he dado un vistazo rapido a JMSSecurityExtraBundle y vi muchas cosas interesantes en la documentacion que no conocia que se podian hacer.
Tambien he estado viendo SonataMediaBundle y no lo logro entender, no entiendo como usarlo, es decir con que relacion tendria que hacer el @OneToMany, supongamos por decir algo tonto que un Post tiene muchos Archivos, es decir una relacion Uno a Muchos yo tengo la entidad post, pero como la relaciono con los archivos a subir??

Muchas gracias Masterpuppet ya no se como agradecerte.

Saludos!!
  #6 (permalink)  
Antiguo 26/02/2012, 09:20
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: Problemas + duda

Luego de instalar todas las dependencias (que son unas cuantas), extender y registrar el bundle tienes que relacionar tus entidades con Sonata\MediaBundle\Entity\Media o Sonata\MediaBundle\Entity\Gallery.

De todas formas te dejo un ejemplo de como podria ser desde cero, va en dos posts porque es medio largo :P, utilizo tu escenario de un post con imagenes, un post va a tener titulo contenido e imagenes, cada imagen va a tener el nombre original de la imagen, fecha de creación y el nombre luego de subir el fichero, la relacion es OneToMany - Bidirectonal, podría ser algo así:

Entities - Post
Código PHP:
Ver original
  1. namespace Acme\DemoBundle\Entity;
  2.  
  3. use Doctrine\ORM\Mapping as ORM;
  4. use Doctrine\Common\Collections\ArrayCollection;
  5.  
  6. /**
  7.  * Acme\DemoBundle\Entity\Post
  8.  *
  9.  * @ORM\Table(name="post__post")
  10.  * @ORM\Entity
  11.  */
  12. class Post
  13. {
  14.     /**
  15.      * @ORM\Id
  16.      * @ORM\Column(type="integer")
  17.      * @ORM\GeneratedValue(strategy="AUTO")
  18.      */
  19.     protected $id;
  20.  
  21.     /**
  22.      * @var string $title
  23.      *
  24.      * @ORM\Column(name="title", type="string", length=255)
  25.      */
  26.     protected $title;
  27.  
  28.     /**
  29.      * @var string $content
  30.      *
  31.      * @ORM\Column(name="content", type="text")
  32.      */
  33.     protected $content;
  34.  
  35.     /**
  36.      * @var ArrayCollection $images
  37.      *
  38.      * @ORM\OneToMany(targetEntity="Acme\DemoBundle\Entity\PostImage", mappedBy="post", cascade={"all"})
  39.      */
  40.     protected $images;
  41.  
  42.     /**
  43.      * Post constructor
  44.      */
  45.     public function __construct()
  46.     {
  47.         $this->images = new ArrayCollection();
  48.     }
  49.  
  50.     /**
  51.      * Get id
  52.      *
  53.      * @return integer
  54.      */
  55.     public function getId()
  56.     {
  57.         return $this->id;
  58.     }
  59.  
  60.     /**
  61.      * Set title
  62.      *
  63.      * @param string $title
  64.      */
  65.     public function setTitle($title)
  66.     {
  67.         $this->title = $title;
  68.     }
  69.  
  70.     /**
  71.      * Get title
  72.      *
  73.      * @return string
  74.      */
  75.     public function getTitle()
  76.     {
  77.         return $this->title;
  78.     }
  79.  
  80.     /**
  81.      * Set content
  82.      *
  83.      * @param text $content
  84.      */
  85.     public function setContent($content)
  86.     {
  87.         $this->content = $content;
  88.     }
  89.  
  90.     /**
  91.      * Get content
  92.      *
  93.      * @return text
  94.      */
  95.     public function getContent()
  96.     {
  97.         return $this->content;
  98.     }
  99.  
  100.     /**
  101.      * Set images
  102.      *
  103.      * @param array $images
  104.      */
  105.     public function setImages($images)
  106.     {
  107.         foreach($images as $image){
  108.             $image->setPost($this);
  109.         }
  110.         $this->images = $images;
  111.     }
  112.  
  113.     /**
  114.      * Add image
  115.      *
  116.      * @param PostImage $image
  117.      */    
  118.     public function addImage($image)
  119.     {
  120.         $image->setPost($this);
  121.         $this->images[] = $image;
  122.     }
  123.  
  124.     /**
  125.      * Get images
  126.      *
  127.      * @return array
  128.      */
  129.     public function getImages()
  130.     {
  131.         return $this->images;
  132.     }
  133.  
  134. }

Entities - PostImage
Código PHP:
Ver original
  1. namespace Acme\DemoBundle\Entity;
  2.  
  3. use Doctrine\ORM\Mapping as ORM;
  4.  
  5. /**
  6.  * Acme\DemoBundle\Entity\PostImage
  7.  *
  8.  * @ORM\Table(name="post__image")
  9.  * @ORM\Entity
  10.  * @ORM\HasLifecycleCallbacks
  11.  */
  12. class PostImage
  13. {
  14.     /**
  15.      * @ORM\Id
  16.      * @ORM\Column(type="integer")
  17.      * @ORM\GeneratedValue(strategy="AUTO")
  18.      */
  19.     protected $id;
  20.  
  21.  
  22.     /**
  23.      * @var string $name
  24.      *
  25.      * @ORM\Column(name="name", type="string", length=255)
  26.      */
  27.     protected $name;
  28.  
  29.     /**
  30.      * @var string $path
  31.      *
  32.      * @ORM\Column(name="path", type="string", length=255)
  33.      */
  34.     protected $path;
  35.    
  36.     /**
  37.      * @var Acme\DemoBundle\Entity\Post $post
  38.      *
  39.      * @ORM\ManyToOne(targetEntity="Acme\DemoBundle\Entity\Post", inversedBy="images")
  40.      */
  41.     protected $post;
  42.  
  43.     /**
  44.      * @var DateTime $createdAt
  45.      *
  46.      * @ORM\Column(name="created_at", type="datetime")
  47.      */
  48.     protected $createdAt;
  49.  
  50.     /**
  51.      * @var Symfony\Component\HttpFoundation\File\UploadedFile $file
  52.      */    
  53.     public $file;
  54.  
  55.     /**
  56.      * Get id
  57.      *
  58.      * @return integer
  59.      */
  60.     public function getId()
  61.     {
  62.         return $this->id;
  63.     }
  64.  
  65.     /**
  66.      * Set name
  67.      *
  68.      * @param string $name
  69.      */
  70.     public function setName($name)
  71.     {
  72.         $this->name = $name;
  73.     }
  74.  
  75.     /**
  76.      * Get name
  77.      *
  78.      * @return string
  79.      */
  80.     public function getName()
  81.     {
  82.         return $this->name;
  83.     }
  84.  
  85.     /**
  86.      * Set path
  87.      *
  88.      * @param string $path
  89.      */
  90.     public function setPath($path)
  91.     {
  92.         $this->path = $path;
  93.     }
  94.  
  95.     /**
  96.      * Get path
  97.      *
  98.  
  99.      * @return string
  100.      */
  101.     public function getPath()
  102.     {
  103.         return $this->path;
  104.     }
  105.    
  106.     /**
  107.      * Set post
  108.      *
  109.      * @param Acme\DemoBundle\Entity\Post $post    
  110.      */
  111.     public function setPost($post)
  112.     {
  113.         $this->post = $post;
  114.     }
  115.  
  116.     /**
  117.      * Get post
  118.      *
  119.      * @return Acme\DemoBundle\Entity\Post
  120.      */
  121.     public function getPost()
  122.     {
  123.         return $this->post;
  124.     }
  125.  
  126.     /**
  127.      * Set createdAt
  128.      *
  129.      * @param DateTime $createdAt    
  130.      */
  131.     public function setCreatedAt(\DateTime $createdAt)
  132.     {
  133.         $this->createdAt = $createdAt;
  134.     }
  135.  
  136.     /**
  137.      * Get createdAt
  138.      *
  139.      * @return DateTime
  140.      */
  141.     public function getCreatedAt()
  142.     {
  143.         return $this->createdAt;
  144.     }    
  145.  
  146.      /**
  147.      * @ORM\PrePersist()    
  148.      */
  149.     public function prePersist()
  150.     {
  151.         $this->createdAt = new \DateTime();
  152.     }
  153.  
  154.      /**
  155.      * @ORM\PrePersist()
  156.      * @ORM\PreUpdate()
  157.      */
  158.     public function preUpload()
  159.     {        
  160.         if (null !== $this->file) {
  161.             $this->name = $this->file->getClientOriginalName();
  162.             // do whatever you want to generate a unique name
  163.             $this->path = uniqid().'.'.$this->file->guessExtension();
  164.         }
  165.     }
  166.  
  167.     /**
  168.      * @ORM\PostPersist()
  169.      * @ORM\PostUpdate()
  170.      */
  171.     public function upload()
  172.     {
  173.         if (null === $this->file) {
  174.             return;
  175.         }
  176.  
  177.         // if there is an error when moving the file, an exception will
  178.         // be automatically thrown by move(). This will properly prevent
  179.         // the entity from being persisted to the database on error
  180.         $this->file->move($this->getUploadRootDir(), $this->path);
  181.  
  182.         unset($this->file);
  183.     }
  184.  
  185.     /**
  186.      * @ORM\PostRemove()
  187.      */
  188.     public function removeUpload()
  189.     {
  190.         if ($file = $this->getAbsolutePath()) {
  191.             unlink($file);
  192.         }
  193.     }
  194.  
  195.     /**
  196.      * @return mixed null|string
  197.      */
  198.     public function getAbsolutePath()
  199.     {
  200.         return null === $this->path ?: $this->getUploadRootDir() . '/' . $this->path;
  201.     }
  202.  
  203.     /**
  204.      * @return mixed null|string
  205.      */
  206.     public function getWebPath()
  207.     {
  208.         return null === $this->path ?: $this->getUploadDir() . '/' . $this->path;
  209.     }
  210.  
  211.     /**
  212.      * @return string
  213.      */
  214.     protected function getUploadRootDir()
  215.     {
  216.         // the absolute directory path where uploaded documents should be saved
  217.         return __DIR__ . '/../../../../web/' . $this->getUploadDir();
  218.     }
  219.  
  220.     /**
  221.      * @return string
  222.      */
  223.     protected function getUploadDir()
  224.     {
  225.         // get rid of the __DIR__ so it doesn't screw when displaying uploaded doc/image in the view.
  226.         return 'uploads';
  227.     }    
  228. }

Ahora los formularios para las entidades:

Forms - Post
Código PHP:
Ver original
  1. namespace Acme\DemoBundle\Form;
  2.  
  3. use Symfony\Component\Form\AbstractType;
  4. use Symfony\Component\Form\FormBuilder;
  5.  
  6. class PostType extends AbstractType
  7. {
  8.     public function buildForm(FormBuilder $builder, array $options)
  9.     {
  10.         $builder
  11.             ->add('title')
  12.             ->add('content')
  13.             ->add('images', 'collection', array(                
  14.                 'type' => new PostImageType(),
  15.                 'allow_add' => true,
  16.                 'allow_delete' => true,
  17.                 'by_reference' => false,
  18.             ))
  19.         ;        
  20.     }
  21.  
  22.     public function getName()
  23.     {
  24.         return 'acme_demobundle_posttype';
  25.     }
  26.    
  27.     public function getDefaultOptions(array $options)
  28.     {
  29.         return array('data_class' => 'Acme\DemoBundle\Entity\Post');
  30.     }
  31.    
  32. }

Forms - PostImage
Código PHP:
Ver original
  1. namespace Acme\DemoBundle\Form;
  2.  
  3. use Symfony\Component\Form\AbstractType;
  4. use Symfony\Component\Form\FormBuilder;
  5.  
  6. class PostImageType extends AbstractType
  7. {
  8.     public function buildForm(FormBuilder $builder, array $options)
  9.     {
  10.         $builder->add('file', 'file');        
  11.     }
  12.  
  13.     public function getName()
  14.     {
  15.         return 'acme_demobundle_postimagetype';
  16.     }
  17.    
  18.     public function getDefaultOptions(array $options)
  19.     {
  20.         return array('data_class' => 'Acme\DemoBundle\Entity\PostImage');
  21.     }
  22.    
  23. }

to be continued...
__________________
http://es.phptherightway.com/
thats us riders :)

Última edición por masterpuppet; 27/02/2012 a las 04:28
  #7 (permalink)  
Antiguo 26/02/2012, 09:25
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: Problemas + duda

Luego el controller

Código PHP:
Ver original
  1. class WelcomeController extends Controller
  2. {
  3.     /**
  4.      * @Route("/", name="home")
  5.      * @Template()
  6.      */
  7.     public function indexAction()
  8.     {
  9.         $post  = new Post();       
  10.         $request = $this->getRequest();
  11.         $form    = $this->createForm(new PostType(), $post);       
  12.  
  13.         if('POST' == $request->getMethod()){
  14.             $form->bindRequest($request);
  15.             if ($form->isValid()) {                    
  16.                 $em = $this->getDoctrine()->getEntityManager();
  17.                 $em->persist($post);
  18.                 $em->flush();
  19.                 $this->get('session')->setFlash('notice', 'Post created successfully!');
  20.                 return $this->redirect($this->generateUrl('home'));            
  21.             }            
  22.         }
  23.         return array('form' => $form->createView());
  24.     }
  25. }

La presentación del form

Código twig:
Ver original
  1. {% extends 'AcmeDemoBundle::layout.html.twig' %}
  2.  
  3. {% block content %}
  4.     <form action="" method="post" {{ form_enctype(form) }}>        
  5.         {{ form_widget(form) }}        
  6.         <input type="submit" />
  7.     </form>
  8.  
  9.     <ul class="record_actions">
  10.         <li>
  11.             <a href="#" class="jslink">
  12.                 Add a Image
  13.             </a>
  14.         </li>
  15.     </ul>
  16. {% endblock %}

y por último unos bits de js

Código Javascript:
Ver original
  1. google.load("jquery", "1.7.1");            
  2. google.setOnLoadCallback(function(){
  3.     (function($){
  4.         function add() {
  5.             var collectionHolder = $('#acme_demobundle_posttype_images');
  6.             var prototype = collectionHolder.attr('data-prototype');
  7.             form = prototype.replace(/\$\$name\$\$/g, collectionHolder.children().length);
  8.             form =  $(form).filter('div').first().html($(form).html() +'<a class="delete_link" href="#">remove</a>');
  9.             collectionHolder.append(form);
  10.         }
  11.        
  12.         $('a.jslink').click(function(event){
  13.             event.preventDefault();
  14.             add();
  15.         });
  16.        
  17.         $(document).on('click', 'a.delete_link',function(event){
  18.             $(event.currentTarget).parent().remove();
  19.         });
  20.     })(jQuery);
  21. });

Como te podrás dar cuenta el drawback de todo esto es la dependencia en js, igual creo que la idea se entiende y espero que te sirva al menos de base.

Saludos.
__________________
http://es.phptherightway.com/
thats us riders :)

Última edición por masterpuppet; 27/02/2012 a las 05:26 Razón: Typos
  #8 (permalink)  
Antiguo 26/02/2012, 13:05
 
Fecha de Ingreso: febrero-2012
Mensajes: 10
Antigüedad: 12 años, 2 meses
Puntos: 0
Respuesta: Problemas + duda

Muchas gracias masterpuppet!!!, no se como agradecerte te comento que intente instalar SonataMediaBundle y siempre me tiraba un error al intentar ejecutar

Código:
php app/console sonata:easy-extends:generate SonataMediaBundle
no encontraba

Código:
// AWS SDK needs a special autoloader
require_once __DIR__.'/../vendor/aws-sdk/sdk.class.php';
Por lo tanto cuando llegue a mi casa intentare la solución desde cero, asi voy aprendiendo mas sobre symfony.

Muchas gracias de verdad y espero no tener que molestar mas.

Saludos.

Sandra.
  #9 (permalink)  
Antiguo 26/02/2012, 15:30
 
Fecha de Ingreso: febrero-2012
Mensajes: 10
Antigüedad: 12 años, 2 meses
Puntos: 0
Respuesta: Problemas + duda

Hola te comento que me ha funcionado la parte de guardar las imagenes, pero no se porque cuando doy al click remove, no realiza nada, tambien te comento como no entendi tu codigo realize lo siguiente:

Código:
             jQuery(document).ready(function($) {
                    
                    $('a.jsAdd').click(function(event){
                            var collectionHolder = $('#acme_demobundle_posttype_files');
                            var prototype = collectionHolder.attr('data-prototype');
                            form = prototype.replace(/\$\$name\$\$/g, collectionHolder.children().length);
                            form =  $(form).filter('div').first().html($(form).html() +'<a href="#" class="jsDelete">remove</a>');
                            collectionHolder.append(form);
                            event.preventDefault();
                        });


                    $('a.jsDelete').click(function(event){    
                        alert("Donde estas");
                        //$(event.currentTarget).parent().remove();
                        //event.preventDefault();
                    });

                });
Lo mas raro de todo es que cuando inspecciono con Firebug me encuentra el link creado es decir <a href="#" class="jsDelete">remove</a> lo cual es obvio por que se ve en la pantalla, pero cuando hago botón derecho y ver codigo fuente de la pagina no me aparece nunca el link a remove mirado el codigo nunca lo encuentro y fijate que quise realizar un simple alert con el evento click y no me muestra el alert, es muy raro!!!

Muchas gracias de nuevo.

Saludos.

Sandra
  #10 (permalink)  
Antiguo 26/02/2012, 16:01
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: Problemas + duda

Que tal Sandra,

Que parte no te quedo clara ?, el js ?, para el ejemplo utilice el google loader, pero si tienes la librería en local como lo tienes ahora esta bien y el error es algo normal, ten en cuenta que como lo tienes estas asignando el evento click a un elemento que al ejecutarse el ready no existe, por esa razón el ejemplo es con on(event delegation), si bien no es el mejor ejemplo(el evento debería estar "atado" al padre mas cercano, el form y no al document...), te debería funcionar correctamente con on, si estas con alguna version de jQuery inferior a 1.7 utililza live o delegate

PD: con respecto al post anterior, el AWS SDK para tu caso no es necesario instalarlo.

Saludos.
__________________
http://es.phptherightway.com/
thats us riders :)
  #11 (permalink)  
Antiguo 26/02/2012, 16:46
 
Fecha de Ingreso: febrero-2012
Mensajes: 10
Antigüedad: 12 años, 2 meses
Puntos: 0
Respuesta: Problemas + duda

Muchas gracias de nuevo, lo que intentado durante todo la semana tu lo realizaste en un rato!!!, espero llegar a tu nivel algun dia.

Muchas gracias de verdad me ha quedado perfecto.... perdon te quedo perfecto jajaja, gracias de verdad!!

Lo que no entendia era google.load("jquery", "1.7.1"); y google.setOnLoadCallback() pero ya he leido la documentacion.

Saludos.

Sandra
  #12 (permalink)  
Antiguo 26/02/2012, 17:03
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: Problemas + duda

Np, la idea es darnos una mano entre todos, ten en cuenta un detalle que se me paso, inicializar la collecion en el constructor, ya esta corregido el post correspondiente.

Saludos.
__________________
http://es.phptherightway.com/
thats us riders :)

Etiquetas: 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 10:37.