Spanish [B4A] [Tutorial] Sentencias Preparadas PHP, PDO, MYSQL

rscheel

Well-Known Member
Licensed User
Longtime User
Estimados les traigo un pequeño tutorial que les servirá mucho, se trata de usar sentencias preparadas con PDO usando una BD remota MySQL, este método de conectarse a una bd remota se utiliza mucho en Android Studio.

Por ahora Comenzare con ingresar datos a la BD y listar esos datos, mas adelante iré agregando actualización y eliminación de los datos.

Comenzaremos con los Archivos PHP que deben tener en su servidor, hosting o localhost.

*Nuestro Script para crear la Tabla meta en su BD.

B4X:
CREATE TABLE `meta` (
  `idMeta` int(3) NOT NULL AUTO_INCREMENT,
  `titulo` varchar(56) NOT NULL,
  `descripcion` varchar(128) NOT NULL,
  `prioridad` varchar(20) DEFAULT NULL,
  `fechaLim` date DEFAULT NULL,
  `categoria` varchar(20) NOT NULL,
  PRIMARY KEY (`idMeta`)
) ENGINE=MyISAM AUTO_INCREMENT=44 DEFAULT CHARSET=latin1;

mysql_login.php

B4X:
<?php
/**
* Provee las constantes para conectarse a la base de datos
* Mysql.
*/
define("HOSTNAME", "Servidor");
define("DATABASE", "basededatos");
define("USERNAME", "usuario");
define("PASSWORD", "password");
?>

Database.php

B4X:
<?php
/**
* Clase que envuelve una instancia de la clase PDO
* para el manejo de la base de datos
*/

require_once 'mysql_login.php';


class Database
{

    /**
     * Única instancia de la clase
     */
    private static $db = null;

    /**
     * Instancia de PDO
     */
    private static $pdo;

    final private function __construct()
    {
        try {
            // Crear nueva conexión PDO
            self::getDb();
        } catch (PDOException $e) {
            // Manejo de excepciones
        }


    }

    /**
     * Retorna en la única instancia de la clase
     * @return Database|null
     */
    public static function getInstance()
    {
        if (self::$db === null) {
            self::$db = new self();
        }
        return self::$db;
    }

    /**
     * Crear una nueva conexión PDO basada
     * en los datos de conexión
     * @return PDO Objeto PDO
     */
    public function getDb()
    {
        if (self::$pdo == null) {
            self::$pdo = new PDO(
                'mysql:dbname=' . DATABASE .
                ';host=' . HOSTNAME .
                ';charset=utf8',
                USERNAME,
                PASSWORD,
                array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8")
            );

            // Habilitar excepciones
            self::$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        }

        return self::$pdo;
    }

    /**
     * Evita la clonación del objeto
     */
    final protected function __clone()
    {
    }

    function _destructor()
    {
        self::$pdo = null;
    }
}

?>

Meta.php

B4X:
<?php
/**
* Representa el la estructura de las metas
* almacenadas en la base de datos
*/
require 'Database.php';

class Meta
{
    function __construct()
    {
    }

    /**
     * Devuelve metas
     */
    public static function getAll()
    {
        $consulta = "SELECT * FROM meta";
        try {
            // Preparar sentencia
            $comando = Database::getInstance()->getDb()->prepare($consulta);
            // Ejecutar sentencia preparada
            $comando->execute();

            return $comando->fetchAll(PDO::FETCH_ASSOC);

        } catch (PDOException $e) {
            return false;
        }
    }

    /**
     * Insertar una nueva meta
     */
    public static function insert(
        $titulo,
        $descripcion,
        $fechaLim,
        $categoria,
        $prioridad
    )
    {
        // Sentencia INSERT
        $comando = "INSERT INTO meta ( " .
            "titulo," .
            " descripcion," .
            " fechaLim," .
            " categoria," .
            " prioridad)" .
            " VALUES( ?,?,?,?,?)";

        // Preparar la sentencia
        $sentencia = Database::getInstance()->getDb()->prepare($comando);

        return $sentencia->execute(
            array(
                $titulo,
                $descripcion,
                $fechaLim,
                $categoria,
                $prioridad
            )
        );

    }

}

?>

insertar_meta.php

B4X:
<?php
/**
* Insertar una nueva meta en la base de datos
*/
require 'Meta.php';

if ($_GET['REQUEST_METHOD'] == 'GET') {

    // Insertar meta
    $retorno = Meta::insert(
        $_GET['titulo'],
        $_GET['descripcion'],
        isset($_GET['fechaLim']) ? $_GET['fechaLim'] : date('Y-m-d'),
        $_GET['categoria'],
        $_GET['prioridad']);

    if ($retorno) {
        // Código de éxito
        $array = [
                    'estado' => 1,
                    'mensaje' => 'Creación éxitosa',
                ];
        $array2[] = $array;
        print json_encode($array2);
    } else {
        // Código de falla
        $array = [
                    'estado' => 2,
                    'mensaje' => 'Creación fallida, intentelo nuevamente.',
                ];
        $array2[] = $array;
        print json_encode($array2);
    }
}

obtener_metas.php

B4X:
<?php
/**
* Obtiene todas las metas de la base de datos
*/
require 'Meta.php';
mb_internal_encoding('UTF-8');
if ($_GET['REQUEST_METHOD'] == 'GET') {

    // Manejar petición GET
    $metas = Meta::getAll();

    if ($metas) {
        $array1 = [
                    'estado' => 1,
                ];
        $array[] = $array1;
        foreach ($metas as $row) {
            $array[] = $row;
        }
        print json_encode($array);
   
    } else {
        $array = [
                    'estado' => 2,
                    'mensaje' => 'Ha ocurrido un error.',
                ];
        $array2[] = $array;
        print json_encode($array2);
    }
}

