PHP - PDO.. Me hacer el insert en la db pero me tira un error..

 
Vista:
Imágen de perfil de facundo

PDO.. Me hacer el insert en la db pero me tira un error..

Publicado por facundo (185 intervenciones) el 13/08/2017 00:42:34
Hola gente! estoy posteando ya que busque ese error por google pero no encuentro la solucion !!
el error que tira es este:
Notice: Indirect modification of overloaded property Product::$price has no effect in C:\xampp\htdocs\clase-02\index.php on line 43
y lo mismo para linea 44 y 45...


aca serian las lineas 9, 10 y 11

el codigo es este:
Index.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$product->fillAttributes([
        'price' => 453.12,
        'stock' => '23',
        'description' => 'sad asdasd asd as'
    ]);
try {
    $sql = ("INSERT INTO productos(price,stock,description) VALUES(?,?,?)");
    $stmt= $conn->prepare($sql);
    $stmt->bindParam('1', $product->price, PDO::PARAM_INT ,4);
    $stmt->bindParam('2', $product->stock, PDO::PARAM_INT ,3);
    $stmt->bindParam('3', $product->description, PDO::PARAM_STR,50);
    $stmt->execute();
} catch (PDOException $e){
    echo 'No se pudo insertar el producto en la base de datos ' . $e->getMessage();
}

Product.php:
1
2
3
4
5
6
7
class Product extends Model
{
	protected $fillable = [
		'price','stock','description'
	];
 
}

Model.php:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
class Model
{
protected $attributes = [];
	protected $fillable = [];
	public function __set($prop, $value)
	{
		if (! in_array($prop, $this->fillable)) {
			throw new Exception("This attribute '$prop' cannot be assigned", 1);
		}
		$this->attributes[$prop] = $value;
	}
	public function __get($prop)
	{
		if (! array_key_exists($prop, $this->attributes)) {
			throw new Exception("The attribute {$prop} does not exists", 1);
		}
		return $this->attributes[$prop];
	}
	public function fillAttributes(array $data = [])
	{
		foreach ($data as $k => $v) {
			$this->{$k} = $v;
		}
	}
}

Alguien tiene idea que es lo que causa ese error ? Desde ya muchas gracias por su ayuda, saludos!
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder
Imágen de perfil de facundo

PDO.. Me hacer el insert en la db pero me tira un error..

Publicado por facundo (185 intervenciones) el 13/08/2017 02:22:52
SOLUCIONADO !!! La verdad no entiendo el error, pero no se porque se me dio por probar cambiar algo, hice esto $price = $product->price y cambie :
1
$stmt->bindParam('1', $product->price, PDO::PARAM_INT ,4);
por esto:
1
$stmt->bindParam('1', $price, PDO::PARAM_INT ,4);

Así anda y la verdad no entiendo porque... Si alguien puede entender ese error lo doy un premio!! jaja
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
1
Comentar
Imágen de perfil de kip
Val: 2.325
Plata
Ha disminuido 1 puesto en PHP (en relación al último mes)
Gráfica de PHP

PDO.. Me hacer el insert en la db pero me tira un error..

Publicado por kip (877 intervenciones) el 13/08/2017 19:30:51
Hola, el problema es algo confuso de explicar, primero veamos lo que dice la doc del método bindParam()

Vincula una variable de PHP a un parámetro de sustitución con nombre o de signo de interrogación correspondiente de la sentencia SQL que fue usada para preparar la sentencia. A diferencia de PDOStatement::bindValue(), la variable es vinculada como una referencia y solamente será evaluada en el momento en el que se llame a PDOStatement::execute().
http://php.net/manual/es/pdostatement.bindparam.php

Marque con negrita algo interesante, el valor es tomado como referencia por bindParam(), ese es el problema y el notice que te envia PHP es claro en ello, te dice que no tiene efecto la indirecta modificación sobre las propiedades sobrecargadas, pero que significa esto ?
Esto significa que estas usando los metodos mágicos __get y set__ para crear y entregar dinamicamente las propiedades de la clase. Entonces cuando llamas a alguna propiedad creada, dichos valores entregados en si no son una referencia de las propiedades de la clase, ya que son en realidad un valor retornado por una funcion(__get).

Lo que dice la doc es:

Nota:
No se puede pasar ninguno de los parámetros de estos métodos mágicos por referencia.

http://php.net/manual/es/language.oop5.overloading.php

Pero, por que bindParam() requiere el valor por referencia ? La doc tambien nos ayuda y explica:

Muchos parámetros son de entrada, es decir, que son usados en un modo de sólo lectura para construir la consulta. Algunos controladores admiten la invocación de procedimientos almacenados que devuelven datos como parámetros de salida, y algunos también como parámetros de entrada/salida, donde se envían datos y son actualizados al recibirlos.

Es decir que esta variable siempre se enviara como referencia para modificar al tipo de dato pasado como tercer parámetro(constantes PDO::PARAM_*) y ademas si se llama a un procedimiento almacenado se debe tener este valor por referencia para modificarlo(en caso de ser un parámetro INOUT el que reciba el procedure).

Pero el problema en si no es por bindParam(), si no mas bien la sobrecarga de propiedades, si hacemos lo siguiente de seguro te lanza el mismo notice:

1
$price =& $product->price;

En el código anterior estamos haciendo una declaración de variable por referencia a otra y es por eso que nos lanzara el notice.

Tu solución es correcta, ya que al declararlo en $price(sin referencia a la propiedad) es esta variable la que bindParam() tomara como referencia !

Aunque si no usaras algun procedimiento almacenado es mejor usar bindValue() tal como te recomiendan en la misma documentación.

Fuentes de ayuda:
https://stackoverflow.com/questions/9452519/php-notice-when-binding-overloaded-property-in-pdostatementbindparam
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
1
Comentar
Imágen de perfil de facundo

PDO.. Me hacer el insert en la db pero me tira un error..

Publicado por facundo (185 intervenciones) el 13/08/2017 20:07:33
Genial, ahora entiendo, gracias!!
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar