<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>programación web &#8211; danisanchez.net</title>
	<atom:link href="https://danisanchez.net/tag/programacion-web/feed/" rel="self" type="application/rss+xml" />
	<link>https://danisanchez.net</link>
	<description></description>
	<lastBuildDate>Thu, 16 Jan 2020 09:46:15 +0000</lastBuildDate>
	<language>es</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://danisanchez.net/wp-content/uploads/2026/07/cropped-favicon-32x32.png</url>
	<title>programación web &#8211; danisanchez.net</title>
	<link>https://danisanchez.net</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Calcular rutas con OpenStreetMap partiendo de la geolocalización del usuario</title>
		<link>https://danisanchez.net/calcular-rutas-con-openstreetmap-partiendo-de-la-geolocalizacion-del-usuario/</link>
					<comments>https://danisanchez.net/calcular-rutas-con-openstreetmap-partiendo-de-la-geolocalizacion-del-usuario/#comments</comments>
		
		<dc:creator><![CDATA[dani.sanchez]]></dc:creator>
		<pubDate>Thu, 16 Jan 2020 09:46:15 +0000</pubDate>
				<category><![CDATA[Publicaciones]]></category>
		<category><![CDATA[Tutoriales]]></category>
		<category><![CDATA[desarrollo web]]></category>
		<category><![CDATA[openstreetmap]]></category>
		<category><![CDATA[programación web]]></category>
		<category><![CDATA[tutoriales]]></category>
		<guid isPermaLink="false">https://www.gestionatuweb.net/?p=6448</guid>

					<description><![CDATA[Hace unos días veíamos los conceptos básicos para integrar OpenStreetMap en nuestras aplicaciones web. Hoy vamos a ir un paso más allá y veremos un ejemplo de cómo calcular rutas partiendo de la geolocalización del usuario hasta el punto destino que estará predefinido (por ejemplo, nuestro negocio, un punto de interés, etc.). Lo primero, debemos [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Hace unos días veíamos los conceptos básicos para <a href="https://danisanchez.net/integra-openstreetmap-en-tus-aplicaciones-web-con-leaflet-y-mapbox/" target="_blank" rel="noreferrer noopener" aria-label="integrar OpenStreetMap (opens in a new tab)">integrar OpenStreetMap</a> en nuestras aplicaciones web.</p>



<p class="wp-block-paragraph">Hoy vamos a ir un paso más allá y veremos un ejemplo de cómo calcular rutas partiendo de la geolocalización del usuario hasta el punto destino que estará predefinido (por ejemplo, nuestro negocio, un punto de interés, etc.).</p>



<p class="wp-block-paragraph">Lo primero, debemos agregar un nuevo plugin que se encargará de realizar los cálculos de ruta y dibujar el trazado: <a href="https://www.liedman.net/leaflet-routing-machine/"><strong>Leaflet Routing Machine</strong></a>.</p>



<p class="wp-block-paragraph">Este sería el código base de nuestra página HTML, con las llamadas tanto a las librerías de Leaflet como a las de Routing Machine.</p>



<pre class="wp-block-code"><code>&lt;!DOCTYPE html>
&lt;html lang="es">
&lt;head>
    &lt;meta charset="UTF-8">
    &lt;meta name="viewport" content="width=device-width, initial-scale=1.0">
    &lt;meta http-equiv="X-UA-Compatible" content="ie=edge">
    &lt;link rel="stylesheet" href="https://unpkg.com/leaflet@1.2.0/dist/leaflet.css" />
    &lt;link rel="stylesheet" href="https://unpkg.com/leaflet-routing-machine@latest/dist/leaflet-routing-machine.css" />
    &lt;script src="https://unpkg.com/leaflet@1.2.0/dist/leaflet.js">&lt;/script>
    &lt;script src="https://unpkg.com/leaflet-routing-machine@latest/dist/leaflet-routing-machine.js">&lt;/script>
    &lt;title>Calcular rutas&lt;/title>
    &lt;style>
        #mapa{
            height: 600px;
        }
    &lt;/style>
&lt;/head>

&lt;body>
    &lt;div id="mapa">&lt;/div>
&lt;/body>
&lt;/html></code></pre>



<h2 class="wp-block-heading">Comprobar que el dispositivo (navegador) soporta geolocalización</h2>



<p class="wp-block-paragraph">Aquí me voy a centrar en la <strong>documentación de Mozilla</strong> donde no he tenido ningún problema para geolocalizarme con Firefox (en Chrome/Chromium si he tenido problemas para geolocalizarme debido a unas limitaciones que ha impuesto Google a la geolocalización a través de HTML5).</p>



<p class="wp-block-paragraph"><em><strong>El siguiente código está probado para Firefox y podría no funcionar correctamente en otros navegadores.</strong></em></p>



<pre class="wp-block-code"><code>&lt;script>
    if(navigator.geolocation){
        //Funciona la geolocalización
    }
    else{
        //No funciona la geolocalización
    }
&lt;/script></code></pre>



<p class="wp-block-paragraph">Con el código anterior comprobamos si la geolocalización está disponible en el dispositivo o navegador web del usuario, en caso afirmativo dibujaremos un mapa donde se mostrará la ruta calculada desde la posición del usuario hasta nuestra ubicación de interés.</p>



<p class="wp-block-paragraph">En caso de que la geolocalización no funcione, podemos dibujar un mapa normal con la ubicación de nuestro destino (sin calcular rutas).</p>



<pre class="wp-block-code"><code>&lt;script>
    if(navigator.geolocation){
        navigator.geolocation.getCurrentPosition(function(position){
            var latitude = position.coords.latitude;
            var longitude = position.coords.longitude;

            var mymap = L.map('mapa', {
                center: &#91;latitude, longitude],
                zoom: 12
            });

            L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw', {
                maxZoom: 25,
                attribution: 'Datos del mapa de &amp;copy; &lt;a href="https://www.openstreetmap.org/">OpenStreetMap&lt;/a>, ' + '&lt;a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA&lt;/a>, ' + 'Imágenes © &lt;a href="https://www.mapbox.com/">Mapbox&lt;/a>', 
                id: 'mapbox/streets-v11'
            }).addTo(mymap);

            L.Routing.control({
                waypoints: &#91;
                    L.latLng(latitude, longitude),
                    L.latLng(37.17059, -3.60552)
                ],
                language: 'es'
            }).addTo(mymap);
        });
    }
    else{
        var mymap = L.map('mapa', {
            center: &#91;37.17059, -3.60552],
            zoom: 17
        });

        L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token=pk.eyJ1IjoibWFwYm94IiwiYSI6ImNpejY4NXVycTA2emYycXBndHRqcmZ3N3gifQ.rJcFIG214AriISLbB6B5aw', {
            maxZoom: 25,
            attribution: 'Datos del mapa de &amp;copy; &lt;a href="https://www.openstreetmap.org/">OpenStreetMap&lt;/a>, ' + '&lt;a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA&lt;/a>, ' + 'Imágenes © &lt;a href="https://www.mapbox.com/">Mapbox&lt;/a>', 
            id: 'mapbox/streets-v11'
        }).addTo(mymap);
    }
&lt;/script></code></pre>



<h2 class="wp-block-heading">Obtener las coordenadas del usuario</h2>



<p class="wp-block-paragraph">Vamos a comentar un poco el codigo. En caso de que la geolocalización esté disponible, el método que obtiene la ubicación del usuario es <strong>getCurrentPosition</strong>, al que le pasamos una función de callback con un parámetro (position) en el que podemos obtener tanto la latitud como la longitud por separado:</p>



<pre class="wp-block-code"><code>navigator.geolocation.getCurrentPosition(function(position){
    var latitude = position.coords.latitude;
    var longitude = position.coords.longitude;
});</code></pre>



<p class="wp-block-paragraph">A continuación dibujamos el mapa posicionándolo en la ubicación del usuario:</p>



<pre class="wp-block-code"><code>var mymap = L.map('mapa', {
    center: &#91;latitude, longitude],
    zoom: 12
});</code></pre>



<p class="wp-block-paragraph">Hay que tener en cuenta que la geolocalización a través de IP puede no ser muy fiable. Si la central a la que estás conectado se encuentra en tu misma población, la geolocalización te ubicará más o menos en tu pueblo, pero por ejemplo, mi conexión ADSL proviene de una red Air Wifi, cuya central se encuentra en otra ciudad, así que el navegador me geolocaliza en esa otra ciudad&#8230;</p>



<p class="wp-block-paragraph">Esto no ocurre con el navegador de mi smartphone si además tengo activada la Ubicación, en este caso me geolocaliza a la perfección.</p>



<p class="wp-block-paragraph">Tras dibujar el mapa llamamos al Routing Machine pasándole las dos coordenadas a calcular:</p>



<h2 class="wp-block-heading">Llamar al método para calcular la ruta</h2>



<pre class="wp-block-code"><code>L.Routing.control({
    waypoints: &#91;
        L.latLng(latitude, longitude), //dirección obtenida del usuario
        L.latLng(37.17059, -3.60552) //dirección fija de destino
    ],
    language: 'es'
}).addTo(mymap);</code></pre>



<p class="wp-block-paragraph">No olvides especificar el código de idioma para que las indicaciones aparezcan en español.</p>



<figure class="wp-block-image size-large"><img fetchpriority="high" decoding="async" width="984" height="711" src="https://danisanchez.net/wp-content/uploads/2020/01/imagen-5.png" alt="" class="wp-image-6460" srcset="https://danisanchez.net/wp-content/uploads/2020/01/imagen-5.png 984w, https://danisanchez.net/wp-content/uploads/2020/01/imagen-5-300x217.png 300w, https://danisanchez.net/wp-content/uploads/2020/01/imagen-5-768x555.png 768w" sizes="(max-width: 984px) 100vw, 984px" /></figure>



<p class="wp-block-paragraph"><strong>NOTA IMPORTANTE:</strong></p>



<p class="wp-block-paragraph">El cálculo de ruta se origina en un servidor OSRM de demostración cuya finalidad es la de probar la API, de hecho si abrimos la consola del inspector de elementos nos avisa de esto:</p>



<p class="wp-block-paragraph"><em>You are using OSRM&#8217;s demo server. Please note that it is <strong>NOT SUITABLE FOR PRODUCTION USE</strong>. Refer to the demo server&#8217;s usage policy: https://github.com/Project-OSRM/osrm-backend/wiki/Api-usage-policy</em></p>



<p class="wp-block-paragraph"><em>To change, set the serviceUrl option.</em></p>



<p class="wp-block-paragraph"><em>Please do not report issues with this server to neither Leaflet Routing Machine or OSRM &#8211; it&#8217;s for demo only, and will sometimes not be available, or work in unexpected ways.</em></p>



<p class="wp-block-paragraph">P<em>lease set up your own OSRM server, or use a paid service provider for production.</em></p>



<p class="wp-block-paragraph">El texto nos advierte que no es recomendable usarlo para entornos de producción, ya que el servidor puede no estar disponible en determinados momentos.</p>



<p class="wp-block-paragraph">Por lo que si queremos implementar el cálculo de rutas en una aplicación web de producción, deberíamos configurar nuestro propio servidor OSRM en nuestro servicio de hosting (consultar al soporte técnico) y modificar la variable <strong>serviceURL</strong> dentro del <em>leaflet-routing-machine.js</em></p>



<figure class="wp-block-image size-large"><img decoding="async" width="984" height="711" src="https://danisanchez.net/wp-content/uploads/2020/01/imagen-4.png" alt="" class="wp-image-6458" srcset="https://danisanchez.net/wp-content/uploads/2020/01/imagen-4.png 984w, https://danisanchez.net/wp-content/uploads/2020/01/imagen-4-300x217.png 300w, https://danisanchez.net/wp-content/uploads/2020/01/imagen-4-768x555.png 768w" sizes="(max-width: 984px) 100vw, 984px" /></figure>



<h2 class="wp-block-heading">Calcular rutas enviando las coordenadas a OpenStreetMap.org</h2>



<p class="wp-block-paragraph">Si no queremos configurar un servidor OSRM siempre podemos hacer el cálculo de rutas directamente en la web de <a rel="noreferrer noopener" aria-label="openstreetmap.org (opens in a new tab)" href="https://www.openstreetmap.org" target="_blank">openstreetmap.org</a>.</p>



<p class="wp-block-paragraph">Para ello podemos enviar a través de un formulario HTML, las coordenadas mediante GET al action=»https://www.openstreetmap.org/directions?engine=fossgis_osrm_car» si queremos hacer la ruta en coche o a  «https://www.openstreetmap.org/directions?engine=fossgis_osrm_foot» si queremos calcular la ruta a pie.</p>



<p class="wp-block-paragraph">La cadena con las coordenadas tiene que tener la siguiente síntaxis:</p>



<p class="wp-block-paragraph"><em>latitud1,longitud1;latitud2,longitud2</em>, por ejemplo:</p>



<p class="wp-block-paragraph"><em>37.17618,-3.96473;37.1894,-3.7216</em></p>



<p class="wp-block-paragraph">Las coordenadas del usuario tendrán que enviarse en el formulario de forma dinámica, es decir, a través de una variable, mientras que las coordenadas de destino pueden especificarse estáticamente.</p>



<p class="wp-block-paragraph">Para el ejemplo, vamos a crear una página HTML con el formulario, y un archivo de funciones .JS que obtendrá las coordenadas del usuario, las pasará al formulario y lo enviará a openstreetmap.org. En el código he integrado jQuery para hacer las escuchas al botón y enviar los datos.</p>



<p class="wp-block-paragraph">Página HTML:</p>



<pre class="wp-block-code"><code>&lt;!DOCTYPE html>
&lt;html lang="es">
&lt;head>
    &lt;meta charset="UTF-8">
    &lt;meta name="viewport" content="width=device-width, initial-scale=1.0">
    &lt;meta http-equiv="X-UA-Compatible" content="ie=edge">
    &lt;script src="https://code.jquery.com/jquery-3.4.1.min.js"
		integrity="sha256-CSXorXvZcTkaix6Yvo6HppcZGetbYMGWSFlBw8HfCJo="
        crossorigin="anonymous">
    &lt;/script>
    &lt;script src="js/funciones.js">&lt;/script>
    &lt;title>Document&lt;/title>
&lt;/head>
&lt;body>
    &lt;h2>Cómo llegar&lt;/h2>

    &lt;form id="formulario_rutas" method="get" action="https://www.openstreetmap.org/directions?engine=fossgis_osrm_car">    
        &lt;input id="coordenadas" type="hidden" name="route" value=""/>
        &lt;input id="calcular_ruta" type="button" value="Cómo llegar"/>
    &lt;/form>
&lt;/body>
&lt;/html></code></pre>



<p class="wp-block-paragraph">Crearemos un formulario con un campo oculto (hidden) que contendrá como valor la cadena que pasaremos a openstreetmap ya formateada como éste espera recibirla. Y un botón que al hacer clic ejecute todo el proceso.</p>



<p class="wp-block-paragraph">Archivo JS:</p>



<pre class="wp-block-code"><code>"use strict";

$(document).ready(function(){
    $("#calcular_ruta").click(function(){
        if(navigator.geolocation){
            navigator.geolocation.getCurrentPosition(function(position){
                var latitude = position.coords.latitude;
                var longitude = position.coords.longitude;

                var cadenaRuta = latitude+","+longitude+";37.1894,-3.7216";
                $("#coordenadas").val(cadenaRuta);
                $("#formulario_rutas").submit();
            });
        }
    });
});</code></pre>



<p class="wp-block-paragraph">En el archivo de funciones, captamos el clic al botón del formulario, geolocalizamos al usuario y construimos la cadenaRuta que pasaremos como valor al campo hidden (coordenadas) del formulario. Por último hacemos un submit al formulario y OpenStreetMap hará la magia.</p>



<figure class="wp-block-image size-large"><img decoding="async" width="1024" height="588" src="https://danisanchez.net/wp-content/uploads/2020/01/imagen-6-1024x588.png" alt="" class="wp-image-6467" srcset="https://danisanchez.net/wp-content/uploads/2020/01/imagen-6-1024x588.png 1024w, https://danisanchez.net/wp-content/uploads/2020/01/imagen-6-300x172.png 300w, https://danisanchez.net/wp-content/uploads/2020/01/imagen-6-768x441.png 768w, https://danisanchez.net/wp-content/uploads/2020/01/imagen-6.png 1239w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p class="wp-block-paragraph">No queda integrado en nuestra web como sí pasaría con un servidor OSRM, pero al menos es una solución elegante.</p>



