ccc

PHP: Cambiar, modificar o borrar contenido capas por su id

 // **************************************************

function replaceHtmlById($htmlOriginal, $id, $nuevoHtml) {

    libxml_use_internal_errors(true);


    // --- DOM PRINCIPAL ---

    $dom = new DOMDocument;

    $dom->loadHTML(mb_convert_encoding($htmlOriginal, 'HTML-ENTITIES', 'UTF-8'));

    $xpath = new DOMXPath($dom);


    // Buscar el nodo con el ID indicado

    $nodes = $xpath->query("//*[@id='$id']");

    if ($nodes->length === 0) {

        return $htmlOriginal; // No encontró el ID

    }

    $nodoViejo = $nodes->item(0);


    // --- NUEVO NODO ---

    // Usamos un wrapper para poder insertarlo en DOMDocument

    $domNuevo = new DOMDocument;

    $domNuevo->loadHTML("<div id='wrap'>$nuevoHtml</div>", LIBXML_HTML_NODEFDTD | LIBXML_HTML_NOIMPLIED);


    // Nodo raíz dentro del wrapper

    $nodoNuevo = $domNuevo->getElementById('wrap')->firstChild;


    // Importar el nodo nuevo al DOM original

    $nodoNuevoImportado = $dom->importNode($nodoNuevo, true);


    // Reemplazar

    $nodoViejo->parentNode->replaceChild($nodoNuevoImportado, $nodoViejo);


    // Devolver HTML

    return $dom->saveHTML();

}


// *********************************************

function emptyHtmlById($htmlOriginal, $id) {

    libxml_use_internal_errors(true);


    $dom = new DOMDocument;

    $dom->loadHTML(mb_convert_encoding($htmlOriginal, 'HTML-ENTITIES', 'UTF-8'));

    $xpath = new DOMXPath($dom);


    // Buscar nodo

    $nodes = $xpath->query("//*[@id='$id']");

    if ($nodes->length === 0) {

        return $htmlOriginal; // ID no encontrado

    }


    $nodo = $nodes->item(0);


    // Eliminar todos los hijos

    while ($nodo->firstChild) {

        $nodo->removeChild($nodo->firstChild);

    }


    return $dom->saveHTML();

}


******************************************************
function removeHtmlById($htmlOriginal, $id) {
    libxml_use_internal_errors(true);
    $dom = new DOMDocument;
    $dom->loadHTML(mb_convert_encoding($htmlOriginal, 'HTML-ENTITIES', 'UTF-8'));
    $xpath = new DOMXPath($dom);

    // Buscar el nodo con ese ID
    $nodes = $xpath->query("//*[@id='$id']");
    if ($nodes->length === 0) {
        return $htmlOriginal; // No existe el ID
    }

    $nodo = $nodes->item(0);
    // Eliminar el nodo completo
    $nodo->parentNode->removeChild($nodo);
    return $dom->saveHTML();
}

$dom = new DOMDocument;
libxml_use_internal_errors(true);
$dom->loadHTML($cuerpo);
libxml_clear_errors();

$xpath = new DOMXPath($dom);
$nodes = $xpath->query("//*[@id='parrilla_".$_GET['parrilla_old']."']");
if ($nodes->length > 0) {
    $htmlParrilla_old = $dom->saveHTML($nodes->item(0));
}

$nodes = $xpath->query("//*[@id='parrilla_".$_GET['parrilla_new']."']");
if ($nodes->length > 0) {
    $htmlParrilla_new = utf8_decode($dom->saveHTML($nodes->item(0)));
}

$new_cuerpo = removeHtmlById($cuerpo,"parrilla_".$_GET["parrilla_new"]);
$new_cuerpo = replaceHtmlById($new_cuerpo, "parrilla_".$_GET["parrilla_old"], $htmlParrilla_new);

Ancla HTML sin que cambie la URL con #

<a href="javascript:document.getElementById('ancla1').scrollIntoView({ behavior: 'smooth' })">lo que sea</a>
<h2 id="ancla1">xxx</h2>

XAMPP: Tener dos versiones de xampp instaladas en el mismo ordenador

Por ejemplo te descargas desde la web de xampp el ejecutable la última versión de XAMPP que viene ya con PHP 8.2

Al instalarlo lo creas en una nueva carpeta (por ejemplo xampp8_2)

Ahora para ejecutar una versión de XAMPP u otra (las dos no se puede al mismo tiempo pues comparten los mismos puertos) crea unos accesos directos ya sea a:
C:\xampp\xampp-control.exe
ó a:
C:\xampp8_2\xampp-control.exe

Para comprobar en cuál estás en cada momento (aparte del panel de XAMPP que tengas abierto):
http://localhost
y para el phpmyadmin: http://localhost/phpmyadmin/
Una cosa importante es también especificar en el path de ordenador donde está la versión de PHP que quieras ejecutar en cada momento (por ejemplo la 8.2), para ello:
Busca en la barra de Windows "Editar las variables de entorno del sistema".
En la ventana de Propiedades del sistema, pulsa en Variables de entorno.
En “Variables del sistema”, busca la variable Path y edítala.
Modifica la ruta que haya a por ejemplo: c:\xampp8_2\php
Aceptar todo y cierra
Reiniciar el ordenador
Ya si desde el terminal pones php-v te saldrá 8.2

