viernes, 19 de junio de 2020

Lenguaje de intercambio JSON

JSON (JavaScript Object Notation - Notación de Objetos de JavaScript) es un formato de intercambio de datos entre sistemas independientes del lenguaje de programación derivado de JavaScript. Sin embargo debido a que emplea convenciones muy empleadas por programadores en la rama del lenguaje C, muchos lenguajes de programación han incluido código para generar y analizar datos en este formato para convertirlos en convertirlos en objetos del lenguaje propio, así se puede concluir que este presenta facilidad de entendimiento tanto para humanos como computadores.

Composición

JSON se construye a partir de dos tipos de estructuras
  • Colección de pares de clave/valor.
    • En lenguajes de programación se tranforman o provienen de un objeto, registro, estructura, diccionario, tabla hash, lista de claves o un arreglo asociativo.
  • Lista de valores. 
    • En lenguajes de programación, esto se implementa o proviene de arreglos, vectores, listas o secuencias.

Sintaxis


En el caso de objetos individuales, este esta delimitad por llaves, dentro aparecen los pares clave valor separados por dos puntos (:) cumpliéndose lo siguiente:
  • La clave siempre será una cadena de texto, el valor puede ser de tipo lógico, textual o numérico.
  • Los valores pueden tomar tres tipos:
    • En el caso del lógico puede ser true o false sin necesidad de comillas
    • En el caso del numérico se emplea el punto para separar enteros de decimales
    • En el caso del texto debe ir entre comillas.

Nota: Se puede dar el caso que el valor de una clave es otro objeto o una colección de estos.

Ejemplo en código:
{
 "alive":true,
 "birthday":"1993-05-17",
 "dni":"96584422",
 "name":"Paul",
 "weight":62.7
}

En el caso de colecciones de objetos, los objetos mantienen su notación anterior y se separan por comas. Además, toda la colección de objetos esta delimitada por corchetes "[" y "]"

Ejemplo en código:
[
 {
  "birthday":"1993-02-07",
  "dni":"10084422",
  "name":"Milagros",
  "weight":52.7
 },
 {
  "birthday":"1992-10-01",
  "dni":"00084422",
  "name":"Yadira",
  "weight":57.0
 },
 {
  "birthday":"1990-01-21",
  "dni":"41557422",
  "name":"Alejandra",
  "weight":49.9
 }
]

En el ejemplo anterior podemos encontrar una colección de tres objetos.


Anidamiento en JSON.

{
   "address":{
      "country":"Peru",
      "department":"Lima"
   },
   "alive":true,
   "birthday":"1993-05-17",
   "dni":"96584422",
   "languages":[
      "Spanish",
      "English"
   ],
   "name":"Paul",
   "pets":[
      {      
         "name":"Argos",
         "type":"dog"
      },
      {      
         "name":"Gardfield",
         "type":"cat"
      }
   ],
   "weight":62.7   
}

Se puede apreciar lo siguiente:

  • La dirección esta compuesta por país y departamento.
  • Tiene un campo lógico llamado "alive"
  • Las fechas viajan en formato de texto
  • Los números como  "weight" no requieren de comillas, pero los códigos como el DNI sí.
  • El campo languages tiene una colección de valores sin clave.
  • En el campo "pets" el valor es una lista de dos objetos con sus propias claves y valores.

Biblioteca gráfica ImageGD en PHP

PHP tiene su propia librería gráfica (al 2020 aún en desarrollo) que permite generar gráficos rectangulares, circulares, lineales y textuales. Además, usar colores en el formato RGB para estos.

Sobre esta biblioteca el manual de PHP menciona:
"PHP no está limitado a crear únicamente salidas HTML. También se puede usar para crear y manipular ficheros de imágenes en una variedad de diferentes formatos de imagen, incluyendo GIF, PNG, JPEG, WBMP y XPM. Aún más práctico es que PHP puede transferir flujos de imagen directamente al navegador. Necesitará compilar PHP con la biblioteca de funciones de imágenes GD para que esto funcione. GD y PHP también pueden requierir otras bibliotecas, dependiendo de los formatos de imagen con los que se quiera trabajar".
Esta biblioteca permite crear imágenes de tipo:
  • JPEG
  • GIF
  • PNG
  • SWF
  • TIFF
  • JPEG2000