<p class="wp-block-paragraph">Paso a paso y no sin alguna dificultad vamos avanzando hacia la no dependencia del todopoderoso GoogleMaps. Seguiremos próximamente&#8230;</p>
]]></content:encoded>
					
					<wfw:commentRss>https://danisanchez.net/calcular-rutas-con-openstreetmap-partiendo-de-la-geolocalizacion-del-usuario/feed/</wfw:commentRss>
			<slash:comments>15</slash:comments>
		
		
			</item>
		<item>
		<title>Crear el Archive Page de nuestro Custom Post (sin plugins)</title>
		<link>https://danisanchez.net/crear-el-archive-page-de-nuestro-custom-post-sin-plugins/</link>
		
		<dc:creator><![CDATA[dani.sanchez]]></dc:creator>
		<pubDate>Fri, 26 Apr 2019 12:00:40 +0000</pubDate>
				<category><![CDATA[Publicaciones]]></category>
		<category><![CDATA[Tutoriales]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[custom post]]></category>
		<category><![CDATA[desarrollo web]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[programación web]]></category>
		<category><![CDATA[publicaciones]]></category>
		<category><![CDATA[tutoriales]]></category>
		<category><![CDATA[wordpress]]></category>
		<guid isPermaLink="false">https://www.gestionatuweb.net/?p=5385</guid>

					<description><![CDATA[Seguimos con esta serie de artículos destinados a la creación de nuestros propios tipos de contenido en WordPress. Hasta ahora hemos visto cómo crear un custom post, asignarle taxonomías y campos personalizados y hasta creamos un template para cargar toda esta información. Ahora lo que nos falta es crear la página archivo (archive page) para [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Seguimos con esta serie de artículos destinados a la creación de nuestros propios tipos de contenido en WordPress. Hasta ahora hemos visto cómo <a href="https://danisanchez.net/crear-un-custom-post-en-wordpress-sin-plugins/" target="_blank" rel="noreferrer noopener">crear un custom post</a>, asignarle <a href="https://danisanchez.net/taxonomias-para-que-sirven-y-como-crearlas-sin-plugins/" target="_blank" rel="noreferrer noopener">taxonomías</a> y <a href="https://danisanchez.net/anadir-campos-personalizados-con-advanced-custom-field/" target="_blank" rel="noreferrer noopener">campos personalizados</a> y hasta<a href="https://danisanchez.net/crear-un-template-para-cargar-nuestro-custom-post-contenido-personalizado/" target="_blank" rel="noreferrer noopener"> creamos un template</a> para cargar toda esta información.</p>



<p class="wp-block-paragraph">Ahora lo que nos falta es crear la página archivo (<strong>archive page</strong>) para listar nuestro custom post, a modo de listado de entradas de WordPress.</p>



<p class="wp-block-paragraph">Para ello, al igual que hicimos con el template para el custom post (<em>single-vehiculos.php</em>), necesitamos crear un nuevo archivo (<em>page.php</em>) al que llamaremos por ejemplo <strong>page-todos-los-vehiculos.php</strong> y guardaremos en el directorio principal del tema activo.</p>



<p class="wp-block-paragraph"><strong>page.php</strong> es el archivo que contiene la estructura básica para una página interna de WordPress y al igual que hicimos con <em>single.php</em>, vamos a aprovechar el codigo escrito para copiarlo en nuestro archivo <em>page-todos-los-vehiculos.php</em> y eliminaremos lo que no necesitamos, dejando únicamente el inicio y final del loop.</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="657" height="621" src="https://danisanchez.net/wp-content/uploads/2019/04/01-loop-archive-custom-post.jpg" alt="" class="wp-image-5389" srcset="https://danisanchez.net/wp-content/uploads/2019/04/01-loop-archive-custom-post.jpg 657w, https://danisanchez.net/wp-content/uploads/2019/04/01-loop-archive-custom-post-300x284.jpg 300w" sizes="auto, (max-width: 657px) 100vw, 657px" /></figure></div>



<p class="wp-block-paragraph">Dentro del loop vamos a crear la consulta que buscará todas entradas de tipo vehículo.</p>



<p class="wp-block-paragraph">La esctructura de la consulta se define:</p>



<pre class="wp-block-code"><code><pre class="wp-block-syntaxhighlighter-code">$args = array(
    'post_type' => 'vehiculos',
    'posts_per_page' => -1,
    'orderby' => 'date',
    'order' => 'DESC'
);
$consulta_vehiculos = new WP_Query($args);</pre></code></pre>



<p class="wp-block-paragraph">Primero declaramos una variable <strong>$args</strong> (argumentos) de tipo <em>array</em> donde pasamos los argumentos de la consulta. Los argumentos más básicos que vamos a definir son: el tipo de post al que hacemos referencia (vehículos), el número de resultados por página (-1 devuelve todos los resultados), el orden (por fecha) y el recorrido del orden (ascendente ASC o descendente DESC).</p>



<p class="wp-block-paragraph">Existen muchos otros argumentos que ponemos incorporar a la consulta para complicarla todo lo que deseemos, pero de momento vamos a empezar por lo más básico.</p>



<p class="wp-block-paragraph">Despues generamos una nueva consulta <strong>new WP_Query()</strong> pasándole los argumentos definidos anteriormente: <strong>new WP_Query($args)</strong>.</p>



<p class="wp-block-paragraph">A continuación vamos a mostrar los datos recogidos en la consulta creando nuestro propio loop. La síntaxis sería la siguiente:</p>



<pre class="wp-block-code"><code><pre class="wp-block-syntaxhighlighter-code">while($consulta_vehiculos->have_posts()) : $consulta_vehiculos->the_post();
   //Código
endwhile; wp_reset_postdata();</pre></code></pre>



<p class="wp-block-paragraph">La forma de declarar nuestro loop personalizado es muy similar al que toma WordPress para el loop principal, con la diferencia de que especificamos la variable donde tenemos nuestra consulta:</p>



<p class="wp-block-paragraph"><strong>while($consulta_vehiculos-&gt;have_posts())</strong><br><strong>$consulta_vehiculos-&gt;the_post()</strong></p>



<p class="wp-block-paragraph">Lo que se traduciría en lenguaje comprensible como: «<em>Mientras existan posts de vehículos, muestrame el post de vehículo</em>«.</p>



<p class="wp-block-paragraph">El final del loop finaliza con <strong>endwhile;</strong></p>



<p class="wp-block-paragraph">Además, para los loops personalizados añadimos la función <strong>wp_reset_postdata()</strong> para «limpiar» los datos de la consulta una vez mostrados y que no interfieran con otros loops que podamos definir en otras partes.</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="728" height="533" src="https://danisanchez.net/wp-content/uploads/2019/04/03-codigo-consulta-final.jpg" alt="" class="wp-image-5396" srcset="https://danisanchez.net/wp-content/uploads/2019/04/03-codigo-consulta-final.jpg 728w, https://danisanchez.net/wp-content/uploads/2019/04/03-codigo-consulta-final-300x220.jpg 300w" sizes="auto, (max-width: 728px) 100vw, 728px" /></figure></div>



<p class="wp-block-paragraph">Para asociar este nuevo archivo con una página interna de WordPress que podamos, por ejemplo añadir al menú principal, crearemos una nueva página y utilizaremos como <em>slug</em> (enlace permanente) el nombre que le hayamos dado al archivo del listado, es decir si hemos llamado al archivo page-todos-los-vehiculos.php utilizaremos como <em>slug</em> en la nueva página «<em>todos-los-vehiculos</em>«.</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="1000" height="460" src="https://danisanchez.net/wp-content/uploads/2019/04/02-slug-pagina-todos-los-vehiculos.jpg" alt="" class="wp-image-5394" srcset="https://danisanchez.net/wp-content/uploads/2019/04/02-slug-pagina-todos-los-vehiculos.jpg 1000w, https://danisanchez.net/wp-content/uploads/2019/04/02-slug-pagina-todos-los-vehiculos-300x138.jpg 300w, https://danisanchez.net/wp-content/uploads/2019/04/02-slug-pagina-todos-los-vehiculos-768x353.jpg 768w" sizes="auto, (max-width: 1000px) 100vw, 1000px" /></figure></div>



<p class="wp-block-paragraph">Como siempre, actualizamos los enlaces permanentes de WordPress en Ajustes &#8211; Enlaces Permanentes &#8211; Guardar Cambios y en este momento quedará asociado el nuevo archivo <em>page-todos-los-vehiculos.php</em> con la página interna de WordPress Vehículos.</p>



<p class="wp-block-paragraph">Para probar nuestra nueva página, vamos a incluir en loop una llamada a la función the_title(), que deberá devolvernos todos los títulos de los post de tipo vehículo que haya en la base de datos:</p>



<pre class="wp-block-code"><code><pre class="wp-block-syntaxhighlighter-code">while($consulta_vehiculos->have_posts()) : $consulta_vehiculos->the_post();
    the_title();
endwhile; wp_reset_postdata();</pre></code></pre>



<p class="wp-block-paragraph">Si visualizamos la página Vehículos, veremos que mostrará el título del post que hay actualmente creado de tipo vehículo:</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="1000" height="423" src="https://danisanchez.net/wp-content/uploads/2019/04/04-vista-pagina-archivo.jpg" alt="" class="wp-image-5398" srcset="https://danisanchez.net/wp-content/uploads/2019/04/04-vista-pagina-archivo.jpg 1000w, https://danisanchez.net/wp-content/uploads/2019/04/04-vista-pagina-archivo-300x127.jpg 300w, https://danisanchez.net/wp-content/uploads/2019/04/04-vista-pagina-archivo-768x325.jpg 768w" sizes="auto, (max-width: 1000px) 100vw, 1000px" /></figure></div>



<p class="wp-block-paragraph">Vamos a añadir algunos vehículos más para poder jugar con los listados de resultados:</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="1000" height="337" src="https://danisanchez.net/wp-content/uploads/2019/04/05.listado-vehiculos.jpg" alt="" class="wp-image-5405" srcset="https://danisanchez.net/wp-content/uploads/2019/04/05.listado-vehiculos.jpg 1000w, https://danisanchez.net/wp-content/uploads/2019/04/05.listado-vehiculos-300x101.jpg 300w, https://danisanchez.net/wp-content/uploads/2019/04/05.listado-vehiculos-768x259.jpg 768w" sizes="auto, (max-width: 1000px) 100vw, 1000px" /></figure></div>



<p class="wp-block-paragraph">Para la página de archivo de vehículos, tomaremos algunos datos para generar el listado, a parte del título, tomaremos la imagen destacada y una parte del contenido. Para ello, en lugar de llamar a la función <strong>the_content()</strong>, llamaremos a la función <strong>the_excerpt()</strong>, que toma solamente una parte del contenido.</p>



<pre class="wp-block-code"><code><pre class="wp-block-syntaxhighlighter-code">while($consulta_vehiculos->have_posts()) : $consulta_vehiculos->the_post();
    the_post_thumbnail();
    the_title('&lt;h2>','&lt;/h2>');
    the_excerpt();
endwhile; wp_reset_postdata();</pre></code></pre>



<p class="wp-block-paragraph">Obtendríamos como resultado:</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="1000" height="1951" src="https://danisanchez.net/wp-content/uploads/2019/04/06-listado-vehiculos-frontend.jpg" alt="" class="wp-image-5407" srcset="https://danisanchez.net/wp-content/uploads/2019/04/06-listado-vehiculos-frontend.jpg 1000w, https://danisanchez.net/wp-content/uploads/2019/04/06-listado-vehiculos-frontend-154x300.jpg 154w, https://danisanchez.net/wp-content/uploads/2019/04/06-listado-vehiculos-frontend-525x1024.jpg 525w, https://danisanchez.net/wp-content/uploads/2019/04/06-listado-vehiculos-frontend-768x1498.jpg 768w, https://danisanchez.net/wp-content/uploads/2019/04/06-listado-vehiculos-frontend-787x1536.jpg 787w" sizes="auto, (max-width: 1000px) 100vw, 1000px" /></figure></div>



<p class="wp-block-paragraph">Por supuesto ya dependería de nosotros darle un poco de formato CSS, metiendo cada apartado en su correspondiente DIV, ajustando el tamaño de las miniaturas, etc. Detalles de diseño que no vamos a ver en este artículo, pues se extendería demasiado y el objetivo principal es el de generar el listado de entradas.</p>



<p class="wp-block-paragraph">En siguientes artículos veremos cómo paginar este listado, para cuando tengamos un número importante de entradas.</p>



<p class="wp-block-paragraph">Nos vemos en el siguiente post! <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Crear un template para cargar nuestro custom post (contenido personalizado)</title>
		<link>https://danisanchez.net/crear-un-template-para-cargar-nuestro-custom-post-contenido-personalizado/</link>
		
		<dc:creator><![CDATA[dani.sanchez]]></dc:creator>
		<pubDate>Thu, 11 Apr 2019 08:05:32 +0000</pubDate>
				<category><![CDATA[Publicaciones]]></category>
		<category><![CDATA[Tutoriales]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[custom post]]></category>
		<category><![CDATA[desarrollo web]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[programación web]]></category>
		<category><![CDATA[tutoriales]]></category>
		<category><![CDATA[wordpress]]></category>
		<guid isPermaLink="false">https://www.gestionatuweb.net/?p=5360</guid>

					<description><![CDATA[Continuamos con esta serie de artículos en los que vemos cómo crear contenidos personalizados en WordPress. Una vez que ya hemos creado nuestro custom post, nuestras taxonomías y campos personalizados, quedará crear la plantilla o template que cargará toda esta información. Dentro de cualquier tema WordPress, el archivo destinado a cargar la información de una [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Continuamos con esta serie de artículos en los que vemos cómo crear contenidos personalizados en WordPress. Una vez que ya hemos creado nuestro <a href="https://danisanchez.net/crear-un-custom-post-en-wordpress-sin-plugins/" target="_blank" rel="noreferrer noopener">custom post</a>, nuestras <a href="https://danisanchez.net/taxonomias-para-que-sirven-y-como-crearlas-sin-plugins/" target="_blank" rel="noreferrer noopener">taxonomías</a> y <a href="https://danisanchez.net/anadir-campos-personalizados-con-advanced-custom-field/" target="_blank" rel="noreferrer noopener">campos personalizados</a>, quedará crear la plantilla o template que cargará toda esta información.</p>



<p class="wp-block-paragraph">Dentro de cualquier tema WordPress, el archivo destinado a cargar la información de una entrada es el single.php.</p>



<p class="wp-block-paragraph">La siguiente imagen muestra el contenido del archivo single.php del tema Twenty Sixteen de WordPress. Cada tema tendrá su código propio, pero lo que nos interesa identificar es dónde comienza y termina el loop. El loop es el código que recoge la información del post que estamos llamando y suele comenzar con:</p>



<pre class="wp-block-code"><code>while ( have_posts() ) : the_post();</code></pre>



<p class="wp-block-paragraph">y terminar con:</p>



<pre class="wp-block-preformatted">endwhile;</pre>



<div class="wp-block-image"><figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="1000" height="639" src="https://danisanchez.net/wp-content/uploads/2019/04/01.template-custom-post.jpg" alt="" class="wp-image-5361" srcset="https://danisanchez.net/wp-content/uploads/2019/04/01.template-custom-post.jpg 1000w, https://danisanchez.net/wp-content/uploads/2019/04/01.template-custom-post-300x192.jpg 300w, https://danisanchez.net/wp-content/uploads/2019/04/01.template-custom-post-768x491.jpg 768w" sizes="auto, (max-width: 1000px) 100vw, 1000px" /></figure></div>



<p class="wp-block-paragraph">Todo lo que va dentro del loop suelen ser las funciones que llaman al título de la entrada, al contenido y a la sección de comentarios.</p>



<p class="wp-block-paragraph">Para crear un fichero similar que cargue el contenido de nuestros custom posts, solo tenemos que crear un nuevo archivo al que llamaremos <strong>single-nombre_del_custom_post.php</strong>. En nuestro caso será <strong>single-vehiculos.php</strong>.</p>



<p class="wp-block-paragraph">Para este nuevo archivo podemos aprovechar todo el contenido del single.php original (para llamar a la cabecera, sidebars, footer, y menús del tema&#8230;) y quedarnos únicamente con el loop vacío, pues añadiremos nuestro propio código para cargar el custom post de Vehículos.</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="655" height="554" src="https://danisanchez.net/wp-content/uploads/2019/04/02.single-vehiculos.jpg" alt="" class="wp-image-5362" srcset="https://danisanchez.net/wp-content/uploads/2019/04/02.single-vehiculos.jpg 655w, https://danisanchez.net/wp-content/uploads/2019/04/02.single-vehiculos-300x254.jpg 300w" sizes="auto, (max-width: 655px) 100vw, 655px" /></figure></div>



<p class="wp-block-paragraph">Una vez creado el archivo <strong>single-vehiculos.php </strong>vamos a refrescar los enlaces permanentes de WordPress, para que este detecte que cada vez que accedamos a una URL del tipo mi-dominio.com/vehiculos/nombre-del-post, cargue la nueva plantilla en lugar de la original. Solo tenemos que ir a Ajustes de WordPress &#8211; Enlaces permanentes y Guardar cambios.</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="815" height="478" src="https://danisanchez.net/wp-content/uploads/2019/04/03.actualizar-enlaces-permanentes.jpg" alt="" class="wp-image-5363" srcset="https://danisanchez.net/wp-content/uploads/2019/04/03.actualizar-enlaces-permanentes.jpg 815w, https://danisanchez.net/wp-content/uploads/2019/04/03.actualizar-enlaces-permanentes-300x176.jpg 300w, https://danisanchez.net/wp-content/uploads/2019/04/03.actualizar-enlaces-permanentes-768x450.jpg 768w" sizes="auto, (max-width: 815px) 100vw, 815px" /></figure></div>



<p class="wp-block-paragraph">Si intentamos acceder a una entrada de tipo Vehículo, veremos que carga correctamente (la URL toma /vehiculos/ford-focus-1-8-tddi), pero el contenido está vacío. Es normal pues dentro del loop no hemos añadido nada de momento.</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="1000" height="599" src="https://danisanchez.net/wp-content/uploads/2019/04/04.template-vacio.jpg" alt="" class="wp-image-5364" srcset="https://danisanchez.net/wp-content/uploads/2019/04/04.template-vacio.jpg 1000w, https://danisanchez.net/wp-content/uploads/2019/04/04.template-vacio-300x180.jpg 300w, https://danisanchez.net/wp-content/uploads/2019/04/04.template-vacio-768x460.jpg 768w" sizes="auto, (max-width: 1000px) 100vw, 1000px" /></figure></div>



<p class="wp-block-paragraph">Para llamar al título del contenido, añadiremos la función <em>the_title()</em> dentro del loop:</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="385" height="174" src="https://danisanchez.net/wp-content/uploads/2019/04/05.llamar-titulo.jpg" alt="" class="wp-image-5365" srcset="https://danisanchez.net/wp-content/uploads/2019/04/05.llamar-titulo.jpg 385w, https://danisanchez.net/wp-content/uploads/2019/04/05.llamar-titulo-300x136.jpg 300w" sizes="auto, (max-width: 385px) 100vw, 385px" /></figure></div>



<p class="wp-block-paragraph">Y como resultado obtenedremos el título de la entrada:</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="1000" height="408" src="https://danisanchez.net/wp-content/uploads/2019/04/06.titulo-en-el-template.jpg" alt="" class="wp-image-5366" srcset="https://danisanchez.net/wp-content/uploads/2019/04/06.titulo-en-el-template.jpg 1000w, https://danisanchez.net/wp-content/uploads/2019/04/06.titulo-en-el-template-300x122.jpg 300w, https://danisanchez.net/wp-content/uploads/2019/04/06.titulo-en-el-template-768x313.jpg 768w" sizes="auto, (max-width: 1000px) 100vw, 1000px" /></figure></div>



<p class="wp-block-paragraph">Lo normal es que el título tenga un tamaño destacado, para ello la función <em>the_title()</em> permite definir que el contenido aparezca entre etiquetas HTML, por ejemplo un H2, declarándolo de este modo:</p>



<pre class="wp-block-code"><code><pre class="wp-block-syntaxhighlighter-code">the_title('&lt;h2>','&lt;/h2>');</pre></code></pre>



<p class="wp-block-paragraph">Y el resultado obtenido será:</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="379" height="242" src="https://danisanchez.net/wp-content/uploads/2019/04/07.titulo-en-el-template-h2.jpg" alt="" class="wp-image-5367" srcset="https://danisanchez.net/wp-content/uploads/2019/04/07.titulo-en-el-template-h2.jpg 379w, https://danisanchez.net/wp-content/uploads/2019/04/07.titulo-en-el-template-h2-300x192.jpg 300w" sizes="auto, (max-width: 379px) 100vw, 379px" /></figure></div>



<p class="wp-block-paragraph">También podríamos añadir la imagen destacada, con la función <em>the_post_thumbnail(), </em>declarándola a continuación del título, así como el contenido (procedente del editor de WordPress) con la función <em>the_content():</em></p>



<pre class="wp-block-code"><code><pre class="wp-block-syntaxhighlighter-code">// Start the loop.
while ( have_posts() ) :
    the_post();
    the_title('&lt;h2>','&lt;/h2>'); //Llama al título del post
    the_post_thumbnail(); //Llama a la imagen destacada del post
    the_content(); //Llama al contenido
// End of the loop.
endwhile;</pre></code></pre>



<p class="wp-block-paragraph">Esto nos dará como resultado:</p>



<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" src="https://danisanchez.net/wp-content/uploads/2019/04/08-template-con-titulo-imagen-contenido-1-1.jpg" alt="" class="wp-image-5370"/></figure></div>



<p class="wp-block-paragraph">Hay que tener en cuenta que la imagen destacada aparecerá con el tamaño del archivo original, o el que permita el contenedor (&lt;div&gt;) donde se encuentre. Podemos llamar a la imagen destacada con un tamaño específico siempre que este se haya declarado en el archivo de funciones del tema.</p>



<p class="wp-block-paragraph">Por ejemplo, si quisiéramos que la imagen destacada apareciera en el post con un ancho de 500px, tendríamos que definirlo en el archivo de funciones (function.php) del tema activo con:</p>



<pre class="wp-block-code"><code><pre class="wp-block-syntaxhighlighter-code">function tamano_miniaturas(){
    add_image_size('cabeceraPost', 500, false);
}
add_action('after_setup_theme', 'tamano_miniaturas');</pre></code></pre>



<p class="wp-block-paragraph">La función <strong>add_image_size()</strong>, recibe 4 parámetros, el identificador del tamaño, la anchura, la altura y el factor de recorte de proporción (true o false). En este caso solo hemos especificado la anchura, ya que desconocemos la proporción de la imagen y de fijar un alto fijo esta podría aparecer desproporcionada.</p>



<p class="wp-block-paragraph">Después tendríamos que llamar a la función <strong>the_post_thumbnail(&#8216;cabeceraPost&#8217;)</strong>, pasándole como parámetro el identificador del tamaño que hemos especificado en add_image_size().</p>



<p class="wp-block-paragraph">Pero esto son temas de diseño que no vamos a abordar en este post.</p>



<p class="wp-block-paragraph">Solo nos quedaría llamar a nuestros campos personalizados para mostrar el precio y matrícula del vehículo.</p>



<p class="wp-block-paragraph">Advances Custom Field dispone de 2 funciones principales para extraer la información de los campos personalizados:</p>



<ul class="wp-block-list"><li><strong>the_field(&#8216;identificador_del_campo&#8217;)</strong></li><li><strong>get_field(&#8216;identificador_del_campo&#8217;)</strong></li></ul>



<p class="wp-block-paragraph">La principal diferencia entre ellos es que <em>the_field()</em> escribe directamente los datos del campo en el lugar donde lo invoquemos, (viene pre-formateado). Y <em>get_field()</em> está pensado para extraer el valor del campo y almacenarlo en algún lugar, por ejemplo una variable. El uso de uno u otro dependerá de nuestras necesidades. Si solo necesitamos pintar el valor del campo en un div vacío, puede que nos interese hacerlo directamente con the_field(), pero si el dato va a ir dentro de una estructura HTML más compleja, como una tabla, es posible que el pre-formateo de the_title() interfiera y no se muestre correctamente, en casos así sería mejor usar el get_field() guardando el dato en una variable y pintar la variable con un echo. Así es como lo vamos a hacer en nuestro ejemplo:</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="518" height="360" src="https://danisanchez.net/wp-content/uploads/2019/04/09.llamada-a-campos-personalizados.jpg" alt="" class="wp-image-5373" srcset="https://danisanchez.net/wp-content/uploads/2019/04/09.llamada-a-campos-personalizados.jpg 518w, https://danisanchez.net/wp-content/uploads/2019/04/09.llamada-a-campos-personalizados-300x208.jpg 300w" sizes="auto, (max-width: 518px) 100vw, 518px" /></figure></div>



<p class="wp-block-paragraph">Definimos una variable $precio y le pasamos el valor del campo personalizado &#8216;precio&#8217; con un get_field()</p>



<pre class="wp-block-code"><code><pre class="wp-block-syntaxhighlighter-code">$precio = get_field('precio');</pre></code></pre>



<p class="wp-block-paragraph">Y lo mismo con el campo matrícula:</p>



<pre class="wp-block-code"><code><pre class="wp-block-syntaxhighlighter-code">$matricula = get_field('matricula');</pre></code></pre>



<p class="wp-block-paragraph">Después pintamos los campos con un echo y un poco de HTML:</p>



<pre class="wp-block-preformatted">echo "&lt;h3&gt;Precio: " . $precio . "€&lt;/h3&gt;";
echo "Matrícula: " . $matricula . "&lt;/h3&gt;";</pre>



<p class="wp-block-paragraph">El resultado obtenido será:</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="910" height="383" src="https://danisanchez.net/wp-content/uploads/2019/04/10.template-con-campos-personalizados.jpg" alt="" class="wp-image-5374" srcset="https://danisanchez.net/wp-content/uploads/2019/04/10.template-con-campos-personalizados.jpg 910w, https://danisanchez.net/wp-content/uploads/2019/04/10.template-con-campos-personalizados-300x126.jpg 300w, https://danisanchez.net/wp-content/uploads/2019/04/10.template-con-campos-personalizados-768x323.jpg 768w" sizes="auto, (max-width: 910px) 100vw, 910px" /></figure></div>



<p class="wp-block-paragraph">Si necesitamos formatear el precio con separadores de miles y decimales, podemos usar la función number_format() de PHP:</p>



<pre class="wp-block-code"><code><pre class="wp-block-syntaxhighlighter-code">echo "&lt;h3>Precio: " . number_format($precio, 2, ',', '.') . "€&lt;/h3>";</pre></code></pre>



<p class="wp-block-paragraph">A la función number_format() le pasamos la variable $precio, el número de decimales a mostrar, el separador de decimales &#8216;,&#8217; y el separador de miles &#8216;.&#8217; y tendremos como resultado:</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="205" height="76" src="https://danisanchez.net/wp-content/uploads/2019/04/11.mejorar-campo-precio.jpg" alt="" class="wp-image-5375"/></figure></div>



<p class="wp-block-paragraph">De esta forma formateamos el precio en el momento de pintarlo en el front-end mientras que en la base de datos se mantiene en formato numérico puro, pudiendo más adelante utilizarlo para ordenar vehículos por precio.</p>



<p class="wp-block-paragraph">En el siguient post veremos como crear una página archivo con los vehículos que ya tengamos guardados en la base de datos.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Taxonomías, para qué sirven y cómo crearlas (sin plugins)</title>
		<link>https://danisanchez.net/taxonomias-para-que-sirven-y-como-crearlas-sin-plugins/</link>
		
		<dc:creator><![CDATA[dani.sanchez]]></dc:creator>
		<pubDate>Mon, 08 Apr 2019 10:56:34 +0000</pubDate>
				<category><![CDATA[Publicaciones]]></category>
		<category><![CDATA[Tutoriales]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[desarrollo web]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[programación web]]></category>
		<category><![CDATA[publicaciones]]></category>
		<category><![CDATA[taxonomías]]></category>
		<category><![CDATA[tutoriales]]></category>
		<category><![CDATA[wordpress]]></category>
		<guid isPermaLink="false">https://www.gestionatuweb.net/?p=5320</guid>

					<description><![CDATA[Tras el último post en el que veíamos cómo crear custom posts, continuamos esta serie de artículos aprendiendo a generar nuestros propios contenidos en WordPress. Uno de los elementos más importantes son las taxonomías. Las taxonomías sirven para categorizar, organizar y filtrar nuestros contenidos de una forma mucho más concisa que utilizando el simple cajetín [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">Tras el <a href="https://danisanchez.net/crear-un-custom-post-en-wordpress-sin-plugins/" target="_blank" rel="noreferrer noopener">último post</a> en el que veíamos cómo crear custom posts, continuamos esta serie de artículos aprendiendo a generar nuestros propios contenidos en WordPress. Uno de los elementos más importantes son las <strong>taxonomías</strong>.</p>



<p class="wp-block-paragraph">Las taxonomías sirven para <em>categorizar, organizar y filtrar</em> nuestros contenidos de una forma mucho más concisa que utilizando el simple cajetín de categorías que WordPress incorpora por defecto. De hecho, tanto las categorías como las etiquetas de WordPress son en sí taxonomías. Veremos más adelante por qué.</p>



<p class="wp-block-paragraph">Continuando con el ejemplo del concesionario de vehículos, supongamos que necesitamos catalogar estos vehículos de diferentes formas. Por ejemplo, podríamos categorizarlos por tipo de vehículo: coche, camión, motocicleta&#8230;, pero también podríamos necesitar categorizarlo por el tipo de motor: diesel, gasolina, eléctrico&#8230;, por el número de puertas: 3, 4, 5&#8230;, por la marca, color, etc.</p>



<p class="wp-block-paragraph">En este caso, la categoría por defecto se nos quedaría corta, de ahí que necesitemos extender el número de «categorías» para definir correctamente el vehículo. Esa es la función principal de las taxonomías.</p>



<p class="wp-block-paragraph">Además, gracias a las taxonomías, podremos construir consultas personalizadas para mostrar únicamente las entradas que tengan marcadas esas taxonomías.</p>



<p class="wp-block-paragraph">Para declarar una taxonomía, utilizaremos como siempre, el archivo de funciones del tema activo (functions.php) o <a href="https://danisanchez.net/wordpress-crear-nuestro-propio-plugin-de-funciones/" target="_blank" rel="noreferrer noopener">nuestro propio plugin de funciones</a>. Podemos declarar todas las taxonomías que necesitemos utilizando la misma función.</p>



<h2 class="wp-block-heading">Declara una taxonomía</h2>



<pre class="wp-block-code"><code><pre class="wp-block-syntaxhighlighter-code">function mis_taxonomias(){
    //Tipo de Vehículo
    $labels = array(
     'name' => _x('Tipo de Vehículo', 'taxonomy general name', 'twentysixteen'),
     'singular_name' => _x('Tipo de Vehículo', 'taxonomy_general_name', 'twentysixteen'),
     'search_items' => __('Buscar Tipo de Vehículo', 'twentysixteen'),
     'all_items' => __('Todos los Tipos de Vehículos', 'twentysixteen'),
     'parent_item' => __('Padre Tipo de Vehículo', 'twentysixteen'),
     'parent_item_colon' => __('Padre Tipo de Vehículo', 'twentysixteen'),
     'edit_item' => __('Editar Tipo de Vehículo', 'twentysixteen'),
     'update_item' => __('Actualizar Tipo de Vehículo', 'twentysixteen'),
     'add_new_item' => __('Añadir Nuevo Vehículo', 'twentysixteen'),
     'new_item_name' => __('Nuevo Tipo de Vehículo', 'twentysixteen'),
     'menu_name' => __('Tipo de Vehículo', 'twentysixteen'),
    );
    $args = array(
     'hierarchical'  => true,
     'labels'  => $labels,
     'show_ui'  => true,
     'show_admin_column'     => true,
     'query_var'  => true,
     'rewrite'  => array('slug' => 'tipo_de_vehiculo'),
    );
    register_taxonomy('tipo-vehiculo', array('vehiculos'), $args);
}
add_action('init','mis_taxonomias');</pre></code></pre>



<p class="wp-block-paragraph">La función <strong>register_taxonomy() </strong>es la encargada de declarar nuestras taxonomías personalizadas.</p>



<p class="wp-block-paragraph">La declaración es bastante similar a declarar un nuevo custom post. Por un lado recibe las etiquetas (labels) para los textos que se mostrará en el panel de WordPress, y por otro los argumentos (args) que definen las caracteríticas y el comportamiento.</p>



<p class="wp-block-paragraph">Los argumentos más interesantes son:</p>



<ul class="wp-block-list"><li><strong>hierarchical:</strong> su estado puede ser true o false. Si es true, la taxonomía mostrará los elementos a modo de listado para seleccionarlos tal y como se hace con las <strong>Categorías</strong> de WordPress. Si está en false, la taxonoḿia se verá como un campo de texto, donde insertaremos manualmente el nombre de los elementos de la taxonomía (como las <strong>Etiquetas</strong> de WordPress).</li><li><strong>rewrite:</strong> Donde especificaremos el slug de la taxonomía, que nos permitirá usar en un nuevo template para obtener un listado de las entradas que incluyan dicha taxonomía.</li></ul>



<p class="wp-block-paragraph">Una vez declarada, esta taxonomía se incluirá directamente como submenú dentro del menú de Vehículos (nuestro custom posts):</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="664" height="258" src="https://danisanchez.net/wp-content/uploads/2019/04/01.taxonomias-01.jpg" alt="" class="wp-image-5323" srcset="https://danisanchez.net/wp-content/uploads/2019/04/01.taxonomias-01.jpg 664w, https://danisanchez.net/wp-content/uploads/2019/04/01.taxonomias-01-300x117.jpg 300w" sizes="auto, (max-width: 664px) 100vw, 664px" /></figure></div>



<p class="wp-block-paragraph">Accediendo a la taxonomía podremos añadir elementos:</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="1000" height="454" src="https://danisanchez.net/wp-content/uploads/2019/04/02.anadir-elementos-taxonomia.jpg" alt="" class="wp-image-5324" srcset="https://danisanchez.net/wp-content/uploads/2019/04/02.anadir-elementos-taxonomia.jpg 1000w, https://danisanchez.net/wp-content/uploads/2019/04/02.anadir-elementos-taxonomia-300x136.jpg 300w, https://danisanchez.net/wp-content/uploads/2019/04/02.anadir-elementos-taxonomia-768x349.jpg 768w" sizes="auto, (max-width: 1000px) 100vw, 1000px" /></figure></div>



<p class="wp-block-paragraph">Una vez creados los elementos de la taxomía, si añadimos un nuevo vehículo veremos el cajetín de la taxonomía, con su listado de elementos a modo de nueva categoría.</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="1000" height="463" src="https://danisanchez.net/wp-content/uploads/2019/04/03.vista-taxonomia-en-custom-post.jpg" alt="" class="wp-image-5326" srcset="https://danisanchez.net/wp-content/uploads/2019/04/03.vista-taxonomia-en-custom-post.jpg 1000w, https://danisanchez.net/wp-content/uploads/2019/04/03.vista-taxonomia-en-custom-post-300x139.jpg 300w, https://danisanchez.net/wp-content/uploads/2019/04/03.vista-taxonomia-en-custom-post-768x356.jpg 768w" sizes="auto, (max-width: 1000px) 100vw, 1000px" /></figure></div>



<p class="wp-block-paragraph">Aprovechando la misma funcion (mis_taxonomias()), vamos a añadir una nueva categoría pero de un estilo más «flexible», donde vamos a especificar los «extras» del vehículo: aire acondicionado, pintura metalizada, dirección asistida, navegador&#8230;). Para ello crearemos una taxonomía al estilo de <strong>Etiquetas</strong> de WordPress.</p>



<pre class="wp-block-code"><code><pre class="wp-block-syntaxhighlighter-code">//Extras del Vehículo
    $labels = array(
     'name' => _x('Extras', 'taxonomy general name', 'twentysixteen'),
     'singular_name' => _x('Extras', 'taxonomy_general_name', 'twentysixteen'),
     'search_items' => __('Buscar Extras', 'twentysixteen'),
     'all_items' => __('Todos los Extras', 'twentysixteen'),
     'parent_item' => __('Padre Extras', 'twentysixteen'),
     'parent_item_colon' => __('Padre Extras', 'twentysixteen'),
     'edit_item' => __('Editar Extras', 'twentysixteen'),
     'update_item' => __('Actualizar Extras', 'twentysixteen'),
     'add_new_item' => __('Añadir Extras', 'twentysixteen'),
     'new_item_name' => __('Nuevo Extras', 'twentysixteen'),
     'menu_name' => __('Extras', 'twentysixteen'),
    );
    $args = array(
     'hierarchical'  => false,
     'labels'  => $labels,
     'show_ui'          => true,
     'show_admin_column'     => true,
     'query_var'  => true,
     'rewrite'  => array('slug' => 'extras'),
    );
    register_taxonomy('extras', array('vehiculos'), $args);</pre></code></pre>



<p class="wp-block-paragraph">Para conseguir el aspecto de taxonomía a modo de etiquetas, solo tenemos que definir el parámetro <strong>&#8216;hierarchical&#8217;</strong> en false.</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="1000" height="601" src="https://danisanchez.net/wp-content/uploads/2019/04/04.vista-taxonomia-en-custom-post.jpg" alt="" class="wp-image-5328" srcset="https://danisanchez.net/wp-content/uploads/2019/04/04.vista-taxonomia-en-custom-post.jpg 1000w, https://danisanchez.net/wp-content/uploads/2019/04/04.vista-taxonomia-en-custom-post-300x180.jpg 300w, https://danisanchez.net/wp-content/uploads/2019/04/04.vista-taxonomia-en-custom-post-768x462.jpg 768w" sizes="auto, (max-width: 1000px) 100vw, 1000px" /></figure></div>



<p class="wp-block-paragraph">Ahora que sabemos cómo declarar nuevas taxonomías, crearemos algunas más que usaremos para hacer pruebas.</p>



<p class="wp-block-paragraph">En el siguiente post veremos cómo crear campos personalizados internos para nuestro custom post, como por ejemplo, un campo para el precio, otro para el año de fabricación, el kilometraje (si el vehículo es usado), etc.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Crear un custom post en WordPress (sin plugins)</title>
		<link>https://danisanchez.net/crear-un-custom-post-en-wordpress-sin-plugins/</link>
					<comments>https://danisanchez.net/crear-un-custom-post-en-wordpress-sin-plugins/#comments</comments>
		
		<dc:creator><![CDATA[dani.sanchez]]></dc:creator>
		<pubDate>Fri, 05 Apr 2019 08:09:47 +0000</pubDate>
				<category><![CDATA[Publicaciones]]></category>
		<category><![CDATA[Tutoriales]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[custom post]]></category>
		<category><![CDATA[desarrollo web]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[programación web]]></category>
		<category><![CDATA[publicaciones]]></category>
		<category><![CDATA[tutoriales]]></category>
		<category><![CDATA[wordpress]]></category>
		<guid isPermaLink="false">https://www.gestionatuweb.net/?p=5307</guid>

					<description><![CDATA[En WordPress no estamos limitados a crear páginas internas y entradas de noticias, podemos crear nuestros propios contenidos a través de los llamados «custom posts«, es aquí donde nos damos cuenta del verdadero potencial de WordPress. Imaginemos que estamos desarrollando la web de un concesionario de vehículos y queremos publicarlos de forma que cada vehículo [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">En WordPress no estamos limitados a crear páginas internas y entradas de noticias, podemos crear nuestros propios contenidos a través de los llamados «<em>custom posts</em>«, es aquí donde nos damos cuenta del verdadero potencial de WordPress.</p>



<p class="wp-block-paragraph">Imaginemos que estamos desarrollando la web de un concesionario de vehículos y queremos publicarlos de forma que cada vehículo se trate como una entrada individual, y así poder categorizarlos, añadirles etiquetas, realizar búsquedas, etc.</p>



<p class="wp-block-paragraph">Los <em>custom post</em> pueden ser declarados en el archivo de funciones del tema activo (functions.php) o en nuestro propio <a href="https://danisanchez.net/wordpress-crear-nuestro-propio-plugin-de-funciones/" target="_blank" rel="noreferrer noopener">plugin de funciones</a>.</p>



<h2 class="wp-block-heading">Declarar un custom post</h2>



<p class="wp-block-paragraph">La estructura básica para añadir el nuevo custom post sería:</p>



<pre class="wp-block-code"><code><pre class="wp-block-syntaxhighlighter-code">&lt;?php
//Custom Post Vehículos
function post_Vehiculos(){
 $labels = array(
 'name'               => _x('Vehículos', 'twentysixteen'),
 'singular_name'      => _x('Vehículo', 'post type singular name', 'twentysixteen'),
 'menu_name'          => _x('Vehículos', 'admin menu', 'gestiona-inmobiliaria'),
 'name_admin_bar'     => _x('Vehículos', 'add new on admin bar', 'twentysixteen'),
 'add_new'            => _x('Añadir Vehículo', 'book', 'twentysixteen'),
 'add_new_item'       => __('Añadir Nuevo Vehículo', 'twentysixteen'),
 'new_item'           => __('Nuevos Vehículos', 'twentysixteen'),
 'edit_item'          => __('Editar Vehículo', 'twentysixteen'),
 'view_item'          => __('Ver Vehículo', 'twentysixteen'),
 'all_items'          => __('Todos los Vehículos', 'twentysixteen'),
 'search_items'       => __('Buscar Vehículos', 'twentysixteen'),
 'parent_item_colon'  => __('Parent Vehículos:', 'twentysixteen'),
 'not_found'          => __('No se han encontrado Vehículos', 'twentysixteen'),
 'not_found_in_trash' => __('No se han encontrado Vehículos en la papelera', 'twentysixteen')
 );
 $args = array(
     'labels'             => $labels,
     'description'        => __('Description.', 'twentysixteen'),
     'public'             => true,
     'publicly_queryable' => true,
     'show_ui'            => true,
     'show_in_menu'       => true,
     'query_var'          => true,
     'rewrite'            => array('slug' => 'vehiculos'),
     'capability_type'    => 'post',
     'has_archive'        => true,
     'hierarchical'       => false,
     'menu_position'      => 6,
     'supports'           => array('title', 'editor', 'author', 'thumbnail'),
 );
 register_post_type('vehiculos', $args);
}
add_action('init', 'post_Vehiculos');
?></pre></code></pre>



<p class="wp-block-paragraph">La función contiene 2 elementos principales, las etiquetas ($labels) y los argumentos ($args).</p>



<p class="wp-block-paragraph">Las etiquetas hacen referencia a los textos que muestra WordPress acerca del custom post, tales como el nombre en singular, en plural, cómo se muestra en el menú, el texto para añadir uno nuevo, para editarlo, etc.</p>



<p class="wp-block-paragraph">Los argumentos tratan cómo se comportará el custom post, algunos parámetros interesantes son:</p>



<ul class="wp-block-list"><li><strong>rewrite</strong>: el slug que generará nuestro custom post, ejemplo: www.tudominio.com/<strong>vehiculos</strong>/url_del_post. Es importante escoger uno apropiado de cara al SEO.</li><li><strong>capability_type:</strong> especifica si el custom post se va a comportar como una página interna (para información fija) o como un post (entrada). Normalmente pondremos tipo post.</li><li><strong>has_archive: </strong>define si el custom post va a tener su propio archivo-listado de posts.</li><li><strong>menu_position:</strong> Controla en qué posición del menú aparecerá el nuevo custom post, por ejemplo, antes o después de las Entradas normales. Podemos jugar con el número hasta dejarlo donde queremos.</li><li><strong>supports</strong>: Define los elementos que podremos utilizar dentro del custom post, por ejemplo un campo para el título, el editor de WordPress, el autor y la imagen destacada (thumbnail).</li></ul>



<p class="wp-block-paragraph">Una vez declarado estará disponible en nuestro menú:</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="1000" height="285" src="https://danisanchez.net/wp-content/uploads/2019/04/custom-post.jpg" alt="" class="wp-image-5312" srcset="https://danisanchez.net/wp-content/uploads/2019/04/custom-post.jpg 1000w, https://danisanchez.net/wp-content/uploads/2019/04/custom-post-300x86.jpg 300w, https://danisanchez.net/wp-content/uploads/2019/04/custom-post-768x219.jpg 768w" sizes="auto, (max-width: 1000px) 100vw, 1000px" /></figure></div>



<p class="wp-block-paragraph">Si añadimos un nuevo vehículo, veremos una pantalla de edición muy similar a las entradas, con su campo para el título, el editor de WordPress, la selección del autor y la imagen destacada:</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="1000" height="557" src="https://danisanchez.net/wp-content/uploads/2019/04/custom-post-2.jpg" alt="" class="wp-image-5313" srcset="https://danisanchez.net/wp-content/uploads/2019/04/custom-post-2.jpg 1000w, https://danisanchez.net/wp-content/uploads/2019/04/custom-post-2-300x167.jpg 300w, https://danisanchez.net/wp-content/uploads/2019/04/custom-post-2-768x428.jpg 768w" sizes="auto, (max-width: 1000px) 100vw, 1000px" /></figure></div>



<p class="wp-block-paragraph">Sin embargo esto podríamos enriquecerlo mucho más, añadiendo categorías, taxonomías y campos personalizados que desatarán realmente todo el potencial de los custom post y que harán que podamos realizar prácticamente cualquier tipo de web.</p>



<p class="wp-block-paragraph">Veremos cómo integrarlos en siguientes posts.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://danisanchez.net/crear-un-custom-post-en-wordpress-sin-plugins/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Crear un select con buscador integrado, gracias a select2</title>
		<link>https://danisanchez.net/crear-un-select-con-buscador-integrado-gracias-a-select2/</link>
					<comments>https://danisanchez.net/crear-un-select-con-buscador-integrado-gracias-a-select2/#comments</comments>
		
		<dc:creator><![CDATA[dani.sanchez]]></dc:creator>
		<pubDate>Fri, 22 Mar 2019 09:16:13 +0000</pubDate>
				<category><![CDATA[Publicaciones]]></category>
		<category><![CDATA[Tutoriales]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[desarrollo web]]></category>
		<category><![CDATA[formularios]]></category>
		<category><![CDATA[programación web]]></category>
		<category><![CDATA[publicaciones]]></category>
		<category><![CDATA[select2]]></category>
		<category><![CDATA[tutoriales]]></category>
		<category><![CDATA[wordpress]]></category>
		<guid isPermaLink="false">https://www.gestionatuweb.net/?p=5183</guid>

					<description><![CDATA[Cuántas veces hemos generado formularios con campos selects interminables (por ejemplo un listado de clientes, de países, de productos&#8230;). Navegar a través de un select de varios cientos de elementos es algo tedioso que seguramente tu cliente o empresa te pedirá solucionar. Lo más óptimo sería ofrecer un campo de búsqueda dentro del propio select [&#8230;]]]></description>
										<content:encoded><![CDATA[
<iframe loading="lazy" width="100%" height="315" src="https://www.youtube-nocookie.com/embed/ptZV3Xekmc0" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>



<div style="height:25px" aria-hidden="true" class="wp-block-spacer"></div>



<p class="wp-block-paragraph">Cuántas veces hemos generado formularios con campos selects interminables (por ejemplo un listado de clientes, de países, de productos&#8230;). Navegar a través de un select de varios cientos de elementos es algo tedioso que seguramente tu cliente o empresa te pedirá solucionar.</p>



<p class="wp-block-paragraph">Lo más óptimo sería ofrecer un campo de búsqueda dentro del propio select aprovechando jQuery y algo de CSS, lo que nos tocaría unas cuantas horas de investigar y programar.</p>



<p class="wp-block-paragraph">Afortunadamente existe <a href="https://select2.org/" target="_blank" rel="noreferrer noopener" aria-label="Select2 (opens in a new tab)">Select2</a>, una librería pensada precisamente para esto, insertar un campo de búsqueda dentro del campo select que deseemos y que además sea sencillo de implementar.</p>



<h2 class="wp-block-heading">Instalación de select2</h2>



<p class="wp-block-paragraph">Para empezar vamos a llamar a los dos archivos (css y js) necesarios para ejecutar el script y que tendrán que llamarse dentro del &lt;head&gt;&lt;/head&gt; de nuestra página.<code><br></code></p>



<pre class="wp-block-code"><code>&lt;link href="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/css/select2.min.css" rel="stylesheet"/&gt;

&lt;script src="https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/js/select2.min.js"&gt;&lt;/script&gt;</code></pre>



<p class="wp-block-paragraph">Para WordPress tendremos que integrarlos a través de una función que podemos llamar en nuestro archivo de funciones (functions.php):</p>



<pre class="wp-block-code"><code>function buscador_en_select(){
    wp_enqueue_style('estilos-select', 'https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/css/select2.min.css', array(),'1.0');
    wp_enqueue_script('jquery'); 
    wp_enqueue_script('script-select', 'https://cdnjs.cloudflare.com/ajax/libs/select2/4.0.6-rc.0/js/select2.min.js', array('jquery'), '1.0');
    wp_enqueue_script('mi-script', get_template_directory_uri().'/js/mi-script.js', array('script-select'),'1.0');
}
add_action('wp_enqueue_scripts', 'buscador_en_select');</code></pre>



<p class="wp-block-paragraph">Como véis, hemos llamado también a jQuery, por si no está ya implementado en el tema y además hemos llamado a mi-script, que es un archivo que crearemos y subiremos al directorio del tema activo en la carpeta js (la crearemos si no existe).</p>



<h2 class="wp-block-heading">Mi Script</h2>



<p class="wp-block-paragraph">Para integrar select2 crearemos un pequeño script en un archivo al que llamaremos mi-script.js y que guardaremos en la ruta /wp-content/themes/tema-activo/js/mi-script.js.</p>



<p class="wp-block-paragraph">En él insertaremos el siguiente código:</p>



<pre class="wp-block-code"><code>jQuery(document).ready(function($){
    $(document).ready(function() {
        $('.mi-selector').select2();
    });
});</code></pre>



<p class="wp-block-paragraph">La línea $(&#8216;mi-selector&#8217;).select2() indica que a todos los select que especifiquemos con la clase &#8216;mi-selector&#8217;, se les aplicará la funcionalidad de integrar un buscador.</p>



<p class="wp-block-paragraph">Por ejemplo:</p>



<pre class="wp-block-code"><code>&lt;select class='mi-selector' name='marcas'&gt;
    &lt;option value=''&gt;Seleccionar una marca&lt;/option&gt;
    &lt;option value='audi'&gt;Audi&lt;/option&gt;
    &lt;option value='bmw'&gt;BMW&lt;/option&gt;
    &lt;option value='citroen'&gt;Citroen&lt;/option&gt;
    &lt;option value='fiat'&gt;Fiat&lt;/option&gt;
    &lt;option value='ford'&gt;Ford&lt;/option&gt;
    &lt;option value='honda'&gt;Honda&lt;/option&gt;
    &lt;option value='hyundai'&gt;Hyundai&lt;/option&gt;
    &lt;option value='kia'&gt;Kia&lt;/option&gt;
    &lt;option value='mazda'&gt;Mazda&lt;/option&gt;
&lt;/select&gt;</code></pre>



<p class="wp-block-paragraph">Se vería así:</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="423" height="304" src="https://danisanchez.net/wp-content/uploads/2019/03/captura-select2-2-1-1.jpg" alt="" class="wp-image-5201" srcset="https://danisanchez.net/wp-content/uploads/2019/03/captura-select2-2-1-1.jpg 423w, https://danisanchez.net/wp-content/uploads/2019/03/captura-select2-2-1-1-300x216.jpg 300w" sizes="auto, (max-width: 423px) 100vw, 423px" /></figure></div>



<p class="wp-block-paragraph">También funciona perfecto con <strong>campos de selección múltiple</strong>, solo tenemos que especificarlo en el select, nombrándolo con corchetes (array) y especificando:</p>



<pre class="wp-block-code"><code><pre class="wp-block-syntaxhighlighter-code">multiple="multiple"</pre></code></pre>



<pre class="wp-block-code"><code>&lt;select class='mi-selector' name='marcas&#91;]' multiple='multiple'&gt;</code></pre>



<p class="wp-block-paragraph">Quedando así:</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="355" height="403" src="https://danisanchez.net/wp-content/uploads/2019/03/select-multiple.jpg" alt="" class="wp-image-5200" srcset="https://danisanchez.net/wp-content/uploads/2019/03/select-multiple.jpg 355w, https://danisanchez.net/wp-content/uploads/2019/03/select-multiple-264x300.jpg 264w" sizes="auto, (max-width: 355px) 100vw, 355px" /></figure></div>



<p class="wp-block-paragraph">Como véis, muy sencillo de implementar y muy práctico. Seguro que nos sacará de más de un apuro.</p>



<p class="wp-block-paragraph">Si te ha gustado, compártelo para que más gente pueda aprovecharlo. Nos vemos en el siguiente post <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
]]></content:encoded>
					
					<wfw:commentRss>https://danisanchez.net/crear-un-select-con-buscador-integrado-gracias-a-select2/feed/</wfw:commentRss>
			<slash:comments>13</slash:comments>
		
		
			</item>
		<item>
		<title>Añadir un formulario de sesión de WordPress en cualquier página o widget (sin plugins)</title>
		<link>https://danisanchez.net/anadir-un-formulario-de-sesion-de-wordpress-en-cualquier-pagina-o-widget-sin-plugins/</link>
		
		<dc:creator><![CDATA[dani.sanchez]]></dc:creator>
		<pubDate>Mon, 31 Dec 2018 12:06:29 +0000</pubDate>
				<category><![CDATA[Publicaciones]]></category>
		<category><![CDATA[Tutoriales]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[desarrollo web]]></category>
		<category><![CDATA[formularios]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[programación web]]></category>
		<category><![CDATA[publicaciones]]></category>
		<category><![CDATA[tutoriales]]></category>
		<category><![CDATA[wordpress]]></category>
		<guid isPermaLink="false">https://www.gestionatuweb.net/?p=4459</guid>

					<description><![CDATA[A menudo puede ser interesante insertar un formulario de inicio de sesión en alguna página interna o zona de widgets de nuestra plantilla. Para crear el formulario de inicio de sesión, definiremos la función en el archivo de funciones del tema activo (functions.php) o en nuestro propio plugin de funciones. Después vamos a poder llamar [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">A menudo puede ser interesante insertar un formulario de inicio de sesión en alguna página interna o zona de widgets de nuestra plantilla.</p>



<p class="wp-block-paragraph">Para crear el formulario de inicio de sesión, definiremos la función en el archivo de funciones del tema activo (functions.php) o en nuestro propio plugin de funciones. Después vamos a poder llamar a nuestro formulario a través de un simple <em>shortcode.</em></p>



<p class="wp-block-paragraph">Vamos a comenzar, definiendo la función que construirá el formulario de sesión:</p>



<pre class="wp-block-code"><code><pre class="wp-block-syntaxhighlighter-code">//Formulario inicio de sesión
  function formInicioSesion($atts){
    //Argumentos
    $args = array(
      'echo' => true,
      'redirect' => ( is_ssl() ? 'https://' : 'http://' ) . $_SERVER&#91;'HTTP_HOST'] . $_SERVER&#91;'REQUEST_URI'],
      'form_id' => 'loginform',
      'label_username' => __( 'Username' ),
      'label_password' => __( 'Password' ),
      'label_remember' => __( 'Remember Me' ),
      'label_log_in' => __( 'Log In' ),
      'id_username' => 'user_login',
      'id_password' => 'user_pass',
      'id_remember' => 'rememberme',
      'id_submit' => 'wp-submit',
      'remember' => true,
      'value_username' => '',
      'value_remember' => false
    );
    if(is_user_logged_in()){
      $current_user = wp_get_current_user();
      echo "&lt;section class='widget_text widget widget_custom_html'>";
      echo "&lt;p>&lt;h3>SESIÓN INICIADA&lt;/h3>&lt;/p>";
      echo "Bienvenido/a " . $current_user->display_name . "!";
    ?>
      &lt;p>&lt;a href="&lt;?php echo wp_logout_url(get_permalink()); ?>">Cerrar sesión&lt;/a>&lt;/p>
      &lt;/section>
    &lt;?php
    }
    else{
      echo "&lt;section class='widget_text widget widget_custom_html'>";
      echo "&lt;p>&lt;h3>ACCESO CLIENTES&lt;/h3>&lt;/p>";
      wp_login_form($args);
      echo "&lt;/section>";
    }
  }
  add_shortcode('form-sesion', 'formInicioSesion');</pre></code></pre>



<p class="wp-block-paragraph">Puedes copiar y pegar directamente este código, pero antes vamos a ver un poco en qué consiste.</p>



<p class="wp-block-paragraph">El formulario de sesión lo controla una función interna de WordPress llamada <strong><em>wp_login_form()</em></strong>, a esta función le podemos pasar una serie de argumentos que definimos anteriormente en el array<strong><em> $args</em></strong>.</p>



<pre class="wp-block-code"><code><pre class="wp-block-syntaxhighlighter-code">//Argumentos
    $args = array(
      'echo' => true,
      'redirect' => ( is_ssl() ? 'https://' : 'http://' ) . $_SERVER&#91;'HTTP_HOST'] . $_SERVER&#91;'REQUEST_URI'],
      'form_id' => 'loginform',
      'label_username' => __( 'Username' ),
      'label_password' => __( 'Password' ),
      'label_remember' => __( 'Remember Me' ),
      'label_log_in' => __( 'Log In' ),
      'id_username' => 'user_login',
      'id_password' => 'user_pass',
      'id_remember' => 'rememberme',
      'id_submit' => 'wp-submit',
      'remember' => true,
      'value_username' => '',
      'value_remember' => false
    );</pre></code></pre>



<p class="wp-block-paragraph">Algunos de estos argumentos son:</p>



<ul class="wp-block-list"><li>redirect: que redirige a https si se encuentra el SSL habilitado (certificado de seguridad instalado en el servidor).</li><li>label_username: que pinta el campo de nombre de usuario.</li><li>label_password: que pinta el campo de contraseña.</li><li>label_remember: que habilita el checkbox para recordar al usuario en el futuro.</li></ul>



<p class="wp-block-paragraph">Los demás argumentos asocian los datos introducidos en el formulario con las variables internas de WordPress para hacer las comprobaciones de usuario y contraseña.</p>



<p class="wp-block-paragraph">Después de definir los argumentos pasamos a realizar una comprobación:</p>



<pre class="wp-block-preformatted">if(is_user_logged_in()){</pre>



<p class="wp-block-paragraph">Si el usuario ya tiene una sesión iniciada, en lugar de mostrar el formulario de sesión, mostraremos un pequeño texto de bienvenida:</p>



<pre class="wp-block-code"><code><pre class="wp-block-syntaxhighlighter-code">$current_user = wp_get_current_user();
echo "&lt;section class='widget_text widget widget_custom_html'>";
echo "&lt;p>&lt;h3>SESIÓN INICIADA&lt;/h3>&lt;/p>";
echo "Bienvenido/a " . $current_user->display_name . "!";</pre></code></pre>



<p class="wp-block-paragraph">Para obtener el nombre del usuario, pasamos a <strong><em>$current_user</em></strong> todos los atributos del usuario activo, gracias a la función <strong><em>wp_get_current_user()</em></strong>.</p>



<p class="wp-block-paragraph">Y lo mostramos con <em><strong>$current_user-&gt;display_name</strong></em>.</p>



<p class="wp-block-paragraph">Además, añadimos un pequeño enlace para cerrar sesión, gracias a la función <strong><em>wp_logout_url()</em></strong>, donde se le puede pasar como parámetro la dirección hacia la que redirigir tras cerrar la sesión. En nuestro ejemplo hemos usado <strong><em>the_permalink()</em></strong>, para continuar en la misma página donde nos encontrábamos.</p>



<pre class="wp-block-code"><code><pre class="wp-block-syntaxhighlighter-code">&lt;p>&lt;a href="&lt;?php echo wp_logout_url(get_permalink()); ?>">Cerrar sesión&lt;/a>&lt;/p></pre></code></pre>



<p class="wp-block-paragraph">Ahora pasamos a la segunda parte de la condición:</p>



<p class="wp-block-paragraph">Si el usuario no tienen sesión iniciada, mostramos el formulario de sesión con <strong><em>wp_login_form($args)</em></strong>, pasándole como parámetros los argumentos definidos al inicio.</p>



<pre class="wp-block-code"><code><pre class="wp-block-syntaxhighlighter-code">}else{
   echo "&lt;section class='widget_text widget widget_custom_html'>";
   echo "&lt;p>&lt;h3>ACCESO CLIENTES&lt;/h3>&lt;/p>";
   wp_login_form($args);
   echo "&lt;/section>";
}</pre></code></pre>



<p class="wp-block-paragraph">Finalmente creamos el <em>shortcode</em> asociado a la función que hemos terminado:</p>



<pre class="wp-block-code"><code><pre class="wp-block-syntaxhighlighter-code">add_shortcode('form-sesion', 'formInicioSesion');</pre></code></pre>



<p class="wp-block-paragraph">Ahora solamente tenemos que llamar al <em>shortcode</em> en el lugar donde queramos mostrar el formulario, que puede ser en el contenido de una página, en una entrada, o en un simple widget de texto, escribiendo simplemente:</p>


<p>[form-sesion]</p>



<div class="wp-block-image"><figure class="aligncenter size-medium"><img loading="lazy" decoding="async" width="300" height="222" src="https://danisanchez.net/wp-content/uploads/2018/12/captura-form-sesion-300x222.jpg" alt="" class="wp-image-4461" srcset="https://danisanchez.net/wp-content/uploads/2018/12/captura-form-sesion-300x222.jpg 300w, https://danisanchez.net/wp-content/uploads/2018/12/captura-form-sesion-768x568.jpg 768w, https://danisanchez.net/wp-content/uploads/2018/12/captura-form-sesion.jpg 964w" sizes="auto, (max-width: 300px) 100vw, 300px" /></figure></div>



<p class="wp-block-paragraph">Espero que te haya sido de utilidad este último artículo del año 2018.</p>



<p class="wp-block-paragraph">Desde gestionatuweb.net, te deseo unas felices fiestas y próspero año 2019. Nos vemos en siguientes posts!</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Datepicker: Integración y configuración en WordPress</title>
		<link>https://danisanchez.net/datepicker-integracion-y-configuracion-en-wordpress/</link>
					<comments>https://danisanchez.net/datepicker-integracion-y-configuracion-en-wordpress/#comments</comments>
		
		<dc:creator><![CDATA[dani.sanchez]]></dc:creator>
		<pubDate>Mon, 10 Dec 2018 19:28:00 +0000</pubDate>
				<category><![CDATA[Publicaciones]]></category>
		<category><![CDATA[Tutoriales]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[datepicker]]></category>
		<category><![CDATA[desarrollo web]]></category>
		<category><![CDATA[formularios]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[programación web]]></category>
		<category><![CDATA[publicaciones]]></category>
		<category><![CDATA[tutoriales]]></category>
		<category><![CDATA[wordpress]]></category>
		<guid isPermaLink="false">https://www.gestionatuweb.net/?p=4427</guid>

					<description><![CDATA[Artículo en vídeo Datepicker es un calendario basado en JQuery integrado en un campo de formulario, con la finalidad de proporcionar al usuario un método cómodo y sencillo de insertar una fecha. Cuando a un usuario se le pide insertar una fecha en un formulario web, si este no implementa unas reglas básicas o indicaciones [&#8230;]]]></description>
										<content:encoded><![CDATA[
<h2 class="wp-block-heading">Artículo en vídeo</h2>



<iframe loading="lazy" width="100%" height="315" src="https://www.youtube-nocookie.com/embed/hXU5Hqn2Ye0" frameborder="0" allow="accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture" allowfullscreen=""></iframe>



<div style="height:25px" aria-hidden="true" class="wp-block-spacer"></div>



<p class="wp-block-paragraph"><br>Datepicker es un calendario basado en JQuery integrado en un campo de formulario, con la finalidad de proporcionar al usuario un método cómodo y sencillo de insertar una fecha.</p>



<p class="wp-block-paragraph">Cuando a un usuario se le pide insertar una fecha en un formulario web, si este no implementa unas reglas básicas o indicaciones claras, el usuario puede verse un poco perdido y no saber de qué forma insertarla:</p>



<p class="wp-block-paragraph"><em>¿Pongo el mes antes que el día?, ¿escribo el mes en números o letras?, ¿el año lo pongo con 2 o 4 cifras?, ¿separo las partes con guiones (-) o diagonales (/)?</em></p>



<p class="wp-block-paragraph">Esto cobra aún más importancia si la fecha se va a guardar en una base de datos que espera que llegue de una forma concreta.</p>



<p class="wp-block-paragraph">Para ello se implementaron herramientas como Datepicker, para que a la hora de insertar una fecha se desplegase un cómodo calendario en el que el usuario seleccionase cómodamente el mes, día y año sin errores, y todo se enviase a la base de datos debidamente procesado.</p>



<p class="wp-block-paragraph">Actualmente, los navegadores web ya incorporan campos de tipo fecha <em>&lt;input type=»date»/&gt;</em>, como puedes ver en el siguiente campo:</p>



<p class="wp-block-paragraph"><strong>Selecciona una fecha:</strong> </p>



<p class="wp-block-paragraph">Cada navegador tiene su particular calendario, que como base, ayuda a que el usuario inserte una fecha correctamente, aunque de cara a funcionalidades más avanzadas están muy limitados.</p>



<p class="wp-block-paragraph">Por ejemplo, no podemos enlazar dos campos de tipo fecha para que se comuniquen entre sí. Imagina que quieres incorporar un sistema de reserva de apartamentos en tu web, y quieres que cuando el usuario inserte la fecha de entrada, automáticamente la fecha de salida parta del día siguiente a la fecha de entrada, o que no se pueda escoger como fecha de salida, una fecha anterior a la de entrada. Con los calendarios basícos integrados por los navegadores actuales esto no es posible.</p>



<p class="wp-block-paragraph"><strong>Pero con Datepicker si.</strong></p>



<p class="wp-block-paragraph">Para todo lo que requiera de una avanzada programación de fechas, Datepicker sigue siendo una excelente herramienta, y en este post vamos a ver cómo integrarlo en WordPress y cómo hacer las configuraciones más útiles dentro de cualquier sistema de reservas.</p>



<h2 class="wp-block-heading">1. Descargar Datepicker</h2>



<p class="wp-block-paragraph">El primer paso es acudir a la web de <a href="https://jqueryui.com/download/" target="_blank" rel="noreferrer noopener">descarga de Datepicker</a> y descargar la última versión estable, que en el momento de escribir este post es la 1.12.1.</p>



<p class="wp-block-paragraph">Tras descomprimir el ZIP, los archivos que nos interesa son:</p>



<ul class="wp-block-list"><li>jquery-ui.css</li><li>jquery-ui.structure.css</li><li>jquery-ui.theme.css</li><li>jquery-ui.js</li><li><strong>Además, crearemos un archivo .js para nuestras propias funciones JavasScript, al que llamaremos funciones.js.</strong></li></ul>



<p class="wp-block-paragraph">Y la carpeta images que tendremos que subir al mismo directorio que los archivos CSS.</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="688" height="529" src="https://danisanchez.net/wp-content/uploads/2018/12/01-archivos-datepicker.jpeg" alt="" class="wp-image-4432" srcset="https://danisanchez.net/wp-content/uploads/2018/12/01-archivos-datepicker.jpeg 688w, https://danisanchez.net/wp-content/uploads/2018/12/01-archivos-datepicker-300x231.jpeg 300w" sizes="auto, (max-width: 688px) 100vw, 688px" /></figure></div>



<p class="wp-block-paragraph">Mi recomendación es subirlos a la misma carpeta donde se encuentra el tema activo de WordPress, es decir /wp-content/themes/tema_activo/</p>



<p class="wp-block-paragraph">Y dentro crear, si no existen, dos subdirectorios, css y js.</p>



<p class="wp-block-paragraph">/wp-content/themes/tema_activo<strong>/css</strong>/ donde subiremos los archivos CSS y la carpeta images de Datepicker.</p>



<p class="wp-block-paragraph">/wp-content/themes/tema_activo<strong>/js</strong>/ donde subiremos el archivo .js de Datepicker y nuestro archivo funciones.js.</p>



<p class="wp-block-paragraph">De tal forma que la estructura de archivos de Datepicker quede así en nuestro proyecto:</p>



<ul class="wp-block-list"><li>wp-content/themes/tema_activo/css/jquery-ui.css</li><li>wp-content/themes/tema_activo/css/jquery-ui-theme.css</li><li>wp-content/themes/tema_activo/css/jquery-ui.structure.css</li><li>wp-content/themes/tema_activo/css/images/</li><li>wp-content/themes/tema_activo/js/jquery-ui.js</li><li>wp-content/themes/tema_activo/js/funciones.js</li></ul>



<h2 class="wp-block-heading">2. Declarar los archivos de Datepicker en WordPress</h2>



<p class="wp-block-paragraph">Una vez subidos todos los archivos, necesitamos declararlos en WordPress para que este los reconozca. Lo normal es hacerlo dentro del archivo de funciones (functions.php) del tema activo, pero si es un tema que se actualiza con frecuencia, también podemos <a href="https://danisanchez.net/wordpress-crear-nuestro-propio-plugin-de-funciones/" target="_blank" rel="noreferrer noopener">crear nuestro propio plugin de funciones</a> y declararlo ahí de la misma forma:</p>



<pre class="wp-block-code"><code>&lt;?php
function js_calendarios(){
   wp_enqueue_script('jquery');
   wp_enqueue_style('calendario-css', get_template_directory_uri().'/css/jquery-ui.css', array(), '1.0');
   wp_enqueue_style('calendario-css-2', get_template_directory_uri().'/css/jquery-ui.theme.css', array(), '1.0');
   wp_enqueue_style('calendario-css-3', get_template_directory_uri().'/css/jquery-ui.structure.css', array(), '1.0');
   wp_enqueue_script('calendario-js', get_template_directory_uri().'/js/jquery-ui.js', array('jquery'), '1.0');
   wp_enqueue_script('funciones-js', get_template_directory_uri().'/js/funciones.js', array('jquery'), '1.0');
}
add_action('wp_enqueue_scripts', 'js_calendarios');
?&gt;</code></pre>



<h2 class="wp-block-heading">3. Configuraciones básicas de Datepicker</h2>



<p class="wp-block-paragraph">Para personalizar nuestro calendario, nos vamos a dirigir a nuestro archivo <strong>funciones.js </strong>y escribimos:</p>



<pre class="wp-block-code"><code>$ = jQuery.noConflict();
$(document).ready(function(){
    $(function(){
        $("#datepicker1").datepicker();
    });
});</code></pre>



<p class="wp-block-paragraph">El identificador #datepicker1 es el que tenemos que usar en el campo input donde queremos que aparezca el calendario, por ejemplo:</p>



<pre class="wp-block-code"><code>&lt;input type="text" name="fecha_entrada" id="datepicker1" placeholder="Fecha de entrada" /&gt;</code></pre>



<p class="wp-block-paragraph">Imprimiría:</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="612" height="453" src="https://danisanchez.net/wp-content/uploads/2018/12/datepicker-imagen.jpeg" alt="" class="wp-image-4435" srcset="https://danisanchez.net/wp-content/uploads/2018/12/datepicker-imagen.jpeg 612w, https://danisanchez.net/wp-content/uploads/2018/12/datepicker-imagen-300x222.jpeg 300w" sizes="auto, (max-width: 612px) 100vw, 612px" /></figure></div>



<p class="wp-block-paragraph">Hasta aquí no difiere mucho de la funcionalidad del calendario integrado por los propios navegadores, además por defecto está inglés, tanto las cadenas de texto como el hecho de que la semana comienza en Domingo.</p>



<p class="wp-block-paragraph">Vamos a comenzar definiendo las etiquetas para que aparezca en español. Para ello tenemos que añadir una serie de parámetros a la función <em>datepicker()</em>, tal y como se muestra en el siguiente código:</p>



<pre class="wp-block-code"><code>$("#datepicker1").datepicker({
   closeText: 'Cerrar',
   prevText: '&lt; Ant',
   nextText: 'Sig &gt;',
   currentText: 'Hoy',
   monthNames: &#91;'Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'],
   monthNamesShort: &#91;'Ene','Feb','Mar','Abr', 'May','Jun','Jul','Ago','Sep', 'Oct','Nov','Dic'],
   dayNames: &#91;'Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves', 'Viernes', 'Sábado'],
   dayNamesShort: &#91;'Dom','Lun','Mar','Mié','Juv','Vie','Sáb'],
   dayNamesMin: &#91;'Do','Lu','Ma','Mi','Ju','Vi','Sá'], 
});</code></pre>



<p class="wp-block-paragraph">Así conseguimos que nuestro calendario ahora se vea en español:</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="605" height="450" src="https://danisanchez.net/wp-content/uploads/2018/12/datepicker-imagen-02.jpeg" alt="" class="wp-image-4437" srcset="https://danisanchez.net/wp-content/uploads/2018/12/datepicker-imagen-02.jpeg 605w, https://danisanchez.net/wp-content/uploads/2018/12/datepicker-imagen-02-300x223.jpeg 300w" sizes="auto, (max-width: 605px) 100vw, 605px" /></figure></div>



<p class="wp-block-paragraph">Pero nos falta un detalle más, y es hacer que la semana comience en Lunes en lugar de Domingo, para ello añadimos el parámetro:</p>



<p class="wp-block-paragraph"><em>firstDay: 1</em></p>



<pre class="wp-block-code"><code>$("#datepicker1").datepicker({
closeText: 'Cerrar',
   prevText: '&lt; Ant',
   nextText: 'Sig &gt;',
   currentText: 'Hoy',
   monthNames: &#91;'Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'],
   monthNamesShort: &#91;'Ene','Feb','Mar','Abr', 'May','Jun','Jul','Ago','Sep', 'Oct','Nov','Dic'],
   dayNames: &#91;'Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves', 'Viernes', 'Sábado'],
   dayNamesShort: &#91;'Dom','Lun','Mar','Mié','Juv','Vie','Sáb'],
   dayNamesMin: &#91;'Do','Lu','Ma','Mi','Ju','Vi','Sá'], 
   firstDay: 1, //Hace que la semana comience en Lunes
});</code></pre>



<p class="wp-block-paragraph">Y aquí el resultado:</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="597" height="445" src="https://danisanchez.net/wp-content/uploads/2018/12/datepicker-imagen-03.jpeg" alt="" class="wp-image-4439" srcset="https://danisanchez.net/wp-content/uploads/2018/12/datepicker-imagen-03.jpeg 597w, https://danisanchez.net/wp-content/uploads/2018/12/datepicker-imagen-03-300x224.jpeg 300w" sizes="auto, (max-width: 597px) 100vw, 597px" /></figure></div>



<p class="wp-block-paragraph">Otra opción interesante es que no se pueda seleccionar un día anterior a la fecha actual, es decir, si hoy estamos a 10 de Diciembre de 2018, el calendario no nos va a permitir seleccionar una fecha anterior, para ello añadimos el parámetro:</p>



<p class="wp-block-paragraph"><em>minDate: 0</em></p>



<pre class="wp-block-code"><code>$("#datepicker1").datepicker({
closeText: 'Cerrar',
   prevText: '&lt; Ant',
   nextText: 'Sig &gt;',
   currentText: 'Hoy',
   monthNames: &#91;'Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'],
   monthNamesShort: &#91;'Ene','Feb','Mar','Abr', 'May','Jun','Jul','Ago','Sep', 'Oct','Nov','Dic'],
   dayNames: &#91;'Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves', 'Viernes', 'Sábado'],
   dayNamesShort: &#91;'Dom','Lun','Mar','Mié','Juv','Vie','Sáb'],
   dayNamesMin: &#91;'Do','Lu','Ma','Mi','Ju','Vi','Sá'], 
   firstDay: 1, //Hace que la semana comience en Lunes
   minDate: 0, //Hace que no se puedan seleccionar fechas pasadas
});</code></pre>



<p class="wp-block-paragraph">Fijaos cómo los días anteriores aparecen en un color más transparente, indicando que no se pueden seleccionar:</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="590" height="431" src="https://danisanchez.net/wp-content/uploads/2018/12/datepicker-imagen-04.jpeg" alt="" class="wp-image-4440" srcset="https://danisanchez.net/wp-content/uploads/2018/12/datepicker-imagen-04.jpeg 590w, https://danisanchez.net/wp-content/uploads/2018/12/datepicker-imagen-04-300x219.jpeg 300w" sizes="auto, (max-width: 590px) 100vw, 590px" /></figure></div>



<p class="wp-block-paragraph">Respecto al formato actual de la fecha, si seleccionamos un día en concreto veremos que el formato está definido en «mes/dia/año»:</p>



<div class="wp-block-image"><figure class="aligncenter"><img loading="lazy" decoding="async" width="588" height="429" src="https://danisanchez.net/wp-content/uploads/2018/12/datepicker-imagen-05.jpeg" alt="" class="wp-image-4442" srcset="https://danisanchez.net/wp-content/uploads/2018/12/datepicker-imagen-05.jpeg 588w, https://danisanchez.net/wp-content/uploads/2018/12/datepicker-imagen-05-300x219.jpeg 300w" sizes="auto, (max-width: 588px) 100vw, 588px" /></figure></div>



<p class="wp-block-paragraph">Si queremos modificar el formato de fecha usamos el parámetro:</p>



<p class="wp-block-paragraph"><em>dateFormat: «dd/mm/yy»</em></p>



<pre class="wp-block-code"><code>$("#datepicker1").datepicker({
closeText: 'Cerrar',
   prevText: '&lt; Ant',
   nextText: 'Sig &gt;',
   currentText: 'Hoy',
   monthNames: &#91;'Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'],
   monthNamesShort: &#91;'Ene','Feb','Mar','Abr', 'May','Jun','Jul','Ago','Sep', 'Oct','Nov','Dic'],
   dayNames: &#91;'Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves', 'Viernes', 'Sábado'],
   dayNamesShort: &#91;'Dom','Lun','Mar','Mié','Juv','Vie','Sáb'],
   dayNamesMin: &#91;'Do','Lu','Ma','Mi','Ju','Vi','Sá'], 
   firstDay: 1, //Hace que la semana comience en Lunes
   minDate: 0, //Hace que no se puedan seleccionar fechas pasadas
   dateFormat: "dd/mm/yy", //Establece el formato de fecha
});</code></pre>



<p class="wp-block-paragraph">Cuyo resultado sería:</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="586" height="426" src="https://danisanchez.net/wp-content/uploads/2018/12/datepicker-imagen-06.jpeg" alt="" class="wp-image-4443" srcset="https://danisanchez.net/wp-content/uploads/2018/12/datepicker-imagen-06.jpeg 586w, https://danisanchez.net/wp-content/uploads/2018/12/datepicker-imagen-06-300x218.jpeg 300w" sizes="auto, (max-width: 586px) 100vw, 586px" /></figure></div>



<p class="wp-block-paragraph">Otra opción que podría resultarnos de interés es la posibilidad de cambiar el mes y el año directamente, para ello usaríamos los parámetros:</p>



<p class="wp-block-paragraph"><em>changeMonth: true,</em><br><em>changeYear: true,</em></p>



<pre class="wp-block-code"><code>$("#datepicker1").datepicker({
closeText: 'Cerrar',
   prevText: '&lt; Ant',
   nextText: 'Sig &gt;',
   currentText: 'Hoy',
   monthNames: &#91;'Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'],
   monthNamesShort: &#91;'Ene','Feb','Mar','Abr', 'May','Jun','Jul','Ago','Sep', 'Oct','Nov','Dic'],
   dayNames: &#91;'Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves', 'Viernes', 'Sábado'],
   dayNamesShort: &#91;'Dom','Lun','Mar','Mié','Juv','Vie','Sáb'],
   dayNamesMin: &#91;'Do','Lu','Ma','Mi','Ju','Vi','Sá'], 
   firstDay: 1, //Hace que la semana comience en Lunes
   minDate: 0, //Hace que no se puedan seleccionar fechas pasadas
   dateFormat: "dd/mm/yy", //Establece el formato de fecha
   changeMonth: true, //Permite seleccionar el mes directamente
   changeYear: true, //Permite seleccionar el año directamente
});</code></pre>



<p class="wp-block-paragraph">El resultado:</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="600" height="513" src="https://danisanchez.net/wp-content/uploads/2018/12/datepicker-imagen-07.jpeg" alt="" class="wp-image-4445" srcset="https://danisanchez.net/wp-content/uploads/2018/12/datepicker-imagen-07.jpeg 600w, https://danisanchez.net/wp-content/uploads/2018/12/datepicker-imagen-07-300x257.jpeg 300w" sizes="auto, (max-width: 600px) 100vw, 600px" /></figure></div>



<h2 class="wp-block-heading">4. Enlazando dos Datepickers</h2>



<p class="wp-block-paragraph">Hasta aquí hemos realizado configuraciones básicas, sobre todo para adaptar Datepicker al sistema de calendario español. Ahora veremos algo realmente interesante que consiste en enlazar dos calendarios Datepicker, de forma que cuando se seleccione una fecha en el Datepicker1, el Datepicker2 impida seleccionar una fecha anterior, muy interesante para sistemas de reservas.</p>



<p class="wp-block-paragraph">Para ello vamos a declarar un segundo Datepicker al que llamaremos #datepicker2, con los mismos parámetros que el #datepicker1.</p>



<pre class="wp-block-code"><code>$("#datepicker2").datepicker({
closeText: 'Cerrar',
   prevText: '&lt; Ant',
   nextText: 'Sig &gt;',
   currentText: 'Hoy',
   monthNames: &#91;'Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'],
   monthNamesShort: &#91;'Ene','Feb','Mar','Abr', 'May','Jun','Jul','Ago','Sep', 'Oct','Nov','Dic'],
   dayNames: &#91;'Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves', 'Viernes', 'Sábado'],
   dayNamesShort: &#91;'Dom','Lun','Mar','Mié','Juv','Vie','Sáb'],
   dayNamesMin: &#91;'Do','Lu','Ma','Mi','Ju','Vi','Sá'], 
   firstDay: 1, //Hace que la semana comience en Lunes
   minDate: 0, //Hace que no se puedan seleccionar fechas pasadas
   dateFormat: "dd/mm/yy", //Establece el formato de fecha
   changeMonth: true, //Permite seleccionar el mes directamente
   changeYear: true, //Permite seleccionar el año directamente
});</code></pre>



<p class="wp-block-paragraph">Ahora añadimos como parámetro al #datepicker1 el siguiente código:</p>



<pre class="wp-block-code"><code>onClose: function (selectedDate){
    $("#datepicker2").datepicker("option", "minDate", selectedDate);
}</code></pre>



<p class="wp-block-paragraph">Y como parámetro del #datepicker2 el siguiente código:</p>



<pre class="wp-block-code"><code>onClose: function (selectedDate){
    $("#datepicker1").datepicker("option", "maxDate", selectedDate);
}</code></pre>



<p class="wp-block-paragraph">Recuerda añadir una coma (,) al final si vas a seguir añadiendo parámetros.</p>



<p class="wp-block-paragraph">Creamos un nuevo input:</p>



<pre class="wp-block-code"><code>&lt;input type="text" name="fecha_salida" id="datepicker2" placeholder="Fecha de salida"/&gt;</code></pre>



<p class="wp-block-paragraph">Y aquí el resultado, si seleccionamos como fecha de entrada el 25 de Diciembre, veremos que en fecha de salida no podemos seleccionar días anteriores al 25 de Diciembre:</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="640" height="477" src="https://danisanchez.net/wp-content/uploads/2018/12/datepicker-imagen-09.jpeg" alt="" class="wp-image-4447" srcset="https://danisanchez.net/wp-content/uploads/2018/12/datepicker-imagen-09.jpeg 640w, https://danisanchez.net/wp-content/uploads/2018/12/datepicker-imagen-09-300x224.jpeg 300w" sizes="auto, (max-width: 640px) 100vw, 640px" /></figure></div>



<p class="wp-block-paragraph">Y ya para finalizar veremos una función para deshabilitar rangos de fechas, es decir, imagina que en tu web de reserva de apartamentos quieres que cuando el usuario despligue el calendario aparezcan bloqueados todos los días que esté reservado.</p>



<p class="wp-block-paragraph">Para ello, previamente, tendríamos que hacer una consulta a la base de datos para traernos las fechas de entrada y salida de cada reserva y guardarlas en un vector o array:</p>



<p class="wp-block-paragraph">Para la función siguiente necesitamos recoger las fechas de la base de datos y pasarlas a formato «mes/día/año».</p>



<p class="wp-block-paragraph">En PHP es fácil:</p>



<pre class="wp-block-code"><code>&lt;?php
    $fecha_formateada = new DateTime($fecha_sin_formatear);
    echo $fecha_formateada-&gt;format('m/d/Y');
?&gt;</code></pre>



<p class="wp-block-paragraph">Cada grupo de fechas entrecomilladas representa un rango (fecha de entrada y fecha de salida), añadimos tantos rangos como reservas haya en la base de datos:</p>



<pre class="wp-block-code"><code>var RangeDates = &#91;"01/10/2019,01/15/2019","01/17/2019,01/24/2019"];
var RangeDatesIsDisable = true;</code></pre>



<p class="wp-block-paragraph">Este ejemplo tomaría 2 rangos de fechas, compuestos por:</p>



<ol class="wp-block-list"><li>Del 10 de Enero de 2019 al 15 de Enero de 2019.</li><li>Del 17 de Enero de 2019 al 24 de Enero de 2019</li></ol>



<p class="wp-block-paragraph">Pasamos la siguiente función que hará las comprobaciones, desglosando los meses, días y años de cada fecha:</p>



<pre class="wp-block-code"><code>function DisableDays(date){
    var isd = RangeDatesIsDisable;
    var rd = RangeDates;
    var m = date.getMonth();
    var d = date.getDate();
    var y = date.getFullYear();
    for (i = 0; i &lt; rd.length; i++){
        var ds = rd&#91;i].split(',');
        var di, df;
        var m1, d1, y1, m2, d2, y2;
        if(ds.length == 1){
            di = ds&#91;0].split('/');
            m1 = parseInt(di&#91;0]);
            d1 = parseInt(di&#91;1]);
            y1 = parseInt(di&#91;2]);
            if (y1 == y &amp;&amp; m1 == (m + 1) &amp;&amp; d1 == d) return &#91;!isd];
        }
 else if (ds.length &gt; 1){
            di = ds&#91;0].split('/');
            df = ds&#91;1].split('/');
            m1 = parseInt(di&#91;0]);
            d1 = parseInt(di&#91;1]);
            y1 = parseInt(di&#91;2]);
            m2 = parseInt(df&#91;0]);
            d2 = parseInt(df&#91;1]);
            y2 = parseInt(df&#91;2]);
          if(y1 &gt;= y || y &lt;= y2){
              if ((m + 1) &gt;= m1 &amp;&amp; (m + 1) &lt;= m2){
             if (m1 == m2){
                 if (d &gt;= d1 &amp;&amp; d &lt;= d2) return &#91;!isd];
                }
 else if(m1 == (m + 1)){
                    if (d &gt;= d1) return &#91;!isd];
                }
 else if(m2 == (m + 1)){
                    if (d &lt;= d2) return &#91;!isd];
                }
 else return &#91;!isd];
              }
          }
        }
    }
    return &#91;isd];
}</code></pre>



<p class="wp-block-paragraph">Y por último añadimos el parámetro: <em>beforeShowDay: DisableDays, </em>a los dos Datepicker, quedando finalmente ambos así:</p>



<pre class="wp-block-code"><code>$("#datepicker1").datepicker({
    closeText: 'Cerrar',
    prevText: '&lt; Ant',
    nextText: 'Sig &gt;',
    currentText: 'Hoy',
    monthNames: &#91;'Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'],
    monthNamesShort: &#91;'Ene','Feb','Mar','Abr', 'May','Jun','Jul','Ago','Sep', 'Oct','Nov','Dic'],
    dayNames: &#91;'Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves', 'Viernes', 'Sábado'],
    dayNamesShort: &#91;'Dom','Lun','Mar','Mié','Juv','Vie','Sáb'],
    dayNamesMin: &#91;'Do','Lu','Ma','Mi','Ju','Vi','Sá'],
    firstDay: 1,
    minDate: 0,
    dateFormat: "dd/mm/yy",
    changeMonth: true,
    changeYear: true,
    beforeShowDay: DisableDays,
    onClose: function (selectedDate){
        $("#datepicker2").datepicker("option", "minDate", selectedDate); 
    }
});
$("#datepicker2").datepicker({
    closeText: 'Cerrar',
    prevText: '&lt; Ant',
    nextText: 'Sig &gt;',
    currentText: 'Hoy',
    monthNames: &#91;'Enero', 'Febrero', 'Marzo', 'Abril', 'Mayo', 'Junio', 'Julio', 'Agosto', 'Septiembre', 'Octubre', 'Noviembre', 'Diciembre'],
    monthNamesShort: &#91;'Ene','Feb','Mar','Abr', 'May','Jun','Jul','Ago','Sep', 'Oct','Nov','Dic'],
    dayNames: &#91;'Domingo', 'Lunes', 'Martes', 'Miércoles', 'Jueves', 'Viernes', 'Sábado'],
    dayNamesShort: &#91;'Dom','Lun','Mar','Mié','Juv','Vie','Sáb'],
    dayNamesMin: &#91;'Do','Lu','Ma','Mi','Ju','Vi','Sá'],
    firstDay: 1,
    minDate: 0,
    dateFormat: "dd/mm/yy",
    changeMonth: true,
    changeYear: true,
    beforeShowDay: DisableDays,
    onClose: function (selectedDate){
        $("#datepicker1").datepicker("option", "minDate", selectedDate);
    }
});</code></pre>



<p class="wp-block-paragraph">Como se aprecia al desplegar el calendario de fecha de entrada, ambos rangos aparecen deshabilitados:</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="653" height="451" src="https://danisanchez.net/wp-content/uploads/2018/12/datepicker-imagen-10.jpeg" alt="" class="wp-image-4449" srcset="https://danisanchez.net/wp-content/uploads/2018/12/datepicker-imagen-10.jpeg 653w, https://danisanchez.net/wp-content/uploads/2018/12/datepicker-imagen-10-300x207.jpeg 300w" sizes="auto, (max-width: 653px) 100vw, 653px" /></figure></div>



<p class="wp-block-paragraph">Esto es solo un extracto de lo que considero es más importante y habitual configurar en cualquier sistema de reservas, pero en la documentación oficial de Datepicker encontrarás más funcionalidades, métodos y parámetros de configuración:</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><a href="http://api.jqueryui.com/datepicker/" target="_blank" rel="noreferrer noopener"><img loading="lazy" decoding="async" width="893" height="555" src="https://danisanchez.net/wp-content/uploads/2018/12/documentacion-datepicker.jpeg" alt="" class="wp-image-4450" srcset="https://danisanchez.net/wp-content/uploads/2018/12/documentacion-datepicker.jpeg 893w, https://danisanchez.net/wp-content/uploads/2018/12/documentacion-datepicker-300x186.jpeg 300w, https://danisanchez.net/wp-content/uploads/2018/12/documentacion-datepicker-768x477.jpeg 768w" sizes="auto, (max-width: 893px) 100vw, 893px" /></a></figure></div>



<p class="wp-block-paragraph">Espero que este post te haya sido de interés y utilidad, si es así no dudes en compartirlo o guardarlo en tus favoritos para futuras consultas.</p>



<p class="wp-block-paragraph">Nos vemos en el siguiente post! <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
]]></content:encoded>
					
					<wfw:commentRss>https://danisanchez.net/datepicker-integracion-y-configuracion-en-wordpress/feed/</wfw:commentRss>
			<slash:comments>9</slash:comments>
		
		
			</item>
		<item>
		<title>Cómo crear roles personalizados en WordPress (sin plugins)</title>
		<link>https://danisanchez.net/como-crear-roles-personalizados-en-wordpress-sin-plugins/</link>
					<comments>https://danisanchez.net/como-crear-roles-personalizados-en-wordpress-sin-plugins/#comments</comments>
		
		<dc:creator><![CDATA[dani.sanchez]]></dc:creator>
		<pubDate>Wed, 21 Nov 2018 18:45:19 +0000</pubDate>
				<category><![CDATA[Publicaciones]]></category>
		<category><![CDATA[Tutoriales]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[desarrollo web]]></category>
		<category><![CDATA[programación web]]></category>
		<category><![CDATA[publicaciones]]></category>
		<category><![CDATA[tutoriales]]></category>
		<category><![CDATA[wordpress]]></category>
		<guid isPermaLink="false">https://www.gestionatuweb.net/?p=4395</guid>

					<description><![CDATA[En WordPress existen 5 roles predefinidos que, en función de los permisos y sus capacidades para con el Dashboard, podemos ordenar en: Suscriptor (Subscriber): No puede crear ningún tipo de contenido pero puede acceder a zonas o contenidos, programados previamente, a los que no pueda acceder un usuario Público. Colaborador (Contributor): Puede crear sus propias [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">En WordPress existen 5 roles predefinidos que, en función de los permisos y sus capacidades para con el Dashboard, podemos ordenar en:</p>



<ul class="wp-block-list"><li><strong>Suscriptor (Subscriber):</strong> No puede crear ningún tipo de contenido pero puede acceder a zonas o contenidos, programados previamente, a los que no pueda acceder un usuario Público.</li><li><strong>Colaborador (Contributor):</strong> Puede <em>crear sus propias entradas</em> aunque estas quedan en estado pendiente de publicación hasta que las apruebe un Editor o Administrador.</li><li><strong>Autor (Author): </strong>Puede <em>publicar, editar y eliminar sus propias entradas</em> pero no las de otro usuario.</li><li><strong>Editor (Editor): </strong>Puede <em>publicar, editar y eliminar</em> cualquier entrada, tanto propia como de otros usuarios. Además puede <em>crear, editar y eliminar</em> páginas.</li><li><strong>Administrador (Administrator): </strong>Puede gestionar cualquier contenido o configuración del sitio web.</li><li><strong>Super Administrador (Super Admin): </strong>En proyectos Multi-Sitio puede crear y eliminar nuevos proyectos, administrar redes, administrar usuarios de red, etc.</li></ul>



<p class="wp-block-paragraph">Pero por si estos roles se nos quedasen cortos, podemos añadir tantos roles queramos con las capacidades específicas que necesitemos.</p>



<p class="wp-block-paragraph">Lo primero será consultar las capacidades que tenemos a nuestra disposición para otorgar a cada uno de los roles que creemos:</p>



<figure class="wp-block-table"><table><tbody><tr><th>Capability</th><th>Super Admin</th><th>Administrator</th><th>Editor</th><th>Author</th><th>Contributor</th><th>Subscriber</th></tr><tr><td>create_sites</td><td>Y</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>delete_sites</td><td>Y</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>manage_network</td><td>Y</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>manage_sites</td><td>Y</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>manage_network_users</td><td>Y</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>manage_network_plugins</td><td>Y</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>manage_network_themes</td><td>Y</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>manage_network_options</td><td>Y</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>upload_plugins</td><td>Y</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>upload_themes</td><td>Y</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>upgrade_network</td><td>Y</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>setup_network</td><td>Y</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><th>Capability</th><th>Super Admin</th><th>Administrator</th><th>Editor</th><th>Author</th><th>Contributor</th><th>Subscriber</th></tr><tr><td>activate_plugins</td><td>Y</td><td>Y<br>(single site or<br>enabled by network setting)</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>create_users</td><td>Y</td><td>Y (single site)</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>delete_plugins</td><td>Y</td><td>Y (single site)</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>delete_themes</td><td>Y</td><td>Y (single site)</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>delete_users</td><td>Y</td><td>Y (single site)</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>edit_files</td><td>Y</td><td>Y (single site)</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>edit_plugins</td><td>Y</td><td>Y (single site)</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>edit_theme_options</td><td>Y</td><td>Y</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>edit_themes</td><td>Y</td><td>Y (single site)</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>edit_users</td><td>Y</td><td>Y (single site)</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>export</td><td>Y</td><td>Y</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>import</td><td>Y</td><td>Y</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><th>Capability</th><th>Super Admin</th><th>Administrator</th><th>Editor</th><th>Author</th><th>Contributor</th><th>Subscriber</th></tr><tr><td>install_plugins</td><td>Y</td><td>Y (single site)</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>install_themes</td><td>Y</td><td>Y (single site)</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>list_users</td><td>Y</td><td>Y</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>manage_options</td><td>Y</td><td>Y</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>promote_users</td><td>Y</td><td>Y</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>remove_users</td><td>Y</td><td>Y</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>switch_themes</td><td>Y</td><td>Y</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>update_core</td><td>Y</td><td>Y (single site)</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>update_plugins</td><td>Y</td><td>Y (single site)</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>update_themes</td><td>Y</td><td>Y (single site)</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>edit_dashboard</td><td>Y</td><td>Y</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>customize</td><td>Y</td><td>Y</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>delete_site</td><td>Y</td><td>Y</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><th>Capability</th><th>Super Admin</th><th>Administrator</th><th>Editor</th><th>Author</th><th>Contributor</th><th>Subscriber</th></tr><tr><td>moderate_comments</td><td>Y</td><td>Y</td><td>Y</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>manage_categories</td><td>Y</td><td>Y</td><td>Y</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>manage_links</td><td>Y</td><td>Y</td><td>Y</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>edit_others_posts</td><td>Y</td><td>Y</td><td>Y</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>edit_pages</td><td>Y</td><td>Y</td><td>Y</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>edit_others_pages</td><td>Y</td><td>Y</td><td>Y</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>edit_published_pages</td><td>Y</td><td>Y</td><td>Y</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>publish_pages</td><td>Y</td><td>Y</td><td>Y</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>delete_pages</td><td>Y</td><td>Y</td><td>Y</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>delete_others_pages</td><td>Y</td><td>Y</td><td>Y</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>delete_published_pages</td><td>Y</td><td>Y</td><td>Y</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>delete_others_posts</td><td>Y</td><td>Y</td><td>Y</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>delete_private_posts</td><td>Y</td><td>Y</td><td>Y</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>edit_private_posts</td><td>Y</td><td>Y</td><td>Y</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>read_private_posts</td><td>Y</td><td>Y</td><td>Y</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>delete_private_pages</td><td>Y</td><td>Y</td><td>Y</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>edit_private_pages</td><td>Y</td><td>Y</td><td>Y</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>read_private_pages</td><td>Y</td><td>Y</td><td>Y</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>unfiltered_html</td><td>Y</td><td>Y (single site)</td><td>Y (single site)</td><td>&nbsp;</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><th>Capability</th><th>Super Admin</th><th>Administrator</th><th>Editor</th><th>Author</th><th>Contributor</th><th>Subscriber</th></tr><tr><td>edit_published_posts</td><td>Y</td><td>Y</td><td>Y</td><td>Y</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>upload_files</td><td>Y</td><td>Y</td><td>Y</td><td>Y</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>publish_posts</td><td>Y</td><td>Y</td><td>Y</td><td>Y</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>delete_published_posts</td><td>Y</td><td>Y</td><td>Y</td><td>Y</td><td>&nbsp;</td><td>&nbsp;</td></tr><tr><td>edit_posts</td><td>Y</td><td>Y</td><td>Y</td><td>Y</td><td>Y</td><td>&nbsp;</td></tr><tr><td>delete_posts</td><td>Y</td><td>Y</td><td>Y</td><td>Y</td><td>Y</td><td>&nbsp;</td></tr><tr><th>Capability</th><th>Super Admin</th><th>Administrator</th><th>Editor</th><th>Author</th><th>Contributor</th><th>Subscriber</th></tr><tr><td>read</td><td>Y</td><td>Y</td><td>Y</td><td>Y</td><td>Y</td><td>Y</td></tr></tbody></table></figure>



<p class="wp-block-paragraph">Para crear un nuevo rol, insertamos el siguiente código en el archivo de funciones del tema activo (functions.php) o en <a href="https://danisanchez.net/wordpress-crear-nuestro-propio-plugin-de-funciones/" target="_blank" rel="noreferrer noopener">nuestro propio plugin de funciones</a>. Vamos a crear por ejemplo, un rol llamado Cliente:</p>



<pre class="wp-block-code"><code><pre class="wp-block-syntaxhighlighter-code">$resultado = add_role(
    'cliente',
    __( 'Cliente' ),
    array(
        'read'         =&gt; true,  // true allows this capability
        'edit_posts'   =&gt; false,
        'delete_posts' =&gt; false,
    )
);</pre></code></pre>



<p class="wp-block-paragraph">En el array añadimos las principales capacidades por defecto:</p>



<ul class="wp-block-list"><li>read (lectura como verdarero).</li><li>edit_posts (editar entradas como falso).</li><li>delete_posts (borrar entradas como falso).</li></ul>



<p class="wp-block-paragraph">A continuación añadimos las capacidades extras para el nuevo rol:</p>



<pre class="wp-block-code"><code><pre class="wp-block-syntaxhighlighter-code">//Actualizar capacidades Cliente
function capacidades_cliente(){
    $role = get_role('cliente');
    $role-&gt;add_cap('publish_posts', true);
    $role-&gt;add_cap('edit_posts', true);
    $role-&gt;add_cap('delete_posts', true);
}
add_action('init', 'capacidades_cliente', 11);</pre></code></pre>



<p class="wp-block-paragraph">Esta función añade al Rol Cliente las capacidades para publicar entradas, editarlas y eliminarlas, pero solamente sus propias entradas, para afectar a las entradas de otros usuarios habría que usar la capacidades «publish_others_posts», «edit_others_posts» y «delete_others_posts».</p>



<p class="wp-block-paragraph"><strong>A TENER EN CUENTA: </strong>Tanto la creación de nuevos roles con add_role(), como las capacidades añadidas, quedan grabadas en la base de datos y aunque eliminemos las funciones, permanecerán activas en el sitio. Si queremos eliminar un rol o una capacidad determinada, usamos <em>remove_role()</em> y <em>remove_cap(&#8216;capacidad&#8217;, true), </em>por ejemplo si queremos quitar la capacidad de eliminar entradas, crearíamos la función:</p>



<pre class="wp-block-code"><code>//Eliminar capacidades Cliente
function eliminar_capacidades_cliente(){
   $role = remove_cap('delete_posts', true);
}
add_action('init', 'eliminar_capacidades_cliente', 11);</code></pre>



<p class="wp-block-paragraph">O para eliminar completamente el rol:</p>



<pre class="wp-block-code"><code>//Eliminar rol Cliente
$resultado = remove_role('cliente');</code></pre>



<p class="wp-block-paragraph">Y una vez que se ejecute por primera vez, la capacidad quedará eliminada de la base de datos.</p>



<p class="wp-block-paragraph">Espero que este post os sirva para sacar más partido a vuestros usuarios, definiendo exactamente aquellas funciones o permisos que queráis otorgarles.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://danisanchez.net/como-crear-roles-personalizados-en-wordpress-sin-plugins/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>Añadir campos adicionales en el registro de WordPress</title>
		<link>https://danisanchez.net/anadir-campos-adicionales-en-el-registro-de-wordpress/</link>
					<comments>https://danisanchez.net/anadir-campos-adicionales-en-el-registro-de-wordpress/#comments</comments>
		
		<dc:creator><![CDATA[dani.sanchez]]></dc:creator>
		<pubDate>Fri, 02 Nov 2018 16:24:39 +0000</pubDate>
				<category><![CDATA[Publicaciones]]></category>
		<category><![CDATA[Tutoriales]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[desarrollo web]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[programación web]]></category>
		<category><![CDATA[publicaciones]]></category>
		<category><![CDATA[tutoriales]]></category>
		<category><![CDATA[wordpress]]></category>
		<guid isPermaLink="false">https://www.gestionatuweb.net/?p=4355</guid>

					<description><![CDATA[En WordPress existe la posibilidad de que los usuarios creen su propia cuenta de forma automática sin que el administrador tenga que intervenir. Para ello debe estar habilitada la opción «Cualquiera puede registrarse» en los Ajustes Generales de WordPress. Una vez habilitada la casilla de registro, cuando accedamos a la pantalla de login, veremos la [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">En WordPress existe la posibilidad de que los usuarios creen su propia cuenta de forma automática sin que el administrador tenga que intervenir.</p>



<p class="wp-block-paragraph">Para ello debe estar habilitada la opción «<em>Cualquiera puede registrarse</em>» en los <strong>Ajustes Generales</strong> de WordPress.</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="890" height="182" src="https://danisanchez.net/wp-content/uploads/2018/11/01.habilitar-registro-wordpress.jpg" alt="" class="wp-image-4356" srcset="https://danisanchez.net/wp-content/uploads/2018/11/01.habilitar-registro-wordpress.jpg 890w, https://danisanchez.net/wp-content/uploads/2018/11/01.habilitar-registro-wordpress-300x61.jpg 300w, https://danisanchez.net/wp-content/uploads/2018/11/01.habilitar-registro-wordpress-768x157.jpg 768w" sizes="auto, (max-width: 890px) 100vw, 890px" /></figure></div>



<p class="wp-block-paragraph">Una vez habilitada la casilla de registro, cuando accedamos a la pantalla de <em>login, </em>veremos la opción <strong>Registrarse:</strong></p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="646" height="500" src="https://danisanchez.net/wp-content/uploads/2018/11/02.link-registro-wordpress.jpg" alt="" class="wp-image-4357" srcset="https://danisanchez.net/wp-content/uploads/2018/11/02.link-registro-wordpress.jpg 646w, https://danisanchez.net/wp-content/uploads/2018/11/02.link-registro-wordpress-300x232.jpg 300w" sizes="auto, (max-width: 646px) 100vw, 646px" /></figure></div>



<p class="wp-block-paragraph">El link de registro tiene la estructura: www.tudominio.xxx/<em>wp-login.php?action=register</em>, por lo que puedes crear un enlace personalizado donde quieras (en el menú principal, widgets&#8230;).</p>



<p class="wp-block-paragraph">El formulario de registro solamente solicita un <em>nombre de usuario</em> y una <em>dirección de correo electrónico</em>, por lo que no se guardarán maś datos del usuario y no sabremos nada más de él.</p>



<p class="wp-block-paragraph">En posts anteriores vimos cómo podíamos <a href="https://danisanchez.net/como-anadir-checkbox-formulario-registro-wordpress-politica-privacidad/" target="_blank" rel="noreferrer noopener">añadir un check de aceptación de términos de privacidad</a> en el formulario de registro de WordPress, pero ese checkbox no era un dato que se registrase en ningún sitio, tan solo servía para comprobar la acción del usuario que valida que se hace responsable de aceptar dichos términos.</p>



<p class="wp-block-paragraph">Imaginemos que además de añadir el checkbox de aceptación, queremos también añadir un campo para solicitar el teléfono del usuario y que este además, se guarde junto a los datos del usuario.</p>



<p class="wp-block-paragraph">El proceso consta de 4 funciones que habrá que especificar en el archivo <em>functions.php</em> del tema activo, o en <a href="https://danisanchez.net/wordpress-crear-nuestro-propio-plugin-de-funciones/" target="_blank" rel="noreferrer noopener">nuestro propio plugin de funciones</a>.</p>



<h3 class="wp-block-heading">Añadir los campos al formulario de registro</h3>



<pre class="wp-block-code"><code><pre class="wp-block-syntaxhighlighter-code">//Añadir campos adicionales al registro del usuario
function campos_adicionales_registro_usuario(){
  $user_phone = (isset($_POST&#91;'user_phone'])) ? $_POST&#91;'user_phone'] : ''; ?>
  &lt;p>
    &lt;label for="user_phone">Teléfono&lt;br/>
    &lt;input type="number" id="user_phone" name="user_phone" class="input" size="25" value="&lt;?php echo esc_attr($user_phone);?>">&lt;/label>
  &lt;/p>
 &lt;div id="aceptacionTerminosRegistro">
 &lt;input type="checkbox" name="acepto"  required/> Acepto los &lt;b>&lt;a href="aviso-legal" target="_blank">términos y condiciones&lt;/a>&lt;/b> de la política de protección de datos.
 &lt;/div>
&lt;?php }
add_action('register_form', 'campos_adicionales_registro_usuario', 10,3);</pre></code></pre>



<p class="wp-block-paragraph">El resultado sería:</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="615" height="607" src="https://danisanchez.net/wp-content/uploads/2018/11/04.nuevos-campos-formulario-registro.jpg" alt="" class="wp-image-4360" srcset="https://danisanchez.net/wp-content/uploads/2018/11/04.nuevos-campos-formulario-registro.jpg 615w, https://danisanchez.net/wp-content/uploads/2018/11/04.nuevos-campos-formulario-registro-300x296.jpg 300w" sizes="auto, (max-width: 615px) 100vw, 615px" /></figure></div>



<h3 class="wp-block-heading">Validar los datos introducidos antes de guardarlos</h3>



<p class="wp-block-paragraph">El siguiente paso consistiría en validar que el usuario ha insertado un dato válido en el campo teléfono y ha aceptado los términos y condiciones de la política de privacidad.</p>



<pre class="wp-block-code"><code><pre class="wp-block-syntaxhighlighter-code">//Validar campos adicionales del registro de usuario
function validar_datos_usuario($errors, $sanitized_user_login, $user_email){
  if(empty($_POST&#91;'user_phone'])){
    $errors->add('user_phone_error', __('&lt;strong>ERROR&lt;/strong>: Por favor, introduzca su Nº de Teléfono'));
  }
  if(empty($_POST&#91;'acepto'])){
    $errors->add('acepto_error', __('&lt;strong>ERROR&lt;/strong>: Debe marcar la casilla de aceptación de privacidad.'));
  }
  return $errors;
}
add_filter('registration_errors', 'validar_datos_usuario', 10, 3);</pre></code></pre>



<p class="wp-block-paragraph">Si los campos están vacíos darán el correspondiente aviso y no dejará continuar:</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="642" height="592" src="https://danisanchez.net/wp-content/uploads/2018/11/05.error-en-los-campos.jpg" alt="" class="wp-image-4362" srcset="https://danisanchez.net/wp-content/uploads/2018/11/05.error-en-los-campos.jpg 642w, https://danisanchez.net/wp-content/uploads/2018/11/05.error-en-los-campos-300x277.jpg 300w" sizes="auto, (max-width: 642px) 100vw, 642px" /></figure></div>



<h3 class="wp-block-heading">Guardar los datos adicionales del formulario de registro</h3>



<pre class="wp-block-code"><code><pre class="wp-block-syntaxhighlighter-code">//Guardar los campos adicionales del usuario
function guardar_campos_adicionales_usuario($user_id){
  if(isset($_POST&#91;'user_phone'])){
    update_user_meta($user_id, 'user_phone', sanitize_text_field($_POST&#91;'user_phone']));
  }
}
add_action('user_register', 'guardar_campos_adicionales_usuario');</pre></code></pre>



<p class="wp-block-paragraph">Con este código guardamos los campos adicionales del formulario de registro, en este caso, el campo teléfono.</p>



<h3 class="wp-block-heading">Visualizar los datos guardados en el panel «Tu perfil» y «Editar Usuario»</h3>



<pre class="wp-block-code"><code><pre class="wp-block-syntaxhighlighter-code">//Agregar los campos adicionales a Tu Perfil y Editar Usuario
function agregar_campos_personalizados_usuario_backend($user) {
  $user_phone = esc_attr(get_the_author_meta('user_phone', $user->ID ));?>
  &lt;h3>Campos adicionales&lt;/h3>
  &lt;table class="form-table">
      &lt;th>&lt;label for="user_phone">Teléfono&lt;/label>&lt;/th>
    &lt;tr>
      &lt;td>&lt;input type="text" name="user_phone" id="user_phone" class="regular-text" value="&lt;?php echo $user_phone;?>" />&lt;/td>
    &lt;/tr>
  &lt;/table>
&lt;?php }
add_action('show_user_profile', 'agregar_campos_personalizados_usuario_backend');
add_action('edit_user_profile', 'agregar_campos_personalizados_usuario_backend');
add_action('personal_options_update', 'guardar_campos_adicionales_cliente');
add_action('edit_user_profile_update', 'guardar_campos_adicionales_cliente');</pre></code></pre>



<p class="wp-block-paragraph">Con esto últmo ya veremos el teléfono registrado por el cliente desde el panel de usuarios:</p>



<div class="wp-block-image"><figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="936" height="553" src="https://danisanchez.net/wp-content/uploads/2018/11/06.visualizar-datos-usuario.jpg" alt="" class="wp-image-4363" srcset="https://danisanchez.net/wp-content/uploads/2018/11/06.visualizar-datos-usuario.jpg 936w, https://danisanchez.net/wp-content/uploads/2018/11/06.visualizar-datos-usuario-300x177.jpg 300w, https://danisanchez.net/wp-content/uploads/2018/11/06.visualizar-datos-usuario-768x454.jpg 768w" sizes="auto, (max-width: 936px) 100vw, 936px" /></figure></div>



<p class="wp-block-paragraph">Recuerda que puedes guardar todos los campos que desees solicitar al usuario, pidiéndolos en la primera función mediante los «inputs», validándolos en la segunda función, y guardándolos y visualizándolos en la tercera y cuarta función.</p>



<p class="wp-block-paragraph">Si crees que este artículo te ha sido útil, compártelo! Hasta el siguente post <img src="https://s.w.org/images/core/emoji/17.0.2/72x72/1f609.png" alt="😉" class="wp-smiley" style="height: 1em; max-height: 1em;" /></p>
]]></content:encoded>
					
					<wfw:commentRss>https://danisanchez.net/anadir-campos-adicionales-en-el-registro-de-wordpress/feed/</wfw:commentRss>
			<slash:comments>15</slash:comments>
		
		
			</item>
	</channel>
</rss>
