Foros del Web » Programando para Internet » PHP »

Call to undefined method de un objeto de sesión

Estas en el tema de Call to undefined method de un objeto de sesión en el foro de PHP en Foros del Web. Hola buenas, a ver si me podeis ayudar un poco en este tema, el problema viene con la clase "carrito.php" y el archivo "addproduct.php" para ...
  #1 (permalink)  
Antiguo 28/09/2011, 16:19
 
Fecha de Ingreso: marzo-2010
Ubicación: Sevilla
Mensajes: 11
Antigüedad: 14 años, 1 mes
Puntos: 1
Call to undefined method de un objeto de sesión

Hola buenas, a ver si me podeis ayudar un poco en este tema, el problema viene con la clase "carrito.php" y el archivo "addproduct.php" para añadir productos al carrito. Aparentemente está todo correcto, pero al intentar acceder a un metodo de la clase carrito desde addproduct, me da el fallo de "Call to undefined method". Los códigos son los siguientes:
carrito.php
Código:
<?php
class carrito {
	var $num_productos;
	var $array_id;
	var $array_nombre;
	var $array_descripcion;
	var $array_tamano;
	var $array_precio;
	var $array_cantidad;
	

	function __construct() {
		$this -> num_productos = 0;
	}

	function introduce_producto($id, $nombre,$descripcion ,$tamano, $precio) {
		if (!in_array($id, $this -> array_id)) {
			$this -> array_id[$this -> num_productos] = $id;
			$this -> array_nombre[$this -> num_productos] = $nombre;
			$this -> array_descripcion[$this -> num_productos] = $descripcion;
			$this -> array_tamano[$this -> num_productos] = $tamano;
			$this -> array_precio[$this -> num_productos] = $precio;
			$this -> array_cantidad[$this -> num_productos] = 1;
			$this -> num_productos++;
		} else {
			$posicion = array_search($id, $this -> array_id);
			$this -> array_cantidad[$posicion]++;
		}
	}

	function elimina_producto($linea) {
		$this -> array_id[$linea] = 0;
	}

	function imprime_carrito() {
		$suma = 0;
		for ($i = 0; $i < $this -> num_productos; $i++) {
			if ($this -> tamano[$i] == "mini") {
				echo '<li id="' . $i . '"><a href="products.php?id=' . $this -> array_id[$i] . '&tamano=mini" class="item"><img src="/images/canastillas/' . $this -> array_id[$i] . '"mini.jpg" /></a>
                        <h4>' . $this -> array_nombre[$i] . '</h4>
                        <p>'.$this -> array_descripcion[$i].'</p>
                        <h5>Unidades: ' . $this -> array_cantidad[$i] . ' </h5>
                        <h3>' . round($this -> array_cantidad[$i] * $this -> array_precio[$i], 2) . '&euro;</h3>
                        <a class="delete" href="eliminar_producto_carrito.php?id=' . $this -> array_id[$i] . '">Eliminar</a></li>';
			}

			if ($this -> tamano[$i] == "midi") {
				echo '<li id="' . $i . '"><a href="products.php?id=' . $this -> array_id[$i] . '&tamano=midi" class="item"><img src="/images/canastillas/' . $this -> array_id[$i] . '"midi.jpg" /></a>
                        <h4>' . $this -> array_nombre[$i] . '</h4>
                        <p><p>'.$this -> array_descripcion[$i].'</p></p>
                        <h5>Unidades: ' . $this -> array_cantidad[$i] . ' </h5>
                        <h3>' . round($this -> array_cantidad[$i] * $this -> array_precio[$i], 2) . '&euro;</h3>
                        <a class="delete" href="eliminar_producto_carrito.php?id=' . $this -> array_id[$i] . '">Eliminar</a></li>';
			}

			if ($this -> tamano[$i] == "maxi") {
				echo '<li id="' . $i . '"><a href="products.php?id=' . $this -> array_id[$i] . '&tamano=maxi" class="item"><img src="/images/canastillas/' . $this -> array_id[$i] . '"maxi.jpg" /></a>
                        <h4>' . $this -> array_nombre[$i] . '</h4>
                        <p><p>'.$this -> array_descripcion[$i].'</p></p>
                        <h5>Unidades: ' . $this -> array_cantidad[$i] . ' </h5>
                        <h3>' . round($this -> array_cantidad[$i] * $this -> array_precio[$i], 2) . '&euro;</h3>
                        <a class="delete" href="eliminar_producto_carrito.php?id=' . $this -> array_id[$i] . '">Eliminar</a></li>';
			}

			if ($this -> tamano[$i] == "producto") {
				echo '<li id="' . $i . '"><a href="mum.php" class="item"><img src="/images/products/' . $this -> array_id[$i] . '".jpg" /></a>
                        <h4>' . $this -> array_nombre[$i] . '</h4>
                        <p><p>'.$this -> array_descripcion[$i].'</p></p>
                        <h5>Unidades: ' . $this -> array_cantidad[$i] . ' </h5>
                        <h3>' . round($this -> array_cantidad[$i] * $this -> array_precio[$i], 2) . '&euro;</h3>
                        <a class="delete" href="eliminar_producto_carrito.php?id=' . $this -> array_id[$i] . '">Eliminar</a></li>';
			}
		}
	}

