Guardar objeto en sesion de PHP

1,427 views
Skip to first unread message

Asier Ramos

unread,
Mar 23, 2012, 7:43:59 AM3/23/12
to symfo...@googlegroups.com
Buenas

Estoy haciendo un carrito de la compra en PHP y de momento es muy basico. Tiene de momento una clase de pedidos que contiene el usuario que lo ha comprado y el articulo que ha comprado,lo rellena y lo guarda en la base de datos. Hasta aqui correcto, el problema lo tengo cuando quiero que el usuario sea anonimo(aun no he buscado la forma de hacer un IsAuthenticated o algo asi y de momento lo igualo a anon., que es chapuza pero para probarlo me vale)...
Hay tengo el problema, distingo si esta conectado o no y si no esta conectado quiero guardar el objeto en la sesion de PHP(mas tarde querria guardar un array de pedidos que no se aun como se hara...) para mas tarde a la hora de comprar le salga para registrarse antes de comprar.

El codigo es el siguiente:

 public function addAction()
    {
        if ($_GET) {
            $NumeroElementos = $_GET["NumeroElementos"];
            $PidArticulo = $_GET["Articulo"];
        }
        $em = $this->get('doctrine.orm.entity_manager');
        $pedidos = new \Eros\CartBundle\Entity\UsrPedidos();
        $articulo = new \Eros\FrontendBundle\Entity\ProArticulo();
        $user= $this->get('security.context')->getToken()->getUser();
       
        $request = $this->get('request');

        if($user!="anon."){
            $pedidos->setSidarticulo($em->getRepository('Eros\FrontendBundle\Entity\ProArticulo')->find($PidArticulo));
            $pedidos->setNumeroarticulos($NumeroElementos);
            $pedidos->setDateadd(new \DateTime("now"));
            $pedidos->setPrecio(4);
            $pedidos->setSiduser($user);
            $em->persist($pedidos);
            $em->flush();
        }else{
            $pedidos->setSidarticulo($em->getRepository('Eros\FrontendBundle\Entity\ProArticulo')->find($PidArticulo));
            $pedidos->setNumeroarticulos($NumeroElementos);
            $pedidos->setDateadd(new \DateTime("now"));
            $pedidos->setPrecio(4);
 
            $session = $this->getRequest()->getSession();
            $session->set('pedidos', $pedidos);
        }

        $response = new Response(json_encode(array('status'=>'OK','items'=>$items)));
        $response->headers->set('Content-Type', 'application/json');
        return $response;
    }

Muchas gracias!!

Absalón Valdés Ormeño

unread,
Mar 23, 2012, 10:46:01 AM3/23/12
to symfo...@googlegroups.com
hola:

1.- si usas un framework que demoró más de 1 año y medio en quedar listo y tiene cientos de personas trabajando en él... por qué no usarlo bien? OJO con eso que haces ahí con el $_GET y luego obteniendo los parametros directamente de la superglobal. es una falla de seguridad tremenda. si quieres verificar si la consulta se hace por el metodo GET entonces usa $request->getMethod() == 'GET'. ahora que lo veo mejor, si $_GET no está definida (es posible eso?) saltará la asignacion de las variables, y lanzará un error cuando las uses en los métodos de más abajo, ya que serán 'indefinidas'. lo que puedes hacer tambien es restringir el metodo usado para llegar al controlador configurando el requerimiento en la ruta con:

requirements:
    _method: GET

y asi no tendras que hacer esa comprobación. si las 2 variables necesariamente deben estar en el request, entonces deberías configurarlas en las ruta, pasarlas como parametros al controlador y asi no tendrás que hacer ese grotesco hack del if ($_GET) { .... } y estarás siguiendo la filosofía del framework.

2.- $this->get('request') cambialo por $this->getRequest(). es lo mismo, pero ya que el controller base la trae, usala. lo mismo con $this->get('doctrine.orm.entity_manager'), puedes hacer lo mismo con $this->getDoctrine()->getEntityManager();

3.- si quieres guardar un objeto en sesion, debes serializarlo/deserializarlo correctamente, de lo contrario al obtenerlo de vuelta se produciran errores. por ejemplo, si tienes algun campo privado o si el estado del objeto depende del contexto en el que se creo. para serializar correctamente debes implementar la interface http://php.net/manual/es/class.serializable.php

sin embargo, parece que es una mala práctica guardar objetos en sesion, por los mismos problemas que ya te mencioné. en ese caso, mejor guardas un array serializado con el ID de la entidad y otros parámetros adicionales.

