1

Necesito agregar un elemento más al array de datos que me retorna una consulta SQL en el modelo. Intenté con array_push(), y no me funcionó.

El modelo es el siguiente:

static public function mdlMostrarUsuarios(){

   $stmt = Conexion::conectar()->prepare("//Consulta");

   $stmt -> execute();

   return $stmt -> fetch();

} //ASÍ ME RETORNA LOS DATOS COMÚN Y CORRIENTE (SIN AGREGARLE NINGUNO TODAVÍA)

Y así es como intenté agregarle un elemento más al array que me retorna:

static public function mdlMostrarUsuarios(){

       $stmt = Conexion::conectar()->prepare("//Consulta");

       $stmt -> execute();

       array_push($stmt, "nuevo", "elemento");

       return $stmt -> fetch();

    }

Pero me arroja el siguiente error:

array_push() expects parameter 1 to be array, object given in D:\xampp\htdocs... on line ... bool(false)

Candelo
  • 519
  • 3
  • 18
  • https://stackoverflow.com/questions/11618349/how-to-add-property-to-object-in-php-5-3-strict-mode-without-generating-error – alanfcm Jan 23 '20 at 23:50

2 Answers2

5

Motivo del error

El error ocurre porque estás haciendo las cosas al revés. En tu código $stmt es un recurso que apunta a los datos, pero no son los datos, por lo tanto no es correcto que intentes meter los elementos del array dentro de $stmt haciendo esto:

array_push($stmt, "nuevo", "elemento"); #Mal hecho, $stmt no es un array

Es importante entender esto para no ir de bruces con PDO. Ten en cuenta que $stmt se crea invocando al método prepare, aquí:

   $stmt = Conexion::conectar()->prepare("//Consulta");

Si lees el Manual de PHP verás que prepare no devuelve un array, sino un objeto que apunta a los datos:

Si el servidor de la base de datos prepara con éxito la sentencia, PDO::prepare() devuelve un objeto PDOStatement. Si no es posible, PDO::prepare() devuelve FALSE o emite una excepción PDOException (dependiendo del manejo de errores).

Solución

Tienes que leer $stmt mediante un método fetch, guardar esa lectura en un array y luego agregar el nuevo dato al array que obtuviste con fetch.

Por ejemplo:

static public function mdlMostrarUsuarios(){
       $stmt = Conexion::conectar()->prepare("//Consulta");
       $stmt -> execute();
       $mData=$stmt -> fetch();
       #Aquí, a los datos recuperados agregamos una clave "nuevo" y un valor "elemento"
       $mData["nuevo"]="elemento";
       return $mData;
    }

También puedes hacerlo al revés, creando primero el array y luego agregando dentro de él el resultado del fetch.

$mData=array("nuevo"=>"elemento");
#Atento aquí a los [] antes del signo de =
$mData[]=$stmt -> fetch();

Otras consideraciones

Conviene que pongas de forma explícita el tipo de fetch que necesitas para los datos, ya que, si no está configurado previamente de otro modo, fetch devuelve por defecto un array asociativo y un array numérico, haciendo que tengas en tus resultados datos que quizá nunca utilizarás y que recargarían la memoria en caso de uso masivo en conexiones concurrentes o en bucles. Para hacer esto, sólo tienes que pasar el fetch style como parámetro a fetch. Por ejemplo, para que te cree un array asociativo, que es lo que se suele usar más a menudo:

       $mData=$stmt -> fetch(PDO::FETCH_ASSOC);

También, para apuntar lo que comenta @quevedo, puedes optar por otro método para obtener los datos que es fetchAll, pero este método tiene algunas diferencias con fetch que debes conocer. Podría ser útil cuando no esperas una cantidad excesiva de filas/columnas en los resultados, porque si son muchas filas, su uso podría desbordar la memoria porque este método mete de golpe todos los datos en una variable. Para profundizar más sobre la diferencia entre ambos métodos, puedes leer esta respuesta.

Hay también un método fetchColumn, que es útil por ejemplo cuando necesitas una columna en específico, por ejemplo en consultas del tipo SELECT COUNT(*) FROM ...