	function precioTotalCarrito() {
		$preciototal = 0;
		for ($i = 0; $i < $this -> num_productos; $i++) {
			$preciototal = $preciototal + ($this -> array_precio * $this -> array_cantidad);
		}
		return round($preciototal, 2);
	}

}
?>
addproduct.php
Código:
<?php
require_once ("carrito.php");
require_once ("operacionesbd.php");
require_once ('crearconexionbd.php');
crearConexionBD();
session_start();

$id = $_GET["id"];
$tipo = $_GET["type"];
if ($tipo == "producto") {
	$elemento = mysql_fetch_assoc(seleccionaCanastillaProductoPorID($id, $tipo));
	$descripcion = substr($elemento["descripcion"], 0, 70);
	$descripcion = $descripcion . "...";
	$_SESSION["carrito"]::introduce_producto($elemento["idproducto"], $elemento["nombre"], $descripcion, $tipo, $elemento["precio"]);
} else {
	$elemento = mysql_fetch_assoc(seleccionaCanastillaProductoPorID($id, $tipo));
	$descripcion = substr($elemento["descripcion"], 0, 70);
	$descripcion = $descripcion . "...";
	if ($tipo == "mini") {
		$precio = $elemento["preciomini"];
	}
	if ($tipo == "midi") {
		$precio = $elemento["preciomidi"];
	}
	if ($tipo == "maxi") {
		$precio = $elemento["preciomaxi"];
	}
	$_SESSION["carrito"] -> introduce_producto($elemento["idcanastilla"], $elemento["nombre"], $descripcion, $tipo, $elemento["precio"]);
}
?>
Como veis el método se llama igual tanto en la llamada como en la clase. La conexión a la BD funciona correctamente así como la creación del objeto carrito en la variable de sesión (comprobado mediante un var_dump()).
Gracias de antemano, un saludo.
  #2 (permalink)  
Antiguo 28/09/2011, 17:01
Avatar de pateketrueke
Modernizr
 
Fecha de Ingreso: abril-2008
Ubicación: Mexihco-Tenochtitlan
Mensajes: 26.399
Antigüedad: 16 años
Puntos: 2534
Respuesta: Call to undefined method de un objeto de sesión

La verdad es que sería inteligente de tu parte compartir el mensaje completo del error, así como describir el contexto preciso en el que resulta el error.

Leer el código no basta, puede estar bien programado, pero seguramente estas empleando mal las sesiones y el objeto a través de ellas.

Sin explicar los pasos para reproducir el error, ¿como esperas que comprendamos?
__________________
Y U NO RTFM? щ(ºдºщ)

No atiendo por MP nada que no sea personal.
  #3 (permalink)  