Esos serian los archivos php los cuales se encargaran de hacer el trabajo.

*Librerías que deben usar.

Captura3.PNG


*Ahora nuestro Layout y Activity en b4a que inserta los datos quedaría de la siguiente manera.

Captura1.PNG



B4X:
Sub Process_Globals

End Sub

Sub Globals
    Private edTitulo As EditText
    Private edDescripción As EditText
    Private spPrioridad As Spinner
    Private spCategoria As Spinner
    Private ServerIP As String = "URL/insertar_meta.php"
End Sub

Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("LayoutAgregar")
    spPrioridad.AddAll(Array As String("Alta", "Media", "Baja", ""))
    spCategoria.AddAll(Array As String("Salud", "Finanzas", "Espiritual", "Profesional", "Material"))
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub btnAgregar_Click
    GetData("GET","GetMensaje")
End Sub

Sub GetData(ADD As String, sJob As String)
    If edTitulo.Text <> "" And edDescripción.Text <> "" Then
        ProgressDialogShow2("Sincronizando...", False)
        Dim GetSQL As HttpJob
        GetSQL.Initialize(sJob, Me)
        Log("prioridad "&spPrioridad.SelectedItem& " categoria "& spCategoria.SelectedItem)
        GetSQL.download2(ServerIP, Array As String ("REQUEST_METHOD", ADD, "titulo", edTitulo.Text, "descripcion", edDescripción.Text, "prioridad", spPrioridad.SelectedItem, "categoria", spCategoria.SelectedItem))
    Else
        ToastMessageShow("Debe Completar todos los campos", False)
    End If
End Sub

Sub JobDone(Job As HttpJob)
    ProgressDialogHide
    If Job.Success Then
             Dim res As String
            res = Job.GetString
            Log("Back from Job:" & Job.JobName )
            Log("Job Text: " & res)
            Dim parser As JSONParser
            parser.Initialize(res)
        Select Job.JobName
            Case "GetMensaje"
                    Dim ListMode As List
                    Dim lst As List
                    Dim estado As Int
                    lst.Initialize
                    ListMode = parser.NextArray 'returns a list with maps
                If ListMode.Size == 0 Then
                    'ToastMessageShow("No hay registros", True)
                Else
                    For i = 0 To ListMode.Size -1
                        Dim ListaData As Map
                        ListaData = ListMode.Get(i)
                            estado = ListaData.Get("estado")
                            'Log(estado)
                            ProgressDialogHide
                            If estado = 1 Then
                                ToastMessageShow(ListaData.Get("mensaje"), False)
                                edTitulo.Text = ""
                                edDescripción.Text = ""
                            End If
                            If estado = 2 Then
                                ToastMessageShow(ListaData.Get("mensaje"), False)
                            End If
                    Next
                End If
    End Select
    End If
End Sub

*Ahora nuestro Layout y Activity Listar.


Captura2.PNG


B4X:
Sub Process_Globals


End Sub

Sub Globals
    Private lwListar As ListView
    Private ServerIP As String = "http://URL/obtener_metas.php"
End Sub

Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("LayoutListar")
    CargaLista
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub

Sub CargaLista
    ProgressDialogShow2("Cargando Datos...", False)
    GetData("GET","GetLista")
End Sub

Sub GetData(ADD As String, sJob As String)
        Dim GetSQL As HttpJob
        GetSQL.Initialize(sJob, Me)
        GetSQL.download2(ServerIP, Array As String ("REQUEST_METHOD", ADD))
End Sub

Sub JobDone(Job As HttpJob)
    ProgressDialogHide
    If Job.Success Then
             Dim res As String
            res = Job.GetString
            Log("Back from Job:" & Job.JobName )
            Log("Job Text: " & res)
            Dim parser As JSONParser
            parser.Initialize(res)
        Select Job.JobName
            Case "GetLista"
                    Dim ListMode As List
                    Dim lst As List
                    Dim estado As String
                    lst.Initialize
                    ListMode = parser.NextArray 'returns a list with maps
                If ListMode.Size == 0 Then
               
                Else
                    For i = 0 To ListMode.Size -1
                        Dim ListaData As Map
                        ListaData = ListMode.Get(i)
                            estado = ListaData.Get("estado")
                            'Log(estado)
                            If estado <> 2 Then
                                If estado == "null" Then
                                    lwListar.AddSingleLine(ListaData.Get("titulo"))
                                End If
                            Else
                                ToastMessageShow(ListaData.Get("mensaje"), False)
                            End If
                            ProgressDialogHide
                    Next
                End If
    End Select
    End If
End Sub

Sub lwListar_ItemClick (Position As Int, Value As Object)
    ToastMessageShow(Position &" "& Value, False)
End Sub

Sub lwListar_ItemLongClick (Position As Int, Value As Object)
    ToastMessageShow(Position &" "& Value, False)
End Sub

Por ahora seria todo, cualquier consulta, error o acotación me lo dejan en un comentario.
 
Last edited:

bgsoft

Well-Known Member
Licensed User
Longtime User
Buen trabajo Rscheel.

Gracias por el aporte.

Saludos
 

desof

Well-Known Member
Licensed User
Longtime User
Genial Rscheel me anduvo de primera muy buen aporte este!
Gracias amigo !!

Abrazos
 

desof

Well-Known Member
Licensed User
Longtime User
Si a este ejemplo le quiisiera implementar que cuando se seleccione de la lista un item me muestre una imagen que este cargado el path en un campo de la BD como seria ?
 
Top