Creando una imagen con "imagecreatetruecolor"

<?php

# Definir el tipo de contenido de la página
header("content-type:image/png");

#Crear la imagen con dimensiones de 200px por lado
$imagen = imagecreatetruecolor(200, 200);

# Mostrar la imagen en formato PNG
imagepng($imagen);

# Liberar memoria
imagedestroy($imagen);

?>


Creando colores con "imagecolorallocate"

<?php

# Permite definir un color RGB
$colorRojo= imagecolorallocate($imagen, 255, 0, 0);

# Permite definir un color RGB
$colorBlanco= imagecolorallocate($imagen, 255, 255, 255);

# Permite definir un color RGB
$colorAmarillo= imagecolorallocate($imagen, 255, 255, 0);

?>


Creando figuras

Tenemos diversos métodos para crear figuras con y sin relleno como:


Figuras sin relleno
  • imagearc — Dibuja un arco parcial
  • imageellipse — Dibuja una elipse
  • imagepolygon — Dibuja un polígono
  • imagerectangle — Dibuja un rectángulo
Figuras con relleno
  • imagefilledarc — Dibuja un arco parcial y rellenarlo
  • imagefilledellipse — Dibuja una elipse con relleno
  • imagefilledpolygon — Dibuja un polígono con relleno
  • imagefilledrectangle — Dibuja un rectángulo con relleno


<?php

# Definir el tipo de contenido de la página
header("content-type:image/png");

#Crear la imagen con dimensiones de 200px por lado
$imagen = imagecreatetruecolor(200, 200);

# Permite definir un color RGB
$colorAmarillo= imagecolorallocate($imagen, 255, 255, 0);
$colorRojo= imagecolorallocate($imagen, 255, 0, 0);

# Gráfica de un rectángulo
imagerectangle($imagen, 10, 10, 190, 190, $colorAmarillo);

# Gráfica de un rectángulo con color de relleno
imagefilledrectangle($imagen, 40, 40, 160, 160, $colorRojo); 

# Mostrar la imagen en formato PNG
imagepng($imagen);

# Liberar memoria
imagedestroy($imagen);

?>


IMAGELINE

Esta función permite la creación de líneas con la siguiente sintaxis:
imageline($image, $x1, $y1, $x2, $y2, $color);
  • image: Un recurso image, es devuelto por una de las funciones de creación de imágenes, como imagecreatetruecolor().
  • x1: Coordenada x del primer punto.
  • y1: Coordenada y del primer punto.
  • x2: Coordenada x del segundo punto.
  • y2: Coordenada y del segundo punto.
  • color: El color de la línea. Un identificador de color creado con imagecolorallocate().
<?php

header("Content-Type: image/png");
$imagen = imagecreatetruecolor(400, 400);
$color = imagecolorallocate($imagen, 255, 255, 0);

# imageline($image, $x1, $y1, $x2, $y2, $color);
imageline($imagen, 12, 33, 300, 200, $color);

# Mostrar la imagen en formato PNG
imagepng($imagen);

# Liberar memoria
imagedestroy($imagen);

?>


IMAGERECTANGLE

Esta función permite la creación de rectágulos con la siguiente sintaxis:
imagerectangle ($image, $x1, $y1, $x2, $y2, $color);
  • image: Un recurso image, es devuelto por una de las funciones de creación de imágenes, como imagecreatetruecolor().
  • x1: Coordenada x de partida.
  • y1: Coordenada y de partida.
  • x2: Coordenada x de llegada.
  • y2: Coordenada y de llegada.
  • color: El color de la línea. Un identificador de color creado con imagecolorallocate().
<?php

header("Content-Type: image/png");
$imagen = imagecreatetruecolor(400, 400);
$color = imagecolorallocate($imagen, 255, 255, 0);

# imagerectangle ($image, $x1, $y1, $x2, $y2, $color);
imagerectangle ($imagen, 12, 33, 300, 200, $color);

# Mostrar la imagen en formato PNG
imagepng($imagen);