Antiguo 29/09/2011, 08:43
 
Fecha de Ingreso: marzo-2010
Ubicación: Sevilla
Mensajes: 11
Antigüedad: 14 años, 1 mes
Puntos: 1
Respuesta: Call to undefined method de un objeto de sesión

Exactamente el error es este:

Fatal error: Call to undefined method carrito::introduce_producto() in C:\xampp\htdocs\NoLloresPatito\php\addproduct.php on line 14

Sobre el contexto, estoy dirigiendo desde una url de un botón de "añadir al carrito" que tiene esta estructura:

"http://localhost/nollorespatito/php/addproduct.php?id=1&type=producto"

Estoy en una página de la web, en donde imprimo los diferentes productos y cada producto en el enlace va incluida la id del producto así como del tipo de elemento (existe producto, mini, midi y maxi).
Si falta algún dato más, no dudéis en preguntarme.

Gracias de antemano, un saludo.
  #4 (permalink)  
Antiguo 29/09/2011, 08:55
Avatar de pateketrueke
Modernizr
 
Fecha de Ingreso: abril-2008
Ubicación: Mexihco-Tenochtitlan
Mensajes: 26.399
Antigüedad: 16 años
Puntos: 2534
Respuesta: Call to undefined method de un objeto de sesión

No entiendo, ¿por qué unas veces usas -> y otras ::?
__________________
Y U NO RTFM? щ(ºдºщ)

No atiendo por MP nada que no sea personal.
  #5 (permalink)  
Antiguo 29/09/2011, 09:30
 
Fecha de Ingreso: marzo-2010
Ubicación: Sevilla
Mensajes: 11
Antigüedad: 14 años, 1 mes
Puntos: 1
Respuesta: Call to undefined method de un objeto de sesión

El método que ejecuto en el objeto de sesión lo puse con "::" por si era eso, pero en un principio lo tenía con el "->".
  #6 (permalink)  
Antiguo 29/09/2011, 09:36
Avatar de pateketrueke
Modernizr
 
Fecha de Ingreso: abril-2008
Ubicación: Mexihco-Tenochtitlan
Mensajes: 26.399
Antigüedad: 16 años
Puntos: 2534
Respuesta: Call to undefined method de un objeto de sesión

¿Y en que momento guardas el objeto carrito en la sesión?

Dices que lo haces... pero no se ve donde.
__________________
Y U NO RTFM? щ(ºдºщ)

No atiendo por MP nada que no sea personal.
  #7 (permalink)  
Antiguo 29/09/2011, 09:45
 
Fecha de Ingreso: marzo-2010
Ubicación: Sevilla
Mensajes: 11
Antigüedad: 14 años, 1 mes
Puntos: 1
Respuesta: Call to undefined method de un objeto de sesión

Incluyo el archivo "header.php" en todas las páginas de la web, el código es el siguiente:

Código:
<?php
session_start();
require_once ('crearconexionbd.php');
require_once ('funciones.php');
require_once ('carrito.php');
crearConexionBD();
if (!isset($_SESSION["carrito"])){ 
   	$_SESSION["carrito"] = new carrito(); 
} 
?>
  #8 (permalink)  
Antiguo 29/09/2011, 10:03
Avatar de pateketrueke
Modernizr
 
Fecha de Ingreso: abril-2008
Ubicación: Mexihco-Tenochtitlan
Mensajes: 26.399
Antigüedad: 16 años
Puntos: 2534
Respuesta: Call to undefined method de un objeto de sesión

Creo que deberías leer el manual al respecto de objetos y sesiones, existen ciertas limitaciones y quizá estas cayendo en una de ellas.
__________________
Y U NO RTFM? щ(ºдºщ)

No atiendo por MP nada que no sea personal.
  #9 (permalink)  
Antiguo 29/09/2011, 10:27
 
Fecha de Ingreso: marzo-2010
Ubicación: Sevilla
Mensajes: 11
Antigüedad: 14 años, 1 mes
Puntos: 1
Respuesta: Call to undefined method de un objeto de sesión