4.- si estas usando "anon." para discriminar entre un usuario logeado y uno anónimo, te recomiendo mejor usar los roles ROLE_USER y IS_AUTHENTICATED_ANONYMOUSLY verificandolos con $this->get('security.context')->isGranted(/* ROLE */) y ya que repites 4 lineas de codigo al crear el objeto $pedidos, mejor las separas a un metodo diferente para que no se haga ese enredo que tienes ahi. 

5.- no olvides agregar control de errores al buscar un objeto en la DB. esto por ejemplo:

  $pedidos->setSidarticulo($em->getRepository('Eros\FrontendBundle\Entity\ProArticulo')->find($PidArticulo));

si el articulo no es encontrado no tienes espacio para devolver un error correctamente, y en setSidarticulo terminarás pasando un valor null, y quedará asi. ahora, si en la definicion de ese campo agregaste nullable=true tendrás un desorden d.p.m. en la BD (quedando varios pedidos SIN ARTICULO DEFINIDO!), y si no es nullable, te lanzará una fea excepcion PDOException diciendo que NULL no es permitido.

6.- declaras la variable $articulo y creas un objeto para ella, pero en ningun momento la usas ya que estas obteniendo el articulo directamente a través del metodo find del repository. Si haces lo del punto 5 ahi te servirá más y no ocupará espacio innecesariamente. Tambien, al final devuelves un json de un array donde pones 'items' => $items, pero en ninguna parte defines de donde sacas esos $items. lo más probable es que lance una excepcion.

Eso seria todo por ahora. no resolví del todo tu pregunta pero no me podía quedar sin guiarte en todo lo que te falta aprender del uso del framework.

saludos cordiales
Absalón Valdés.


--
Has recibido este mensaje porque estás suscrito al grupo "symfony-es" de Google Groups.
Para publicar en este grupo, envía un email a symfo...@googlegroups.com
Para darte de baja, envía un email a symfony-es+...@googlegroups.com
El resto de opciones puedes encontrarlas en http://groups.google.com/group/symfony-es?hl=es

Asier Ramos

unread,
Mar 23, 2012, 1:41:39 PM3/23/12
to symfo...@googlegroups.com
Bueno ante todo gracias por la respuesta. Sobre lo que comentas decirte que son cosas que me serviran para mejorar, como otras muchas que tengo apuntadas(como por ejemplo lo de anon.,tratamiento de AJAX y el tratamiento de excepciones,), pero llevo pocas horas de programacion con este Framework y tengo muchisimas cosas pendiente de aprender y que mejorar. Cojere nota de todas y cada una de las cosas que me estas diciendo y aprendere de ellas. 
El aprendizaje del Framework me esta llevando bastante tiempo y ademas tengo el problema de que tengo que ir avanzando cosas segun "aprendo" pero para mi ahora lo principal es tener las funcionalidades minimas en el menor tiempo posible, luego pretendo revisar las cosas y ver que se puede mejorar, cambiar...

Sobre el problema en si, como puedo guardar un objeto que sea global para toda la sesion si no es como una variable de sesion??Porque se muchas formas por ejemplo en .NET o J2EE pero en PHP no conozco ninguna otra que no sean sesiones. 

Saludos

Richard R. Perez Q.

unread,
Mar 23, 2012, 4:27:44 PM3/23/12
to symfo...@googlegroups.com
Hola Asier,

Un poco fuera del tema, ya que indicas que te estas iniciando, te puedo recomendar el siguiente blog


Como podrás ver en la portada se promociona un libro, el cual te ayudaría a aprender lo que conforma este framework, que tan rápido dependerá de tu tiempo para leerlo.

También puedes encontrar una serie de videos que te ayudaría mucho en este link (del mismo blog)


En este grupo muchas veces se han publicado diferente recuerso para ayudar a aprender, puedes buscarlos, aqui dejo otro mas.




2012/3/23 Asier Ramos <utho...@gmail.com>

--
Has recibido este mensaje porque estás suscrito al grupo "symfony-es" de Google Groups.
Para publicar en este grupo, envía un email a symfo...@googlegroups.com
Para darte de baja, envía un email a symfony-es+...@googlegroups.com
El resto de opciones puedes encontrarlas en http://groups.google.com/group/symfony-es?hl=es



--
Atte.
Richard R. Perez Q.

Asier Ramos