# Liberar memoria
imagedestroy($imagen);

?>


IMAGEREARC

Esta función permite la creación de arcos y circunferencias con la siguiente sintaxis:
imagearc($image, $cx, $cy, $ancho, $largo, $inicio, $fin, $color);
  • image: Un recurso image, es devuelto por una de las funciones de creación de imágenes, como imagecreatetruecolor().
  • cx: Coordenada x del centro.
  • cy: Coordenada y del centro.
  • largo: largo del arco.
  • ancho: ancho del arco.
  • inicio: ángulo de inicio en grados sexagésimales.
  • fin: ángulo de fin en grados sexagésimales.
  • color: El color de la línea. Un identificador de color creado con imagecolorallocate()
<?php

header("Content-Type: image/png");
$imagen = imagecreatetruecolor(400, 400);
$color = imagecolorallocate($imagen, 255, 255, 0);

# imagearc($image, $cx, $cy, $an, $la, $ini, $fin, $col);
imagearc ($imagen, 200, 200, 100, 100,0, 360, $color);

# Mostrar la imagen en formato PNG
imagepng($imagen);

# Liberar memoria
imagedestroy($imagen);

?>




Métodos GET y POST con PHP

Para enviar información a través de la web tenemos dos métodos que son el protocolo HTTP que emplea el método POST y mediante la URL que emplea el método GET.


Método GET

Es mucho más veloz, pero tiene ciertas limitaciones como la cantidad de datos a enviar, no se permite enviar archivos y se visualiza el valor enviado por el URL, lo que lo puede hacer aparentemente frágil para sistemas de autentificación, pero si se le añade encriptamiento resulta en un método seguro y veloz.

Supongamos el siguiente formulario en una página llamada "formulario.html"
<!DOCTYPE html>
<html>
    <head>
        <title>Formulario GET</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
    </head>
    <body>
        <form action="receptorget.php" method="GET">
            <label>Nombre</label><br/>
            <input type="text" name="txtNombre"/><br/><br/>
            <label>Clave</label><br/>
            <input type="password" name="txtClave"/>
            <br/><br/>
            <select name="txtIdioma">
                <option value="esp">Español</option>
                <option value="ing">Inglés</option>
                <option value="fra">Francés</option>
            </select><br/><br/><br/>
            <button type="submit">Enviar por GET</button>
        </form>  
    </body>
</html>

Se aprecia que en el formulario aparecen dos atributos con sus respectivos valores que son:
  • action: indica a que página viajarán los datos
  • method: indica la forma de enviar los datos, en este caso GET

La salida visual sería:












En una página llamada "receptorget.php" vamos a recibir estos valores enviados por GET, el URL que aparecerá en el navegador tendrá la siguiente forma:

http://localhost/test/receptorget.php?txtNombre=Paul&txtClave=12345&txtIdioma=ing

El código de "receptorget.php" sería:
<?php

$nombre = $_GET["txtNombre"];
$clave = $_GET["txtClave"];
$idioma = $_GET["txtIdioma"];

echo "Nombre: $nombre <br/>";

echo "Longitud de la clave: " . strlen($clave) . "<br/>";

switch ($idioma) {
    case "esp":
        echo "Habla español";
        break;
    case "ing":
        echo "Habla inglés";
        break;
    case "fra":
        echo "Habla francés";
        break;
    case "":
        echo "No ingresó idioma";
        break;
    default:
        echo "ERROR";
        break;
} ?>

El resultado visual sería el siguiente:
Nombre: Paul
Longitud de la clave: 5
Habla inglés 

Método POST

Es menos veloz que el método GET, pero permite enviar una gran la cantidad de datos, incluidos archivos como fotos y no se visualiza los valores enviados en el URL, lo que lo convierte en el método favorito para inicio de sesión.

Supongamos el siguiente formulario en una página llamada "formulario.html"
<!DOCTYPE html>
<html>
    <head>
        <title>Formulario GET</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
    </head>
    <body>
        <form action="receptorget.php" method="POST">
            <label>Nombre</label><br/>
            <input type="text" name="txtNombre"/><br/><br/>
            <label>Clave</label><br/>
            <input type="password" name="txtClave"/>
            <br/><br/>
            <select name="txtIdioma">
                <option value="esp">Español</option>
                <option value="ing">Inglés</option>
                <option value="fra">Francés</option>
            </select><br/><br/><br/>
            <button type="submit">Enviar por POST</button>
        </form>  
    </body>