Agradecería que especificases un poco más... leerme toda la documentación relativa a objetos y sesiones en PHP no es que sea una respuesta demasiado especifica...
  #10 (permalink)  
Antiguo 29/09/2011, 10:55
Avatar de pateketrueke
Modernizr
 
Fecha de Ingreso: abril-2008
Ubicación: Mexihco-Tenochtitlan
Mensajes: 26.399
Antigüedad: 16 años
Puntos: 2534
Respuesta: Call to undefined method de un objeto de sesión

Comienza por leer acerca de sesiones, pues el problema no es tu objeto, sino la forma en que lo defines y accedes a través de la sesión.
__________________
Y U NO RTFM? щ(ºдºщ)

No atiendo por MP nada que no sea personal.
  #11 (permalink)  
Antiguo 29/09/2011, 15:49
Avatar de Webstudio
Colaborador
 
Fecha de Ingreso: noviembre-2001
Ubicación: 127.0.0.1
Mensajes: 3.499
Antigüedad: 22 años, 5 meses
Puntos: 69
Respuesta: Call to undefined method de un objeto de sesión

Puedo hacerte una sugerencia respecto a tu implementación? En vez de guardar todos los datos en arrays distintos... das demasiado espacio al error, si los indices de repente no se correspondieran los unos con los otros.

Podrías utilizar este acercamiento a tus objetos, donde dejás reservado a cada uno las competencias que le son necesarias. Fijate como todo el tema de trabajo con datos de un producto quedaron dentro de la clase Producto, mientras que los manejos de distintos productos, quedan dentro del Carrito.
Código PHP:
<?php
class Carrito
{
    protected 
$productos = array();

    
/**
     * Agrega un producto al carrito, ya sea asignando un array
     * o un objeto del tipo Producto ya cargado
     */
    
public function agregaProducto($info)
    {
        if(
is_array($info)) {
            
$product = new Producto();
            
$product->cargaPorArray($info);
        } else if(
$info instanceof Producto) {
            
$product $info;
        } else {
            throw 
Exception('Informacion de Producto invalida');
        }

        
$id $product->getId();

        
/** Si el producto ya existe, incrementa la cantidad */
        
if($this->existeProducto($id))
        {
            
$this->obtieneProducto($id)->incrementaCant$product->getCantidad() );
        } else {
            
$this->productos[$id] = $product;
        }
    }

    
/**
     * Retorna una bandera si el producto ya existe
     */
    
public function existeProducto($id)
    {
        return !empty(
$this->productos[$id]);
    }

    
/**
     * Accessor para un producto específico
     * Devuelve null si no existe.
     */
    
public function obtieneProducto($id)
    {
        if (
$this->existeProducto($id)) {
            return 
$this->productos[$id];
        } else {
            return 
null;
        }
    }

    
/**
     * Si pasamos un Producto como parámentro, usa el id para
     * eliminarlo del carrito
     */
    
public function eliminaProducto($producto)
    {
        if (
$producto instanceof Producto) {
            
$id $producto->getId();
        } else {
            
$id = (int) $producto;
        }

        unset(
$this->productos[$id]);
    }

    
/**
     * Calcula el precio total del carrito, tomando en cuenta
     * el precio de cada producto y la cantidad de elementos
     */
    
public function getPrecio()
    {
        
$total 0;
        foreach(
$this->productos as $producto) {
            
$total += $producto->getPrecio();
        }
        return 
round($total2);
    }

    
/**
     * Utiliza un objeto Renderer para representar el Carrito
     * a través de tags HTML
     */
    
public function imprimeProductos()
    {
        
/* Acá yo no soy muy amigo de mezclar HTML dentro de
           objetos de negocio, asi que voy por una opcion
           que suelo utilizar: Objetos Renderers */
        
return CarritoRenderer::render($this);
    }

    public function 
obtenerProductos()
    {
        return 
$this->productos;
    }
}