A. Cedano
  • 86,578
  • 19
  • 122
  • 221
  • Si necesitas recoger la consulta como array puedes hacer `$consulta = $stmt->fetchAll(PDO::FETCH_ASSOC);` y tener en cuenta que cada línea es a su vez un array de la forma `['nombre_columna' => valor, ...]` de modo que la adición de valores debe ser cuidadosa pues podrías estar tratando de agregar nuevas líneas con estructura diferente. – quevedo Jan 24 '20 at 03:17
  • @quevedo es correcto. Pero en la respuesta me ceñí a lo que el OP ya tenía. Él estaba leyendo los datos con el método `fetch` por tanto lo dejé cómo estaba. Lo que sí conviene hacer es indicar de forma explícita el *fetch style*, haciendo: `$mData = $stmt->fetch(PDO::FETCH_ASSOC);` porque si no tiene configurado este estilo por defecto `fetch` crea un array asociativo y numérico. – A. Cedano Jan 24 '20 at 10:42
  • @a-cedano sólo agregué la anotación para que quien use tu respuesta (que es bastante buena) cuente con una orientación adicional para recuperar los datos de la consulta. – quevedo Jan 24 '20 at 13:09
2

El error está en que la función array_push() solo soporta 2 parámetros.

array_push($mi_array, 'un valor de cualquier tipo');

Otra forma de agregar un elemento a un array es agregar corchetes luego de la variable, así:

$mi_array[] = 'un valor de cualquier tipo';

y para agregar un elemento a un array con una clave especifica debes hacerlo de la siguiente manera:

$mi_array['mi_clave_personalizada'] = 'un valor de cualquier tipo';

esta linea creará el par clave valor dentro del array si no existe y en caso que exista, lo sobrescribirá.

para ver si la clave está siendo utilizada previamente puedes utilizar la función isset(), que te permitirá saber si el array cuenta con ese indice.

isset($mi_array['mi_clave_personalizada'])

En lo que respecta al error:

array_push() expects parameter 1 to be array, object given...

$stmt no es un array, es un objeto. Debes transformarlo a array si deseas agregarle elementos. Puedes comprobar el tipo del elemento con la función gettype()

Soy César Mora
  • 2,165
  • 3
  • 10
  • 30
  • 1
    Esto puede crear confusión: *`$stmt` no es un array, es un objeto. Debes transformarlo a array si deseas agregarle elementos.* Realmente **`$stmt` no puede *transformase en array***, como si tomas un JSON y lo conviertes en array. `$stmt` es otra cosa, es un objeto o recurso que apunta a los datos y tiene sus propios métodos (`fetch`) para leer ese recurso. Se trata de leer los datos a los que `$stmt` apunta y si se quiere, crear un array con esos datos, pero no es que `$stmt` se transforme a array. – A. Cedano Jan 24 '20 at 00:15
  • Si te fijas en mi respuesta -donde te basaste para actualizar la tuya- mi intención es explicar el "cómo puedo..." para que la persona logre llegar a una solución por si misma y aprenda algo en vez de solo copiar y ejecutar sin entender el por qué. El objeto que mencionas en contexto es una clase (php representa las clases como objetos) así que si puede ser transformada a array dependiendo de lo que buscas y los modificadores de acceso. Yo menciono la palabra "transformación" no castear directamente el objeto a array. – Soy César Mora Jan 24 '20 at 00:27
  • ¿Qué quieres decir con que me basé en tu respuesta para actualizar la mía? Tu afirmación es confusa, porque en ningún caso `$stmt` se puede ni transformar ni castear a array, como ya expliqué claramente **desde el principio**, `$stmt` es un recurso que apunta a los datos, con sus métodos de lectura propios. Jamás podrás transformarlo ni castearlo, podrás solamente leerlo o recorrerlo o como quieras llamarlo. – A. Cedano Jan 24 '20 at 00:30
  • Tienes razón, $stmt en contexto es solo un puntero – Soy César Mora Jan 24 '20 at 00:39