</html>

Se aprecia que en el formulario aparecen dos atributos con sus respectivos valores que son:
  • action: indica a que página viajarán los datos
  • method: indica la forma de enviar los datos, en este caso POST

La salida visual sería:












En una página llamada "receptorpost.php" vamos a recibir estos valores enviados por POST, el URL que aparecerá en el navegador no tiene ninguna modificación

El código de "receptorget.php" sería:
<?php

$nombre = $_POST["txtNombre"];
$clave = $_POST["txtClave"];
$idioma = $_POST["txtIdioma"];

echo "Nombre: $nombre <br/>";

echo "Longitud de la clave: " . strlen($clave) . "<br/>";

switch ($idioma) {
    case "esp":
        echo "Habla español";
        break;
    case "ing":
        echo "Habla inglés";
        break;
    case "fra":
        echo "Habla francés";
        break;
    case "":
        echo "No ingresó idioma";
        break;
    default:
        echo "ERROR";
        break;
} ?>

El resultado visual sería el siguiente:
Nombre: Paul
Longitud de la clave: 5
Habla inglés 



El método $_Request["name"]

PHP tiene como método de entrada a GET y POST, pero cuando se desconoce el medio por el que llegarán los datos se puede recurrir al método $

<?php
   $nombre = $_REQUEST["txtNombre"];
   $clave = $_REQUEST["txtClave"];
   $idioma = $_REQUEST["txtIdioma"];
?>

Modificaciones de seguridad

Por cuestiones de seguridad y adaptándonos a los nuevos cambios se reemplaza los $_GET y $POST por:
<?php
$dia =  filter_input(INPUT_GET, 'txtIdioma', FILTER_SANITIZE_STRING);
$clave = filter_input(INPUT_POST, 'txtIdioma', FILTER_SANITIZE_STRING); 
?>


jueves, 11 de junio de 2020

Sesiones en PHP

El manual PHP indica sobre el soporte de las sesiones en PHP: "El soporte para sesiones en PHP consiste en una manera de preservar ciertos datos a través de accesos posteriores, lo que permite crear aplicaciones más personalizadas y mejorar el atractivo de un sitio web."


Crear sesiones

Para mantener seguridad al inicio de sesión, por ejemplo. Se opta por el uso de sesiones, ya que estos valores son almacenados en el servidor y no la computadora del usuario.

Para crear una sesión:
<?php
   
   # Iniciar sesión
   session_start();

   # Declarar los identificadores de sesión y sus valores
   $_SESSION["sesion"]="hola";
   $_SESSION["valor"]=12;

?>

$_SESSION (y todas las variables registradas) son serializadas internamente por PHP.

Operaciones con sesiones
<?php

   # Iniciar sesión
   session_start();

   # Crear sesión
   $_SESSION["valor"]=12;

   # Ver el valor de una sesión
   echo $_SESSION["valor"];

   # Actualizar el valor de una sesión
   $_SESSION["valor"]=100;

   # Cerrar sesión
   unset ( $_SESSION["valor"] ); //Liberar memoria
   session_destroy(); //Cerra la sesión propiamente dicha

?>

Usos de las sesiones

"PHP permite el uso de sesiones, valores que podemos usar para autentificar a un usuario, debe ser una medida adicional al encriptado en la base de datos para iniciar sesión"


SESIÓN PARA INICIO DE SESIÓN

<?php

   /* Colocar dentro del método de autentificación de usuario */

   if (validar()=true){
      # Creamos una sesión
      session_star(); 
      # Creamos una clave
      $_SESSION[ "acceso" ]="E14007a"; 
      # Enviamos a la página de inicio
      header ("location: inicio.php"); 
   } else {
      # Creamos una sesión para evitar conflicto al cerrar la sesión
      session_star();
      # Destruimos la sesión
      session_destroy(); 
      # Lo retornamos a la página de login
      header ("location: login.php");
   }