class 
Producto
{
    protected 
$id           null;
    protected 
$nombre       '';
    protected 
$descripcion  '';
    protected 
$tamano       null;
    protected 
$precio       null;
    protected 
$cantidad     null;

    
/**
     * Accessors, se puede arreglar con un método __get
     */
    
public function getId()
    {
        return 
$this->id;
    }

    public function 
getNombre()
    {
        return 
$this->nombre;
    }

    public function 
getDescripcion()
    {
        return 
$this->descripcion;
    }

    public function 
getTamano()
    {
        return 
$this->tamano;
    }

    public function 
getCantidad()
    {
        return 
$this->cantidad;
    }

    public function 
incrementaCant$cantidad )
    {
        return 
$this->cantidad+=$cantidad;
    }

    public function 
getPrecio()
    {
        return 
$this->precio $this->cantidad;
    }


    public function 
cargaPorArray($data)
    {
        if(!
$this->id) { // evitamos sobreescribir un producto
            
$this->id           $data['id'];
            
$this->nombre       $data['nombre'];
            
$this->descripcion  $data['descripcion'];
            
$this->tamano       $data['tamano'];
            
$this->precio       $data['precio'];
            
$this->cantidad     $data['cantidad'];
        } else {
            throw new 
Exception('Intentaste cargar un producto que ya estaba cargado.');
        }
    }
}
Es una opinión personal, pero a mi no me gusta mezclar tags de HTML junto a mi lógica de negocios, así puedo mantener la funcionalidad independiente de la presentación. En este caso y para este fin, es que creé dos objetos nuevos, que se encargar de representar en HTML a los Productos y al Carrito. Se llaman Renderers porque se me ocurrió llamarlos asi, pero te separan la lógica de presentación por si después querés cambiar el HTML por GTK o por linea de comandos:

Código PHP:
class CarritoRenderer
{
    static public function 
render(Carrito $carrito)
    {
        
$html '';
        foreach(
$carrito->obtenerProductos() as $producto)
        {
            
$html.= ProductoRenderer::render($producto);
        }
        return 
$html;
    }
}