PHPStorm: Cargar desde PHPStorm un repositorio

En el menú de phpstorm: GIT -> Clone
En URL poner los datos del clone:
git@bitbucket.org:lo-que-sea.git
Y en Directory:
C:\xampp\htdocs\lo-que-sea
Creará automáticamente la carpeta lo-que-sea y clonará dicho repositorio en tu ordenador local

GIT: Saber a qué repositorio está apuntando un proyecto

git remote -v

Jquery: Acceder al valor de un campo del form a partir del id del form

$("#formLSG").find('[name="cp"]').val();
Para sacar el valor de todos los campos del form:
$("#formLSG").find('input, select, textarea').each(function() {
    var nombreCampo = $(this).attr('name');
    var valorCampo = $(this).val();
    console.log(nombreCampo + ': ' + valorCampo);
});

Composer: Error porque el paquete a instalar no tiene SSL

Primero poner:
composer config -g secure-http false
Y después ya instalar el paquete que se quiera sin problema:
composer require cboden/ratchet

CSS: Mostrar un texto sobre una imagen al hacer hover sobre ella

 <html>
<head>
<style>
.hover-img {
  background-color: #000;
  color: #fff;
  display: inline-block;
  margin: 8px;
  max-width: 320px;
  min-width: 240px;
  overflow: hidden;
  position: relative;
  text-align: center;   width: 100%;
}

.hover-img figcaption {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  align-items: center;
  z-index: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  line-height: 1.1em;
  opacity: 0;
  z-index: 2;
  transition-delay: 0.1s;
  font-size: 20px;
  font-family: sans-serif;
  font-weight: 400;
  letter-spacing: 1px;
  text-transform: uppercase;
}

.hover-img:hover img { /* oscurecer la imagen */
 opacity:0.6;
}

.hover-img:hover figcaption { /* Mostrar el texto de invisible a visible */
  opacity: 1;
}