?>


VALIDAR EL INICIO DE SESIÓN

<?php

   # Iniciamos sesión
   session_start();

   # si la sesion es diferente a la iniciada
   if($_SESSION[ "acceso" ] != "E14007a";){ 
      # Destruimos la sesión
      session_destroy();
      # Lo retornamos a la página de login
      header ("location: login.php");
   }
?>

<!-- CÓDIGO HTML -->

Cookies en PHP

Las cookies pueden ser borradas, aceptadas, ignoradas o bloqueadas según se desee, para esto se debe configurar convenientemente el navegador web.

Del punto de vista lingüístico, el término Cookie es un anglicismo para las "galletas informáticas", estas pueden ser borradas, aceptadas, ignoradas o bloqueadas por el cliente mediante la configuración del navegador web.

Tienen diversas aplicaciones como:
  • Como un contador de visitas al sitio web.
  • Un contenedor de información que se almacena en el computador cliente y puede ser consultado por el servidor. Por ejemplo, un carrito de compras virtual.
  • Hacer seguimiento al cliente. Por ejemplo, gustos de navegación, spyware, etc.
  • Uso con intenciones malignas. Por ejemplo, las Zombie cookies.


Crear COOKIES

Para crear una cookie básica se necesita dos parámetros: el nombre de la cookie y el valor asignado. Se debe crear antes de cargar el documento HTML.
<?php
   setcookie("texto", "Bienvenido a PHP");
   setcookie("contador", 12);
   setcookie("acumulado", 33.5);
?>

Del ejemplo anterior hemos creado 3 cookies que almacenan un valor tipo cadena, tipo entero y tipo decimal. Estos se almacenan en la computadora del usuario de modo que no consumen recursos del servidor.

Llamar COOKIES

Todas las cookies se almacenan en $_COOKIE que tiene forma de array, de forma que se les llama mediante su identificador y ese valor se puede almacenar en una variable o mostrar.
<?php

   //Creamos el cookie en un archivo
   setcookie("contador", 12);

?>
<?php
   //Llamamos al cookie desde otro archivo
   $dato = $_COOKIE["contador"];

   echo $dato; //Mostrara en pantalla 12
?>


Parámetros en una cookie

Los parámetros que podemos pasar son:
  • Clave: el nombre de la cookie.
  • Valor: el valor de la cookie.
  • Duración: el tiempo que la cookie está activa.
  • Ruta: el lugar donde se almacena la cookie.
  • Dominio: el servidor donde se almacena la cookie.
  • Protocolo de seguridad: la cookie se puede transmitir por HTTPS.
  • Uso solo de HTTP: la cookie solo es accesible por http y no por otros como javaScript por ejemplo

Cookie con tiempo y sin tiempo

Se puede indicar la duración de una Cookie, si no lo hacemos esta se destruye al cerrar el navegador.

<?php
   /*Sin tiempo*/
   setcookie("nombre","argos") ;
   /* Duración: hasta que se cierre el navegador*/

   /*Con tiempo*/
   setcookie("apodo","perrosaurio", time() + 30*24*60*60) ; 
   /* Duración: 1 mes
      Con Time() iniciamos en cero, y le agregamos un mes en segundos, 
      no afecta si el usuario cierra el navegador
   */
?>


Cookie con ruta

Se puede indicar una ubicación para almacenar las Cookies.
<?php

   #Con ruta simple
   setcookie("apodo","perrosaurio", time() + 30*24*60*60, "/"); 
   //Se guarda en el directorio raíz

   #Con ruta específica
   setcookie("apodo","perrosaurio", time() + 30*24*60*60, "/cookie"); 
   // Se guarda en la carpeta cookie dentro del directorio raíz

?>

Cookie con dominio

Se puede indicar una ruta distinta a la del computador del cliente para almacenar la información:
<?php

   #Con dominio
   setcookie("nombre","argos", time() + 1000, "/c", "www.argosperro.com") ;

   /*
    * Duración: 1000 segundos
    * Carpeta: "c" dentro del directorio del dominio
    * Dominio donde se almacena: www.argosperro.com
   */

?>