class 
ProductoRenderer
{
    static public function 
render(Producto $producto)
    {
        
$html '';

        
$id $producto->getId();

        if (
$id) {
            
$html.= "<li id='{$id}'>";
            
$html.= self::renderImagen($producto);
            
$html.= self::renderNombre($producto);
            
$html.= self::renderDescripcion($producto);
            
$html.= self::renderCantidad($producto);
            
$html.= self::renderPrecio($producto);
            
$html.= "<a class='delete' href='eliminar_producto_carrito.php?id={$id}'>Eliminar</a>";
            
$html.= '</li>';
        }

        return 
$html;
    }

    static function 
renderImagen(Producto $producto)
    {
        return 
"<a href='products.php?id={$producto->getId()}&tamano={$producto->getTamano()}'
                class='item' >
                <img src='/images/canastillas/{$producto->getId()}{$producto->getTamano()}.jpg' />
                </a>"
;
    }

    static function 
renderNombre(Producto $producto)
    {
        return 
"<h4>{$producto->getNombre()}</h4>";
    }

    static function 
renderDescripcion(Producto $producto)
    {
        return 
"<p>{$producto->getDescripcion()}</p>";
    }

    static function 
renderCantidad(Producto $producto)
    {
        return 
"<h5>Unidades: {$producto->getCantidad()}</h5>";
    }

    static function 
renderPrecio(Producto $producto)
    {
        return 
"<h3>{$producto->getPrecio()}</h3>";
    }

Si te fijás, estos objetos están preparados para ser dibujados con el método render() o llamando a los renders más específicos para armar la estructura que vos quieras luego en tus vistas.

Si vamos a la utlización de estas nuevas clases, podrías hacerlo asi :
Código PHP:
<?php
require_once ("carrito.php");
require_once (
"operacionesbd.php");
require_once (
'crearconexionbd.php');
crearConexionBD();
session_start();

$id $_GET["id"]?$_GET["id"]:null;
$tipo $_GET["type"]?$_GET["type"]:null;
$carrito = new Carrito();

if (
$id && $tipo) {
    
// Pedis los datos.
    
$elemento mysql_fetch_assoc(seleccionaCanastillaProductoPorID($id$tipo));
    
$elemento['descripcion'] = substr($elemento["descripcion"], 070) . "...";

    
//Dependiendo del tipo ...
    
switch($tipo) {
        case 
'mini':
        case 
'midi':
        case 
'maxi':
            
$precio $elemento[$tipo];
            break;
        default:
            
$precio $elemento['precio'];
            break;
    }

    
/* Acá asegurate que los indices del array son los mismos
       que los índices que necesita el objeto Producto */
    
$carrito->agregaProducto($elemento);

echo 
$c->imprimeProductos();
}
Ahora, cómo hacemos para guardar el carrito de compra entero y persistirlo en la sesión?
Esta parte no es TAN simple. Hay algunos métodos, te voy a contar cuál es el que a mi me parece un poco más complicado pero menos inestable. Siempre es bueno separar competencias, asi que la encargada de guardar el carrito en una sesión, debería ser otra clase. Veamos como la podemos hacer lo más simple posible...
Código PHP:
class CarritoSessionMapper
{
    static public function 
getCarrito()
    {
        if(!
session_id()) {
            
session_start();
        }
        if (!empty(
$_SESSION['carrito']) && is_string($_SESSION['carrito']) )
        {
            return 
unserialize($_SESSION['carrito']);
        } else {
            return 
null;
        }
    }

    static public function 
setCarrito(Carrito $carrito)
    {
        if(!
session_id()) {
            
session_start();
        }
        
$_SESSION['carrito'] = serialize($carrito);
    }

Y la manera de utilizarlo, sería algo asi :
Código PHP:
if( ($c CarritoSessionMapper::getCarrito()) === null) {
    
$c = new Carrito();
}

$c->agregaProducto(array(
    
'id'    => 5,
    
'nombre' => 'Zend Framework',
    
'descripcion' => 'Excelente Framework de Desarrollo',
    
'tamano' => 'maxi',
    
'precio' => 25,
    
'cantidad' =>  '3',
));

CarritoSessionMapper::setCarrito($c);

var_dump($_SESSION); 
Ya saben, este tipo de ejercicios me encantan. Si alguna parte no se entendió o no funcionó, me avisan y lo revisamos.

Saludos !
__________________
Tutoriales Photoshop | Web-Studio.com.ar
Artículos PHP | ZonaPHP.com
  #12 (permalink)  
Antiguo 30/09/2011, 07:27
Avatar de Webstudio
Colaborador
 
Fecha de Ingreso: noviembre-2001
Ubicación: 127.0.0.1
Mensajes: 3.499
Antigüedad: 22 años, 5 meses
Puntos: 69
Respuesta: Call to undefined method de un objeto de sesión

Sepan disculpar, releyendo lo publicado me doy cuenta que tuve un error en la parte de "como utilizar las nuevas clases", asi es como debería ir correctamente:
Código PHP:
//Dependiendo del tipo ... 
    
switch($tipo) { 
        case 
'mini'
        case 
'midi'
        case 
'maxi'
            
$precio $elemento[$tipo]; 
            break; 
        default: 
            
$precio $elemento['precio']; 
            break; 
    } 

    
// Ahora si tomamos el valor correctamente.
    
$elemento['precio'] = $precio;
    
    
/* Acá asegurate que los indices del array son los mismos 
       que los índices que necesita el objeto Producto */ 
    
$carrito->agregaProducto($elemento); 
__________________
Tutoriales Photoshop | Web-Studio.com.ar
Artículos PHP | ZonaPHP.com

Etiquetas: call, carrito, clase, class, metodo, tiendas
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

SíEste tema le ha gustado a 1 personas




La zona horaria es GMT -6. Ahora son las 17:54.