.hover-img h2 {
  font-size: 1.3em;
  opacity: 0;
  -webkit-transition: opacity 0.35s, -webkit-transform 0.35s;
  transition: opacity 0.35s, transform 0.35s;
  -webkit-transform: scale(1.5);
  transform: scale(1.5);
  .hover-img:hover h2 {
  opacity: 1;
  -webkit-transform: scale3d(1,1,1);
  transform: scale3d(1,1,1);
}
</style>
</head>
<body>
<figure class="hover-img">
<img src="https://picsum.photos/id/200/440/320.jpg">
  <figcaption>
    <h2>En un lugar de la mancha</h2>
  </figcaption>
</figure>
</body>
</html>

Más información en: https://www.30secondsofcode.org/css/s/image-overlay-hover/

PHPStorm: Hacer GIT desde develop a master

En PHPStorm: Hacer Pull: Ctrl+T
Hacer Push: Ctrl+K

Pasar de Develop a Master: 1. Primero hacerte un pull normal con Ctrl+T
2. En PHPStorm en GIT Version Control te saldrán los cambios q hay en repositorio
3. En PHPStorm: a la derecha del todo en master de colores darle a la flecha: Bajar a Remote -> Develop -> "Merge origjn/develop to master"
4. Una vez esté todo en tu ordenador pues hacerte un push con Ctrl+K para volver a subir al repositorio todo (ya directamente a master)

Node.js: Subir a producción

Lo primero en package.json añadir en scripts el comando de start, quedaría: "scripts": {
   "dev": "nodemon src/index.js",
   "start": "node src/index.js"
},
Tener creado un .gitignore con:
node_modules/
.env

Y subir todo al respositorio de github o bitbucket

Node.js: Variables de entorno

npm i dotenv
Creamos el fichero .env en la raiz
PORT=3000
DB_HOST=localhost
DB_PORT=3306 # es el port para mysql
DB_USER=root
DB_PASSWORD=
DB_DATABASE=ejemplo
Creamos el fichero src/config.js
import {config} from "dotenv"
config()
export const PORT = process.env.PORT || 3000
export const DB_HOST = process.env.DB_HOST || localhost
export const DB_PORT = process.env.DB_PORT || 3306
export const DB_USER = process.env.DB_USER || root
export const DB_PASSWORD = process.env.DB_PASSWORD || ""
export const DB_DATABASE = process.env.DB_DATABASE || ejemplo
Y ahora ya en el fichero src/db.js:
import {createPool} from "mysql2/promise"
import {PORT,DB_HOST,DB_PORT,DB_USER,DB_PASSWORD,DB_DATABASE} from "./config.js"

export const pool = createPool({
   host: DB_HOST,
   user: DB_USER,
   password: DB_PASSWORD,
   port: DB_PORT,
   database: DB_DATABASE
})
Una forma más limpia y ordenada es no poner todo el código en index.js sino crear un fichero src/app.js donde meter todas las inicializaciones del index, y en el index dejar solo:
import app from "./app.js"
import {PORT} from "./config.js"
app.listen(PORT)
console.log("server funcionando en: "+PORT)

Node.js: Control de errores

Cuando se produce un error se para la ejecución y no se puede seguir usandolo. Por tanto siempre es aconsejable usar try y catch para todo. try {
   const [rows] = await pool.query("select * from clientes")
   res.json(rows)
}
catch(error) {
   return res.status(500).json({
     message: "algo ha fallado"
   })
}

Así si se produce cualquier error se ejecuta el catch, sale ese mensaje pero la ejecución no se interrumpe y sigue todo OK.
Personalizar el mensaje de error si una url no existe. En el index.js justo antes del app.listen(3000):
// si no encuentra ninguna ruta que saque un error de pag no encontrada
app.use((req,res,next) => {
   res.status(404).json({
     message: "Error: Esa url no existe"
   })
})

Node.js: Actualizar un dato

En el clientesRoutes.js:
router.put("/updateCliente/:id",updateCliente)
En el clientesController:
export const updateCliente = async (req,res) => {
   const id = req.params.id
   const {nombre,edad,profesion} = req.body
   const [result] = await pool.query("update clientes set nombre=IFNULL(?,nombre), edad=IFNULL(?,edad), profesion=IFNULL(?,profesion) where id = ?",[nombre,edad,profesion,id])
   if (result.affectedRows == 0) {
     return res.status(404).json({
        message: "Cliente no se pudo actualizar"
     })
   }
   res.send("Cliente actualizado")
}

A la hora de envíar se pondrá en el Thunder Client (o en el POstman) PUT localhost:3000/updateCliente/2

Por convenio si no se van a actualizar todos los datos entonces se envía con PATCH (aunque hace lo mismo que PUT)

Node.js Controllers: Borrar un dato

En \src\routes\clientesRoutes.js:
router.delete("/deleteCliente/:id",deleteCliente)
En \src\controllers\clientesControllers.js:
export const deleteCliente = async (req,res) => {
   const [result] = await pool.query("deleteeee from clientes where id = ?",[req.params.id])
   if (result.affectedRows <=0) {
     return res.status(404).json({
     "message": "Cliente no encontrado al intentar borrarlo"
     })
   }
   res.sendStatus(204) // que todo OK pero no envia nada
}

Node.js controllers: Obtener datos

En \src\routes\clientesRoutes.js:
router.get("/getCLientes",getClientes)
router.get("/getCLienteById/:id",getClienteById)

En \src\controllers\clientesControllers.js:
export const getClientes = async (req,res) => {
   const [rows] = await pool.query("selectttt * from clientes")
   res.json(rows)
}

export const getClienteById = async (req,res) => {
   const [rows] = await pool.query("selecttttt * from clientes where id = ?", [req.params.id])
   if (rows.length <= 0) {
      return res.status(404).json({
      "message": "Cliente no encontrado"
      })
   }
   res.json(rows[0])
}

Node.js: Controllers: Insertar datos

Para probarlo desde el postman o desde el Thunder Client enviamos la prueba en json a:
POST: localhost:3000/crearCliente:
{
   "nombre": "nom3",
   "edad": 33,
   "profesion": "prof3"
}

Para poder recibir en json en el index.js tenemos q tener:
app.use(express.json());
Y luego en clientesController:
export const crearCliente = async (req,res) => {
   const {nombre,edad,profesion} = req.body
   const [rows] = await pool.query("insert into clientes(nombre,edad,profesion) values (?,?,?)", [nombre,edad,profesion])
   res.send(rows)
}

Node.js: Controllers

Creas un fichero \src\controllers\clientesControllers.js:
export const getClientes = (req,res) => {
   res.send("Aquí obtendremos todos los clientes")
}
export const crearCliente = (req,res) => {
   res.send("Crear cliente nuevo")
}
export const updateCliente = (req,res) => {
   res.send("Actualizar cliente")
}
export const deleteCliente = (req,res) => {
   res.send("Borrar cliente")
}

Y en \src\routes\clientesRoutes.js:
import {Router} from "express"
import {getClientes,crearCliente,updateCliente,deleteCliente} from "../controllers/clientesControllers.js"

const router = Router()

router.get("/getCLientes",getClientes)
router.post("/crearCliente",crearCliente)
router.put("/updateCliente",updateCliente)
router.delete("/deleteCliente",deleteCliente)

export default router;

Node.js: Crear rutas

Por ejemplo crear rutas para usar en nuestro index.js: routes/index_routes.js:
import {Router} from "express"
import {pool} from "../src/db.js"
const router = Router()

router.get("/probarCnn", async (req,res) => {
   const result = await pool.query("select * from clientes")
   res.json(result)
})
export default router;
Y luego para usarlo en nuestro index.js:
import indexRoute from "../routes/index_routes.js"
...
app.use(indexRoute)

Otro ejemplo: routes/clientes_routes.js:
import {Router} from "express"
const router = Router()

router.get("/getCLientes",(req,res) => {
   res.send("Aquí obtendremos todos los clientes")
})
export default router;
Y para usarlo en el index (o en el fichero q queramos):
import clientRoute from "../routes/clientes_routes.js"
...
app.use(clientRoute)