Cookie con protocolos HTTPS y HTTP

Se puede implementar protocolos seguros para las Cookies mediante el siguiente formato.
<?php

   #Si queremos usar un protocolo seguro, hacemos:

   setcookie("galleta", "Hola", time()+1000, "/", "www.gatofeliz.com", true, true);

   /*
    * El primer valor en "true" activa el protocolo seguro
    * El segundo "true" evita que se usen protocolos diferentes al HTTP
    * Es necesario establecer un dominio al cual mandar los valores
   */

?>



sábado, 6 de junio de 2020

Framework Bootstrap 4

Desarrollado por la empresa Twitter como un proyecto interno para evitar el uso de múltiples fuentes de desarrollo, en determinado momento, año 2011, fue liberado y puesto a disposición de la comunidad conviertiendose rápidamente, año 2012, en uno de los marcos de trabajo (Framework) más empleados desde GitHub. Cuenta con 4 versiones siendo la 3ra considerada por muchos la más estable, pero es cada vez mayor el uso que se le da a la 4ta versión.


Versión 3 vs versión 4

  • Bootstrap 4 es la versión más nueva de Bootstrap; con nuevos componentes, hoja de estilo más rápida y más capacidad de respuesta.
  • Bootstrap 4 admite las últimas versiones estables de todos los principales navegadores y plataformas. Sin embargo, Internet Explorer 9 y versiones anteriores no son compatibles.
  • Si es necesario soporte para Internet Explorer 8 o 9, se debe emplear Bootstrap 3. Es la versión más estable de Bootstrap, y aún es compatible con el equipo para correcciones de errores críticos y cambios de documentación. Sin embargo, no se le agregan nuevas funciones.

Formas de agregar Bootstrap a un proyecto

Tenemos 2, la primera es hacer la llamada remota al Framework (entre los proveedores tenemos a MaxCDN) y la segunda es descargarlo y tenerlo como una biblioteca interna.

Mediante MaxCDN

Tendríamos el siguiente código:

<!DOCTYPE html>
<html>
    <head>
        <title>Título de la página</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
        <!-- Latest compiled and minified CSS -->
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css">
        <!-- jQuery library -->
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
        <!-- Popper JS -->
        <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>
        <!-- Latest compiled JavaScript -->
        <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js"></script> 
    </head>
    <body>
        <!--Cuerpo de la página-->
    </body>
</html>


Mediante descarga

Se procede a la página oficial de Bootstrap y en la sección de descargas se sigue las instrucciones: https://getbootstrap.com/docs/4.1/getting-started/download/


Grid Classes

Tiene 5 clases que se pueden emplear para el diseño ppor columnas:
  • .col- (extra small devices - pantalla menor que 576px)
  • .col-sm- (small devices - pantalla mayor o igual que 576px)
  • .col-md- (medium devices - pantalla mayor o igual que 768px)
  • .col-lg- (large devices - pantalla mayor o igual que 992px)
  • .col-xl- (xlarge devices - pantalla mayor o igual que 1200px)

Estas se pueden combinar para obtener diferentes disposiciones y estructuras más flexibles. Además, se puede emplear la clase .col que se autodimensiona como en el siguiente ejemplo.


<!DOCTYPE html>
<html>
    <head>
        <title>Título de la página</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0, shrink-to-fit=no">
        <!-- Latest compiled and minified CSS -->
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css">
        <!-- jQuery library -->
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
        <!-- Popper JS -->
        <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>
        <!-- Latest compiled JavaScript -->
        <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js"></script> 
    </head>
    <body>
        <div class="container-fluid">
            <h1>La clase columna</h1>
            <p>Nota: Se autodimensionan automáticamente en una fila de manera que tienen el mismo tamaño</p>
            <div class="row">
                <div class="col" style="background-color:lavender;">.col</div>
                <div class="col" style="background-color:orange;">.col</div>
                <div class="col" style="background-color:lavender;">.col</div>
                <div class="col" style="background-color:orange;">.col</div>
                <div class="col" style="background-color:lavender;">.col</div>
                <div class="col" style="background-color:orange;">.col</div>
            </div>
        </div>
    </body>
</html>