unread,
Mar 23, 2012, 5:50:41 PM3/23/12
to symfo...@googlegroups.com
Gracias por la informacion,el libro de Javier Eguiluz ya lo conocia me lo compre el dia que salio, lo tengo leido y voy haciendo cosillas con el, ademas Javier Eguiluz me ha ayudado con bastantes cosas en mi proyecto. La otra info la mirare en cuanto pueda, pero muchisimas gracias por la informacion de verdad. Se por otra parte muchas cosas no estan correctamente hechas, pero tampoco hago nada que no tenga apuntado a la minima duda para cuando lo que quiero desarrollar este funcional, refactorizarlo y aplicar lo que he ido aprendiendo con el tiempo que son bastantes cosas.

Saludos


2012/3/23 Asier Ramos <utho...@gmail.com>
Para darte de baja, envía un email a symfony-es+unsubscribe@​googlegroups.com

El resto de opciones puedes encontrarlas en http://groups.google.com/​group/symfony-es?hl=es



--
Atte.
Richard R. Perez Q.



2012/3/23 Asier Ramos <utho...@gmail.com>
Para darte de baja, envía un email a symfony-es+unsubscribe@​googlegroups.com

El resto de opciones puedes encontrarlas en http://groups.google.com/​group/symfony-es?hl=es

Asier Ramos

unread,
Mar 24, 2012, 10:33:01 AM3/24/12
to symfo...@googlegroups.com
Buenas aparte de lo que te comente ayer, el enviar los parametros por GET en vez de pasarselos al controlador es porque lo hago con el metodo $.get de jQuery y no se como pasarselos a un controlador de otra forma para realizarlo con AJAX, para hacerlo con un controlador deberia pasarle a path() una ruta dinamica con valores que dependen de campos que se recuperan con javascript, entiendo que esa llamada deberia hacerla con FOSJsRoutingBundle??
Absalón Valdés.

Para darte de baja, envía un email a symfony-es+unsubscribe@​googlegroups.com

Asier Ramos

unread,
Apr 1, 2012, 4:36:16 AM4/1/12
to symfo...@googlegroups.com
Al final la pregunta quedo sin responder, alguna forma de hacer que una lista de objetos durante una sesion se guarde durante toda la navegacion por la pagina sin sesiones?Porque yo es la unica forma que veo. Bueno tambien la podria guardar siempre en la base de datos con su id de sesion pero me parece absurdo guardar informacion que puede no llegarse a completarse...


El viernes 23 de marzo de 2012 12:43:59 UTC+1, Asier Ramos escribió:

Marcos García

unread,
Apr 1, 2012, 12:10:20 PM4/1/12
to symfo...@googlegroups.com
Hola!

Bueno, te comento:

Para empezar, te recomiendo usar $this->getDoctrine()->getEntityManager() en vez de get('doctrine.orm.entity_manager') (es más fácil de recordar). Luego, también podrías hacer uso de los 'use' para no tener que escribir toda la ruta de la clase.

Yo lo que hice para saber si un usuario es anónimo es importar el Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken de forma que si un usuario está logueado, se puede comprobar así

if ($this->get('security.context')->getToken() instanceof UsernamePasswordToken))

Con respecto a lo de las sesiones, yo lo que hago es guardar la información relevante en un array y luego la "seteo" como haces tú, con $request->getSession()->set('elIDquelequierasponer', $array);

Y luego para obtenerlo, con un $sesion = (array) $peticion->getSession()->get('elIDquelequierasponer'); Leí por internet que no es recomendable guardar directamente una entidad en la sesión ya que puede traer problemas...

Si eso, puedes buscar bundles carritos en symfony2 ya hechos y comparar un poco como hacen...

Espero haberte ayudado.

Un saludo,
 
Marcos García
marc...@gmail.com



--
Has recibido este mensaje porque estás suscrito al grupo "symfony-es" de Google Groups.
Para publicar en este grupo, envía un email a symfo...@googlegroups.com
Para darte de baja, envía un email a symfony-es+...@googlegroups.com

Asier Ramos

unread,
Apr 1, 2012, 1:54:36 PM4/1/12
to symfo...@googlegroups.com
Las dos primeras partes la primera la adopte(en un principio creo que lo utilice pero me dio error y utilice la otra forma) y la segunda lo hice de la siguient forma if($this->get('security.context')->isGranted('ROLE_USER')), que creo que es parecido tambien a lo que haces tu.

Lo de la session lo intente hacer serializando con la interfaz serializable(implements Serializable) pero me daba error, me decia que no existia Serializable. Entonces me cree un metodo en la entidad para pasar los datos necesarios en un string y lo guardo en la session. Me gustaria utilizar Serializable pero si me da error pues he tenido qu ebuscar otra solucion.

Saludos y gracias
Reply all
Reply to author
Forward
0 new messages