<?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>Tutoriales y screencast archivos - KumbiaPHP Framework PHP en español</title>
	<atom:link href="https://kumbiaphp.com/blog/category/tutoriales-y-screencast/feed/" rel="self" type="application/rss+xml" />
	<link>https://kumbiaphp.com/blog/category/tutoriales-y-screencast/</link>
	<description>Web &#38; app MVC PHP framework</description>
	<lastBuildDate>Mon, 24 Nov 2025 21:51:00 +0000</lastBuildDate>
	<language>es</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://kumbiaphp.com/blog/wp-content/uploads/2016/01/250-150x150.png</url>
	<title>Tutoriales y screencast archivos - KumbiaPHP Framework PHP en español</title>
	<link>https://kumbiaphp.com/blog/category/tutoriales-y-screencast/</link>
	<width>32</width>
	<height>32</height>
</image> 
<site xmlns="com-wordpress:feed-additions:1">123854898</site>	<item>
		<title>Chatbots inteligentes en PHP con KumbiaPHP</title>
		<link>https://kumbiaphp.com/blog/2025/11/07/chatbots-inteligentes-en-php-con-kumbiaphp/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=chatbots-inteligentes-en-php-con-kumbiaphp</link>
					<comments>https://kumbiaphp.com/blog/2025/11/07/chatbots-inteligentes-en-php-con-kumbiaphp/#respond</comments>
		
		<dc:creator><![CDATA[HenryStivens]]></dc:creator>
		<pubDate>Fri, 07 Nov 2025 06:00:00 +0000</pubDate>
				<category><![CDATA[AI]]></category>
		<category><![CDATA[Tutoriales y screencast]]></category>
		<category><![CDATA[ejemplos]]></category>
		<guid isPermaLink="false">https://kumbiaphp.com/blog/?p=2975</guid>

					<description><![CDATA[<p>¿Qué es un chatbot inteligente? Un chatbot con PHP es un asistente virtual que usa inteligencia artificial para simular&#8230;</p>
<p>La entrada <a href="https://kumbiaphp.com/blog/2025/11/07/chatbots-inteligentes-en-php-con-kumbiaphp/">Chatbots inteligentes en PHP con KumbiaPHP</a> se publicó primero en <a href="https://kumbiaphp.com/blog">KumbiaPHP Framework PHP en español</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p style="text-align: center;"><iframe title="YouTube video player" src="https://www.youtube.com/embed/ksijcOJSRAY?si=EPYBZNdJ6_KcJo0U" width="560" height="315" frameborder="0" allowfullscreen="allowfullscreen"></iframe></p>

<h2>¿Qué es un chatbot inteligente?</h2>
<p>Un chatbot con <a href="https://kumbiaphp.com/blog/category/php/">PHP</a> es un asistente virtual que usa inteligencia artificial para simular una conversación natural con usuarios, realizando tareas como responder preguntas, agendar citas, brindar soporte técnico y más. Implementar un chatbot inteligente utilizando PHP puede potenciar significativamente tu aplicación web.</p>
<p data-pm-slice="1 1 []">Veremos paso a paso cómo configurar las dependencias, conectar con el modelo GPT-4 y construir una interfaz simple que permita interactuar con el asistente directamente desde tu aplicación web.</p>
<h2>Herramientas recomendadas para crear chatbots con PHP</h2>
<ul data-spread="false">
<li>
<p><a href="https://openai.com/es-ES/api/"><strong>OpenAI API</strong></a>: Facilita el acceso a modelos avanzados como GPT-4 para procesamiento de lenguaje natural y es ideal para construir un chatbot con PHP.</p>
</li>
<li>
<p><a href="https://dialogflow.cloud.google.com/"><strong>Dialogflow</strong></a>: Servicio gestionado de Google que simplifica la creación de interfaces conversacionales y puede integrarse fácilmente como chatbot con PHP.</p>
</li>
<li>
<p><a href="https://rasa.com/"><strong>Rasa</strong></a>: Alternativa open source para chatbots personalizados y con mayor control, perfecta para crear un chatbot con PHP.</p>
</li>
</ul>
<h2>Creando un chatbot con PHP y KumbiaPHP usando la API de OpenAI</h2>
<h4>Paso 1: Instalar dependencias</h4>
<p>Usa Composer para instalar la librería oficial de OpenAI para tu chatbot con PHP (<a href="https://packagist.org/packages/openai-php/client">Packagist de</a><br /><a href="https://packagist.org/packages/openai-php/client">OpenAI PHP</a>):</p>


<pre class="wp-block-code language-bash"><code class="" data-line="">composer require openai-php/client</code></pre>



<span id="more-2975"></span>


<h4 data-pm-slice="1 1 []">Paso 2: Configuración específica para OpenAI</h4>
<p>Crea un archivo específico para la configuración en <em>config/openai.php</em> para tu chatbot con PHP:</p>


<pre class="wp-block-code language-php"><code class="" data-line="">&lt;?php

return &#091;
    &#039;api_key&#039; =&gt; &#039;TU_API_KEY&#039;,
    &#039;model&#039; =&gt; &#039;gpt-4-turbo&#039;,
    &#039;systemPrompt&#039; =&gt; 
        &#039;Eres un asistente útil. Te llamas Kumbita y amas Kumbiaphp&#039;,
];</code></pre>


<h4 data-pm-slice="1 1 []">Paso 3: Crear modelo para lógica de OpenAI</h4>
<p>Crea el archivo <em>app/models/open_ai_model.php</em>, esencial para desarrollar un chatbot con PHP:</p>


<pre class="wp-block-code language-php"><code class="" data-line="">&lt;?php

use \OpenAI\Client;

/**
 * OpenAI Service Model
 */
class OpenAiModel
{
    /**
     * @var OpenAiModel|null Instancia única de la clase
     */
    private static ?OpenAiModel $instance;

    /**
     * @var Client El cliente OpenAI
     */
    private Client $client;

    /**
     * @var array Configuración de OpenAI
     */
    private array $config;

    /**
     * Constructor para otras config
     *
     * @param array Configuración (opcional)
     */
    public function __construct(?array $config = null)
    {
        $this-&gt;config = $config ?? Config::read(&#039;openai&#039;);
        $this-&gt;client = OpenAI::client($this-&gt;config&#091;&#039;api_key&#039;]);
    }

    /**
     * Obtiene la instancia única del servicio
     *
     * @param array Configuración (opcional)
     * @return OpenAiModel
     */
    public static function getInstance(?array $config = null): self
    {
        return self::$instance ??= new self($config);
    }

    /**
     * Obtiene el cliente OpenAI
     * 
     * @return Client
     */
    public function getClient(): Client
    {
        return $this-&gt;client;
    }

    /**
     * Envía un mensaje a OpenAI y recibe la respuesta
     * 
     * @param string $message El mensaje del usuario
     * @param string $systemPrompt El prompt del sistema (opcional)
     *
     * @return string La respuesta del modelo
     */
    public function sendMessage(string $message, ?string $systemPrompt = null): string
    {
        $response = $this-&gt;client-&gt;chat()-&gt;create(&#091;
            &#039;model&#039; =&gt; $this-&gt;config&#091;&#039;model&#039;],
            &#039;messages&#039; =&gt; &#091;
                &#091;
                  &#039;role&#039; =&gt; &#039;system&#039;,
                  &#039;content&#039; =&gt; $systemPrompt ?? $this-&gt;config&#091;&#039;systemPrompt&#039;]
                ],
                &#091;
                  &#039;role&#039; =&gt; &#039;user&#039;,
                  &#039;content&#039; =&gt; $message
                ],
            ],
        ]);

        return $response-&gt;choices&#091;0]-&gt;message-&gt;content;
    }
}</code></pre>


<h4 data-pm-slice="1 1 []">Paso 4: Crear controlador Chatbot en KumbiaPHP</h4>


<pre class="wp-block-code language-php"><code class="" data-line="">&lt;?php

class ChatbotController extends AppController
{
    /**
     * Muestra el chatbot
     */
    public function index()
    {
    }

    /**
     * Endpoint para manejar mensajes del chatbot
     */
    public function message()
    {
        View::select(null, &#039;json&#039;);

        $message = Input::post(&#039;message&#039;);

        $this-&gt;data = match ($message) {
            null, &#039;&#039; =&gt; &#091;],
            default =&gt;  &#091;&#039;reply&#039; =&gt; OpenAiModel::getInstance()-&gt;sendMessage($message)],
        };
    }
}
</code></pre>


<h4 data-pm-slice="1 1 []">Paso 5: Crear la vista del chatbot en KumbiaPHP</h4>
<p>Crea la vista <em>index.phtml</em> en <em>app/views/chatbot/</em> para interactuar fácilmente con tu chatbot con PHP:</p>


<pre class="wp-block-code language-php"><code class="" data-line="">&lt;section id=&quot;aibot&quot;&gt;
    &lt;h1&gt;Chatbot Inteligente con PHP y KumbiaPHP&lt;/h1&gt;

    &lt;div id=&quot;chatResponse&quot;&gt;
        &lt;p&gt;
            &lt;b&gt;Kumbita:&lt;/b&gt; Hola, me llamo Kumbita. ¿Qué quieres saber hoy?
        &lt;/p&gt;
    &lt;/div&gt;

    &lt;?= Form::open(&#039;&#039;, &#039;POST&#039;, &#039;id=&quot;chatbot&quot;&#039;) ?&gt;
    &lt;?= Form::text(&#039;message&#039;, &#039;placeholder=&quot;Escribe tu pregunta&quot; autofocus&#039;) ?&gt;
    &lt;?= Form::submit(&#039;Enviar&#039;, &#039;class=&quot;btn btn-primary&quot;&#039;) ?&gt;
    &lt;?= Form::close() ?&gt;
&lt;/section&gt;

&lt;script&gt;
    document.getElementById(&quot;chatbot&quot;).addEventListener(&quot;submit&quot;,
        function(event) {
            event.preventDefault();
            sendMessage();
        });

    const messageEl = document.getElementById(&#039;message&#039;);
    const chatResponse = document.getElementById(&#039;chatResponse&#039;);
    const btnSubmit = document.querySelector(&#039;#chatbot &#091;type=&quot;submit&quot;]&#039;);
    const speech = &#039;speechSynthesis&#039; in window ? new SpeechSynthesisUtterance() : null;
    const apiError = &quot;Lo siento, parece que hay un error al conectar a la API&quot;;

    speak(&quot;Hola, me llamo Kumbita. ¿Qué quieres saber hoy?&quot;, &quot;es&quot;);

    function sendMessage() {
        const message = messageEl.value;
        if(message.trim() === &#039;&#039;) return;
        btnSubmit.disabled = true;
        messageEl.disabled = true;
        chatResponse.innerHTML += `&lt;p&gt;&lt;b&gt;Tu:&lt;/b&gt; ${message}&lt;/p&gt;&lt;div id=&quot;loading&quot;&gt;&lt;/div&gt;`;
        chatResponse.scrollTop = chatResponse.scrollHeight;

        fetch(&#039;/chatbot/message&#039;, {
                method: &#039;POST&#039;,
                headers: {
                    &#039;Content-Type&#039;: &#039;application/x-www-form-urlencoded&#039;,
                    &#039;Accept&#039;: &#039;application/json&#039;
                },
                body: &#039;message=&#039; + encodeURIComponent(message)
            })
            .then(response =&gt; response.json())
            .then(data =&gt; {
                response(data.reply ?? &quot;&quot;);
            })
            .catch(error =&gt; {
                console.log(error);
                response(apiError);
            })
            .finally(() =&gt; {
                btnSubmit.disabled = false;
                messageEl.disabled = false;
                messageEl.value = &#039;&#039;;
                messageEl.focus();
            });
    }

    function response(message) {
        speak(message);
        document.getElementById(&#039;loading&#039;).remove();
        chatResponse.innerHTML += `&lt;p&gt;&lt;b&gt;Kumbita:&lt;/b&gt; ${message}&lt;/p&gt;`;
        chatResponse.scrollTop = chatResponse.scrollHeight;
    }

    function speak(text, lang = navigator.language) {
        if(!speech) return;
        speech.lang = lang
        speech.text = text
        window.speechSynthesis.speak(speech)
    }
&lt;/script&gt;

&lt;style&gt;
    #aibot {
        max-width: 500px;
        margin: 0 auto;

        &amp; h1 {
            text-align: center;
        }

        &amp; #chatbot {
            display: flex;
            margin-top: 1em;
        }

        &amp; #message {
            flex: 1;
            border-radius: 2rem 0 0 2rem;
            padding: 0.5em 1em;
            box-shadow: none;

            &amp;:focus {
                outline: none;
            }
        }

        &amp; &#091;type=&quot;submit&quot;] {
            flex: 0;
            border-radius: 0 2rem 2rem 0;
            box-shadow: none;
            
            &amp;:disabled {
                opacity: 0.5;
            }
        }

        &amp; #chatResponse {
            margin: 20px auto 0;
            min-height: 60px;
            max-height: 400px;
            background: #f5f5f5;
            border-radius: 6px;
            padding: 1em;
            box-shadow: 1px 1px 5px #eee;
            overflow-y: auto;
            display: flex;
            flex-direction: column;

            &amp; p {
                color: #333;
            }
        }
    }
    #loading {
        width: 12px;
        height: 12px;
        border-radius: 50%;
        display: block;
        margin:15px auto;
        position: relative;
        color: #9ab8ef;
        box-sizing: border-box;
        animation: animloader 1s linear infinite alternate;
    }

    @keyframes animloader {
        0% {box-shadow: -38px -6px, -14px 6px,  14px -6px;}
        33% {box-shadow: -38px 6px, -14px -6px,  14px 6px;}
        66% {box-shadow: -38px -6px, -14px 6px, 14px -6px;}
        100% {box-shadow: -38px 6px, -14px -6px, 14px 6px;}
    }
&lt;/style&gt;
</code></pre>



<figure class="wp-block-image size-large"><a href="https://kumbiaphp.com/blog/wp-content/uploads/2025/11/kumbiaphp-chatbot-openai.jpg"><img fetchpriority="high" decoding="async" width="1024" height="576" src="https://kumbiaphp.com/blog/wp-content/uploads/2025/11/kumbiaphp-chatbot-openai-1024x576.jpg" alt="Chatbot inteligente con PHP Y KumbiaPHP" class="wp-image-2989" srcset="https://kumbiaphp.com/blog/wp-content/uploads/2025/11/kumbiaphp-chatbot-openai-1024x576.jpg 1024w, https://kumbiaphp.com/blog/wp-content/uploads/2025/11/kumbiaphp-chatbot-openai-300x169.jpg 300w, https://kumbiaphp.com/blog/wp-content/uploads/2025/11/kumbiaphp-chatbot-openai-768x432.jpg 768w, https://kumbiaphp.com/blog/wp-content/uploads/2025/11/kumbiaphp-chatbot-openai-1536x864.jpg 1536w, https://kumbiaphp.com/blog/wp-content/uploads/2025/11/kumbiaphp-chatbot-openai-940x529.jpg 940w, https://kumbiaphp.com/blog/wp-content/uploads/2025/11/kumbiaphp-chatbot-openai.jpg 1920w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></figure>


<h3 data-pm-slice="1 1 []">Ventajas de usar chatbots en aplicaciones PHP</h3>
<ul data-spread="false">
<li>
<p>Disponibilidad 24/7.</p>
</li>
<li>
<p>Respuestas inmediatas y personalizadas.</p>
</li>
<li>
<p>Optimización de recursos humanos y reducción de costos operativos.</p>
</li>
</ul>
<p>Este ejemplo constituye una <strong>base sólida</strong> para comprender cómo integrar inteligencia artificial en tus proyectos PHP con KumbiaPHP. A partir de aquí, puedes ampliarlo añadiendo <strong>manejo de historial de conversación</strong>, <strong>personalización de prompts del sistema</strong>, <strong>validaciones adicionales de entrada</strong>, o incluso <strong>mecanismos de seguridad</strong> para evitar abusos en el endpoint.</p>
<p>Al finalizar esta guía, tendrás un chatbot completamente funcional listo para integrarse en cualquier proyecto desarrollado con KumbiaPHP. Anímate a probarlo, experimentar con sus respuestas y descubrir el potencial de combinar la sencillez de PHP con la potencia de la inteligencia artificial. Si te ha resultado útil, <strong>comparte este artículo</strong> o deja tus comentarios en el blog para seguir mejorando juntos.</p>


<h2 class="wp-block-heading">Agradecimientos</h2>



<p class="wp-block-paragraph">Agradecemos especialmente a @joanhey por tomarse el tiempo de revisar y mejorar el código de ejemplo, aportando sugerencias valiosas que ayudaron a hacerlo más claro y funcional para la comunidad de desarrolladores de KumbiaPHP.</p>
<p>La entrada <a href="https://kumbiaphp.com/blog/2025/11/07/chatbots-inteligentes-en-php-con-kumbiaphp/">Chatbots inteligentes en PHP con KumbiaPHP</a> se publicó primero en <a href="https://kumbiaphp.com/blog">KumbiaPHP Framework PHP en español</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://kumbiaphp.com/blog/2025/11/07/chatbots-inteligentes-en-php-con-kumbiaphp/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2975</post-id>	</item>
		<item>
		<title>Buscador avanzado de texto completo para KumbiaPHP con Meilisearch</title>
		<link>https://kumbiaphp.com/blog/2025/04/19/buscador-avanzado-texto-completo-kumbiaphp-meilisearch/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=buscador-avanzado-texto-completo-kumbiaphp-meilisearch</link>
					<comments>https://kumbiaphp.com/blog/2025/04/19/buscador-avanzado-texto-completo-kumbiaphp-meilisearch/#respond</comments>
		
		<dc:creator><![CDATA[HenryStivens]]></dc:creator>
		<pubDate>Sat, 19 Apr 2025 08:00:00 +0000</pubDate>
				<category><![CDATA[AI]]></category>
		<category><![CDATA[Tutoriales y screencast]]></category>
		<category><![CDATA[buscador]]></category>
		<category><![CDATA[ejemplos]]></category>
		<guid isPermaLink="false">https://kumbiaphp.com/blog/?p=2903</guid>

					<description><![CDATA[<p>La entrada <a href="https://kumbiaphp.com/blog/2025/04/19/buscador-avanzado-texto-completo-kumbiaphp-meilisearch/">Buscador avanzado de texto completo para KumbiaPHP con Meilisearch</a> se publicó primero en <a href="https://kumbiaphp.com/blog">KumbiaPHP Framework PHP en español</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<div style="text-align:center;"><iframe width="560" height="315" src="https://www.youtube.com/embed/knyUp-Wleg4?si=b5TdpovBYkE4dCpm" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe></div>



<p class="" data-start="271" data-end="624">Si estás buscando implementar un <strong data-start="304" data-end="374">buscador avanzado de texto completo para KumbiaPHP con <a href="https://www.meilisearch.com/">Meilisearch</a></strong>, este artículo te mostrará cómo hacerlo de manera sencilla, efectiva y escalable. Descubre cómo aprovechar todo el potencial de Meilisearch en tus aplicaciones KumbiaPHP, ofreciendo a tus usuarios búsquedas rápidas y resultados altamente relevantes.</p>
<h2>¿Por qué utilizar un buscador avanzado de texto completo para KumbiaPHP con Meilisearch?</h2>
<p>Implementar un <strong data-start="739" data-end="809">buscador avanzado de texto completo para KumbiaPHP con Meilisearch</strong> permite llevar las capacidades de búsqueda de tus aplicaciones a otro nivel. Meilisearch es un motor de búsqueda rápido, potente y de fácil configuración, ideal para aplicaciones modernas que requieren búsquedas en tiempo real, autocompletado y manejo de grandes volúmenes de datos.<br data-start="1020" data-end="1023" />Además, gracias a sus capacidades de búsqueda semántica impulsada por inteligencia artificial, se pueden obtener resultados mucho más precisos incluso cuando las palabras de búsqueda no coinciden exactamente con los términos indexados.</p>
<h2>Requisitos</h2>
<p>Antes de comenzar a integrar un <strong data-start="2097" data-end="2167">buscador avanzado de texto completo para KumbiaPHP con Meilisearch</strong>, verifica que tu entorno cumpla con los siguientes requisitos básicos:</p>
<ul>
<li>
<p>Tener una aplicación funcionando con <strong><a href="https://kumbiaphp.com/blog/manuales-y-descargas/">KumbiaPHP 1.2</a> o superior</strong>.</p>
</li>
<li>
<p>Tener <strong><a href="_wp_link_placeholder" data-wplink-edit="true">PHP 8.0</a> o superior</strong>.</p>
</li>
<li>
<p>Tener acceso al servidor o contenedor donde correrá <strong>Meilisearch</strong>.</p>
</li>
<li>
<p>Instalar el cliente de Meilisearch para PHP con Composer:</p>
</li>
</ul>
<pre><code class="language-bash" data-line="">composer require meilisearch/meilisearch-php \
guzzlehttp/guzzle \
http-interop/http-factory-guzzle:^1.0</code></pre>
<ul>
<li>
<p>Instalar el nuevo ActiveRecord de KumbiaPHP si aún no lo tienes:</p>
</li>
</ul>
<pre><code class="language-bash" data-line="">composer require kumbia/activerecord
</code></pre>
<blockquote>
<p>Este nuevo ActiveRecord es un componente externo que puedes usar en cualquier proyecto PHP, y es requerido para que los modelos soporten los callbacks usados por el trait MeilisearchSearchable.</p>
</blockquote>
<h2 id="configuraci%C3%B3n-del-cliente-meilisearch-singleton" class="code-line" dir="auto" data-line="31">Configuración del Cliente Meilisearch</h2>
<p class="code-line" dir="auto" data-line="33">Crea el archivo <em>default/app/config/meilisearch.php</em> con la siguiente estructura:</p>



<span id="more-2903"></span>



<pre class="wp-block-code language-php"><code class="" data-line="">&lt;?php
/**
 * MeiliSearch configuration file.
 *
 * This file contains the configuration settings for connecting to MeiliSearch.
 */
return &#091;
    &#039;host&#039; =&gt; &#039;http://127.0.0.1:7700&#039;, // Change the host
    &#039;api_key&#039; =&gt; &#039;&#039;, // Change the key
];
</code></pre>



<h2 id="integrando-meilisearch-con-el-trait-meilisearchsearchabletrait" class="code-line" dir="auto" data-line="63">Trait MeilisearchSearchableTrait</h2>
<p class="code-line" dir="auto" data-line="65">Crea el archivo&nbsp;<em>default/app/libs/meilisearch_searchable_trait.php</em> con el siguiente código:</p>



<pre class="wp-block-code language-php"><code class="" data-line="">&lt;?php

use Meilisearch\Client;

/**
 * Trait MeilisearchSearchableTrait
 */
trait MeilisearchSearchableTrait
{
    /**
     * MeiliSearch client instance.
     */
    protected static ?Client $_meiliClient = null;

    /**
     * Retrieves the MeiliSearch client instance.
     */
    protected static function getMeiliClient(): Client
    {
        if (null !== self::$_meiliClient) {
            return self::$_meiliClient;
        }

        $config = \Config::read(&#039;meilisearch&#039;);
        if (!$config || !is_array($config)) {
            throw new \RuntimeException(&#039;MeiliSearch configuration not found in config file.&#039;);
        }
        $host   = $config&#091;&#039;host&#039;] ?? &#039;http://localhost:7700&#039;;
        $apiKey = $config&#091;&#039;api_key&#039;] ?? &#039;&#039;;

        return self::$_meiliClient = new Client($host, $apiKey);
    }

    /**
     * Returns the index name. By default it returns the table name provided by the model.
     */
    protected static function searchableAs(): string
    {
        return static::getTable();
    }

    /**
     * Converts the model instance to an array for indexing.
     */
    abstract protected function toSearchArray(): array;

    /**
     * Callback executed after a model is created.
     * The new record is automatically added to the MeiliSearch index.
     */
    protected function _afterCreate(): void
    {
        self::getMeiliClient()
            -&gt;index(static::searchableAs())
            -&gt;addDocuments(&#091;$this-&gt;toSearchArray()]);
    }

    /**
     * Callback executed after a model is updated.
     * The updated record is synchronized in the MeiliSearch index.
     */
    protected function _afterUpdate(): void
    {
        self::getMeiliClient()
            -&gt;index(static::searchableAs())
            -&gt;updateDocuments(&#091;$this-&gt;toSearchArray()]);
    }

    /**
     * Deletes a record and synchronizes the deletion with the MeiliSearch index.
     */
    public static function delete($pk): bool
    {
        $deleted = parent::delete($pk);

        if ($deleted) {
            self::getMeiliClient()
                -&gt;index(static::searchableAs())
                -&gt;deleteDocument($pk);
        }

        return $deleted;
    }

    /**
     * Performs a search query on the MeiliSearch index.
     */
    public static function search(string $query, array $options = &#091;]): array
    {
        $results = self::getMeiliClient()
            -&gt;index(static::searchableAs())
            -&gt;search($query, $options);

        return $results-&gt;getHits();
    }

    /**
     * Bulk-imports existing records into the MeiliSearch index.
     */
    public static function importToMeilisearch(int $chunkSize = 500): void
    {
        $offset = 0;

        do {
            $records = static::filter(&quot;LIMIT $chunkSize OFFSET $offset&quot;);
            $data    = &#091;];

            foreach ($records as $record) {
                $data&#091;] = $record-&gt;toSearchArray();
            }

            if (!empty($data)) {
                self::getMeiliClient()
                    -&gt;index(static::searchableAs())
                    -&gt;addDocuments($data);
            }

            $offset += $chunkSize;
        } while (count($records) === $chunkSize);
    }
}
</code></pre>



<h2>Ventajas del Trait MeilisearchSearchable</h2>
<ul>
<li>
<p><strong>Integración simple</strong>: Reutiliza fácilmente la funcionalidad en múltiples modelos.</p>
</li>
<li>
<p><strong>Automatización</strong>: Mantiene sincronizados automáticamente tus modelos con el índice de búsqueda.</p>
</li>
<li>
<p><strong>Flexibilidad</strong>: Puedes personalizar fácilmente el comportamiento de búsqueda por cada modelo.</p>
</li>
<li><strong>Inteligencia Artificial:</strong> Soporte para búsqueda semántica mediante integración con IA (OpenAI u otros proveedores).</li>
</ul>
<h2 class="" data-start="3331" data-end="3432">Cómo utilizar en la práctica un buscador avanzado de texto completo para KumbiaPHP con Meilisearch</h2>



<h3 data-pm-slice="1 1 []">Paso 1: Implementación en Modelos</h3>
<p>A continuación, integra el trait en tus modelos que extiendan de LiteRecord:</p>
<h4>Ejemplo con Modelo Product</h4>



<pre class="wp-block-code language-php"><code class="" data-line="">&lt;?php

use Kumbia\ActiveRecord\LiteRecord;

class Product extends LiteRecord
{
    use MeilisearchSearchableTrait;

    protected static $table = &#039;products&#039;;

    protected function toSearchArray(): array
    {
        return &#091;
            &#039;id&#039; =&gt; $this-&gt;id,
            &#039;name&#039; =&gt; $this-&gt;name,
            &#039;description&#039; =&gt; $this-&gt;description,
            &#039;price&#039; =&gt; $this-&gt;price,
        ];
    }
}</code></pre>



<h4 data-pm-slice="1 1 []">Ejemplo con Modelo Article</h4>



<pre class="wp-block-code language-php"><code class="" data-line="">&lt;?php

use Kumbia\ActiveRecord\LiteRecord;

class Article extends LiteRecord
{
    use MeilisearchSearchableTrait;

    protected static $table = &#039;articles&#039;;

    protected function toSearchArray(): array
    {
        return &#091;
            &#039;id&#039; =&gt; $this-&gt;id,
            &#039;title&#039; =&gt; $this-&gt;title,
            &#039;content&#039; =&gt; $this-&gt;content,
            &#039;author&#039; =&gt; $this-&gt;author,
        ];
    }
}</code></pre>



<p data-pm-slice="1 1 []">Una vez implementado el trait en tus modelos, realizar búsquedas será simple y eficaz. Estos ejemplos prácticos ilustran claramente cómo aprovechar tu nuevo <strong data-start="3591" data-end="3661">buscador avanzado de texto completo para KumbiaPHP con Meilisearch</strong>.</p>
<h3 data-pm-slice="1 1 []">Paso 2: Realizar búsquedas fácilmente</h3>
<p>Ahora puedes realizar búsquedas en tus modelos:</p>



<pre class="wp-block-code language-php"><code class="" data-line="">// Buscar productos
$products = Product::search(&#039;zapatos deportivos&#039;, &#091;&#039;limit&#039; =&gt; 10]);

// Buscar artículos
$articles = Article::search(&#039;tecnología&#039;, &#091;&#039;limit&#039; =&gt; 5]);</code></pre>



<h3 data-pm-slice="1 1 []">Paso 3: Importar datos existentes</h3>
<p>Si ya tienes datos almacenados en tu base de datos, puedes importarlos fácilmente:</p>



<pre class="wp-block-code language-php"><code class="" data-line="">Product::importToMeilisearch();
Article::importToMeilisearch();</code></pre>



<h2 data-pm-slice="1 1 []">Ejemplo de Mielisearch con Controlador y Vista en KumbiaPHP</h2>
<h3>Paso 1: Crea el controlador</h3>
<p>Controlador: <em>app/controllers/products_controller.php</em></p>



<pre class="wp-block-code language-php"><code class="" data-line="">class ProductsController extends AppController
{
    public function search()
    {
        if (Input::hasPost(&#039;query&#039;)) {
            $this-&gt;results = Product::search(Input::post(&#039;query&#039;));
        }
    }
}</code></pre>



<h3 data-pm-slice="1 1 []">Paso 2: Crea la vista</h3>
<p data-pm-slice="1 1 []">Vista: <em>app/views/products/search.phtml</em></p>



<pre class="wp-block-code language-php"><code class="" data-line="">&lt;h1&gt;Buscar productos&lt;/h1&gt;

&lt;?php View::content(); ?&gt;

&lt;?= Form::open(); ?&gt;
    &lt;?= Form::text(&#039;query&#039;, &#039;placeholder=&quot;Buscar...&quot;&#039;) ?&gt;
    &lt;?= Form::submit(&#039;Buscar&#039;) ?&gt;
&lt;?= Form::close(); ?&gt;

&lt;?php if (empty($results) &amp;&amp; Input::post(&#039;query&#039;)): ?&gt;
    &lt;p&gt;No se encontraron resultados.&lt;/p&gt;
    &lt;?php return 1 ?&gt;
&lt;?php endif; ?&gt;

&lt;h2&gt;Resultados&lt;/h2&gt;
&lt;ul&gt;
    &lt;?php foreach ($results as $product): ?&gt;
        &lt;li&gt;
            &lt;strong&gt;&lt;?= h($product&#091;&#039;name&#039;]) ?&gt;&lt;/strong&gt;&lt;br&gt;
            &lt;?= h($product&#091;&#039;description&#039;]) ?&gt;&lt;br&gt;
            Precio: $&lt;?= h($product&#091;&#039;price&#039;]) ?&gt;
        &lt;/li&gt;
    &lt;?php endforeach; ?&gt;
&lt;/ul&gt;
</code></pre>



<p data-pm-slice="1 1 []">La combinación de KumbiaPHP con Meilisearch a través del trait MeilisearchSearchable te permite ofrecer una experiencia superior en búsquedas a tus usuarios. Con la posibilidad de usar IA para búsquedas semánticas, la calidad de los resultados se eleva aún más. La integración es simple, escalable y potente, haciendo que valga la pena el esfuerzo inicial.</p>
<p>¡Prueba esta integración y lleva tus búsquedas al siguiente nivel con KumbiaPHP y Meilisearch!</p>
<p>La entrada <a href="https://kumbiaphp.com/blog/2025/04/19/buscador-avanzado-texto-completo-kumbiaphp-meilisearch/">Buscador avanzado de texto completo para KumbiaPHP con Meilisearch</a> se publicó primero en <a href="https://kumbiaphp.com/blog">KumbiaPHP Framework PHP en español</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://kumbiaphp.com/blog/2025/04/19/buscador-avanzado-texto-completo-kumbiaphp-meilisearch/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2903</post-id>	</item>
		<item>
		<title>Cómo crear modelos de forma correcta</title>
		<link>https://kumbiaphp.com/blog/2022/09/10/crear-modelos-de-forma-correcta/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=crear-modelos-de-forma-correcta</link>
					<comments>https://kumbiaphp.com/blog/2022/09/10/crear-modelos-de-forma-correcta/#comments</comments>
		
		<dc:creator><![CDATA[Nelson Rojas]]></dc:creator>
		<pubDate>Sat, 10 Sep 2022 17:34:02 +0000</pubDate>
				<category><![CDATA[Tutoriales y screencast]]></category>
		<guid isPermaLink="false">https://kumbiaphp.com/blog/?p=2676</guid>

					<description><![CDATA[<p>La entrada <a href="https://kumbiaphp.com/blog/2022/09/10/crear-modelos-de-forma-correcta/">Cómo crear modelos de forma correcta</a> se publicó primero en <a href="https://kumbiaphp.com/blog">KumbiaPHP Framework PHP en español</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Bienvenidos a este post que trata sobre el cómo crear modelos de forma correcta para aplicaciones que utilizan el patrón de diseño MVC: Modelo, Vista, Controlador.</p>
<p>Una parte importante del trabajo dentro de un Framework MVC es el buen uso de los Modelos. </p>
<p>El modelo es <strong>responsable de mantener el estado de la aplicación</strong>. A veces este estado es transitorio, y dura sólo un par de interacciones con el usuario. Otras veces el estado es permanente y se almacena fuera de la aplicación, a menudo en una base de datos.</p>
<p>Un modelo es algo más que datos; impone todas las reglas de negocio que se aplican a esos datos. Por ejemplo, si un descuento no debe aplicarse a los pedidos de menos de de 20 euros, el modelo aplicará la restricción. Esto tiene sentido; al poner la implementación de estas reglas de negocio en el modelo, nos aseguramos de que nada más en la aplicación puede hacer que nuestros datos <strong>no sean válidos</strong>. El modelo actúa como tanto un <strong>guardián</strong> como un <strong>almacén de datos</strong>.</p>
<p><span id="more-2676"></span></p>
<p>Otra definición para el modelo es la <a href="https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller" target="_blank" rel="noopener">siguiente</a>: es el componente central del patrón (MVC). Es la estructura de datos dinámica de la aplicación, independiente de la interfaz de usuario. Gestiona directamente los datos, la lógica y las reglas de la aplicación.</p>
<p>En muchos casos, especialmente cuando uno comienza a trabajar en MVC, se cree que los modelos son <strong>únicamente</strong> para la gestión de la persistencia y la consulta de los datos de una base de datos (o de un repositorio)</p>
<h2>Fundamentos</h2>
<p>Antes de ahondar en los ejemplos y en los errores clásicos, nos gustaría mostrarte una imagen que puede ser de ayuda respecto de la forma en la que deberíamos construir nuestras aplicaciones usando el patrón descrito por <strong>Trygve Reenskaug</strong> (MVC)</p>
<p> </p>


<div class="wp-block-image">
<figure class="aligncenter size-full"><a href="https://kumbiaphp.com/blog/wp-content/uploads/2022/06/UrtaH.png"><img loading="lazy" decoding="async" width="596" height="232" src="https://kumbiaphp.com/blog/wp-content/uploads/2022/06/UrtaH.png" alt="comparación entre mala y buena implementación de modelos en mvc" class="wp-image-2678" srcset="https://kumbiaphp.com/blog/wp-content/uploads/2022/06/UrtaH.png 596w, https://kumbiaphp.com/blog/wp-content/uploads/2022/06/UrtaH-300x117.png 300w" sizes="auto, (max-width: 596px) 100vw, 596px" /></a></figure>
</div>


<p>La imagen, que es gentileza del Framework CakePHP, nos indica que una aplicación mal diseñada (Bad cake) tiene mucho código en los controladores y poco en las vistas y modelos. En la práctica, los controladores deberían servirnos principalmente para gestionar el Routing (las urls), interactuar con los modelos y despachar las vistas. En contraposición, una buena implementación (Good cake), debería contener más código en los modelos y menos en las vistas y controladores.</p>
<p>Volvamos un poco a lo que se mencionaba sobre el problema de los recién iniciados en MVC. Si bien es común que un modelo gestione datos de una base de datos, también sirve para gestionar «cosas» que no tienen relación con ello. Un ejemplo puede ser un modelo para un carro de compras. Es completamente factible llevar a cabo esta tarea sin persistencia en el DBMS (Database Management System). Bastaría con hacerlo con el objeto de sesión. Por otro lado, un modelo también podría encargarse de los pagos electrónicos, y luego apoyarse de otro que persista datos. Un modelo podría estar dedicado a la realización de cálculos específicos, otro del envío de notificaciones (SMS, Whatsapp, e-mail, etc), otro de la ejecución de tareas por shell dentro del servidor, y así sucesivamente.</p>
<p><strong>¿Qué es lo más común?</strong></p>
<p>Que las personas definan un modelo heredando de la clase del ORM (Object Relational Mapping) y, por ejemplo, en el caso de las notificaciones o el carro de compras, bastaría con que se utilizara una clase simple.</p>
<p>Vale, que aún no hay ejemplos porque nos quedan algunos <strong>fundamentos</strong> que debemos considerar.</p>
<h3>DRY</h3>
<p>Para muchos desconocido por sus siglas, pero viene del inglés <strong>Don&#8217;t Repeat Yourself</strong>. En buen castellano sería «No te repitas». ¿Qué significa esto? Significa que debemos gestionar cada «trozo de código» a su labor respectiva, en un único lugar. ¿Y qué tiene de malo copiar y pegar código? Cuando uno tiene mucho código repetido se rompe el principio DRY.</p>
<p>La repetición puede ser principalmente por desconocimiento de las herramientas que provee el Framework, o la clase de la que uno hereda. Por lo tanto, <strong>haz tu tarea de estudiante</strong>: <em>revisa los métodos, la documentación y luego ponte manos a la obra para que <strong>no repitas cosas</strong> que ya están implementadas</em> (lo que comúnmente llamamos reinventar la rueda)</p>
<p>Una vez que no tengas ruedas repetidas, verás que realizar <strong>modificaciones</strong> será una tarea sencilla, evitando así la <strong>fragilidad</strong> del código.</p>
<h3>OOP</h3>
<p>En términos de Orientación a Objetos, muchas veces no tenemos tan clara la diferencia entre el uso de la herencia, métodos estáticos y métodos dinámicos. Este tipo de temas los veremos en los ejemplos.</p>
<h3>El ORM</h3>
<p>Debemos familiarizarnos con la librería que gestiona la persistencia y las consultas al motor de bases de datos, en especial sus métodos, propiedades y los <strong>callbacks</strong>. En esto último quisiera detenerme un momento. Los callbacks son la analogía a lo que en un motor de base de datos se conoce como <strong>triggers</strong> (disparadores). Existen diferentes tipos de triggers, pero en generar se clasifican en los que se ejecutan <strong>antes</strong> de una acción y los que lo hacen <strong>después</strong> (before y after respectivamente)</p>
<p>El nuevo <a href="https://github.com/KumbiaPHP/ActiveRecord" target="_blank" rel="noopener"><strong>LiteRecord</strong></a> implementa callbacks para las acciones de creación (_beforeCreate, _afterCreate), para actualización (_beforeUpdate, _afterUpdate) y para guardar (_beforeSave, _afterSave)</p>
<p>En palabras simples, si el modelo encuentra un método _beforeAlgo, ejecutará dicha función antes de que se ejecute el método «Algo» (asumiendo que «Algo» puede ser Create, Save, Update). Por otro lado un _afterAlgo, se ejecutará luego que la función «Algo» haya finalizado.</p>
<p>Estos temas también los iremos tratando con casos cotidianos. Puedes checar su documentación en este <a href="https://github.com/KumbiaPHP/ActiveRecord/blob/master/LiteRecord.php" target="_blank" rel="noopener">enlace</a>.</p>
<h3>Traits </h3>
<p>Desde la versión de PHP 5.4 se implementan los <a href="https://www.php.net/manual/es/language.oop5.traits.php" target="_blank" rel="noopener">Traits</a> (rasgos, características) Es una buena estrategia para continuar con el principio DRY. De pronto tienes propiedades o métodos que son compartidos entre diferentes clases. Puedes extraer esos métodos en un trait y luego indicar que la clase implementa dichos «rasgos». Así tendrás un único lugar para ellos y finalmente, si hay menos código «innecesario o repetitivo», habrá menos errores y será más fácil de hacer mantención/corrección del mismo.</p>
<p> </p>
<p> </p>
<p>La entrada <a href="https://kumbiaphp.com/blog/2022/09/10/crear-modelos-de-forma-correcta/">Cómo crear modelos de forma correcta</a> se publicó primero en <a href="https://kumbiaphp.com/blog">KumbiaPHP Framework PHP en español</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://kumbiaphp.com/blog/2022/09/10/crear-modelos-de-forma-correcta/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2676</post-id>	</item>
		<item>
		<title>Live Reload en PHP</title>
		<link>https://kumbiaphp.com/blog/2020/08/18/live-reload-php/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=live-reload-php</link>
					<comments>https://kumbiaphp.com/blog/2020/08/18/live-reload-php/#respond</comments>
		
		<dc:creator><![CDATA[HenryStivens]]></dc:creator>
		<pubDate>Tue, 18 Aug 2020 05:00:00 +0000</pubDate>
				<category><![CDATA[IDE]]></category>
		<category><![CDATA[Tutoriales y screencast]]></category>
		<category><![CDATA[livereload]]></category>
		<category><![CDATA[vscode]]></category>
		<guid isPermaLink="false">https://kumbiaphp.com/blog/?p=2536</guid>

					<description><![CDATA[<p>La entrada <a href="https://kumbiaphp.com/blog/2020/08/18/live-reload-php/">Live Reload en PHP</a> se publicó primero en <a href="https://kumbiaphp.com/blog">KumbiaPHP Framework PHP en español</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>En el siguiente video mostramos como configurar<a href="https://code.visualstudio.com/"> Visual Studio Code</a> y los navegadores más populares, Google Chrome y Firefox,&nbsp; para obtener live reload o recarga automática funcionando correctamente con KumbiaPHP.</p>
<h2>Vscode, Google Chrome y Firefox con livereload</h2>
<figure style="text-align: center;"><iframe src="https://www.youtube.com/embed/XXYpuMhkbHk" allowfullscreen="allowfullscreen" loading="lazy" width="560" height="315" frameborder="0"></iframe>
<figcaption>Live Reload en PHP</figcaption>
</figure>
<p>Extensión LiveReload para Visual Studio Code: <a href="https://marketplace.visualstudio.com/items?itemName=ziishaned.livereload">https://marketplace.visualstudio.com/items?itemName=ziishaned.livereload</a></p>
<p>Extensión LiveReload++ para Google Chrome: <a href="https://chrome.google.com/webstore/detail/livereload%20%20/ciehpookapcdlakedibajeccomagbfab">https://chrome.google.com/webstore/detail/livereload++/ciehpookapcdlakedibajeccomagbfab</a></p>
<p>Extensión LiveReload para Firefox: <a href="https://addons.mozilla.org/es/firefox/addon/livereload-web-extension/">https://addons.mozilla.org/es/firefox/addon/livereload-web-extension/</a></p>
<p>La entrada <a href="https://kumbiaphp.com/blog/2020/08/18/live-reload-php/">Live Reload en PHP</a> se publicó primero en <a href="https://kumbiaphp.com/blog">KumbiaPHP Framework PHP en español</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://kumbiaphp.com/blog/2020/08/18/live-reload-php/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2536</post-id>	</item>
		<item>
		<title>Compartir el core para diferentes aplicaciones</title>
		<link>https://kumbiaphp.com/blog/2020/08/05/compartir-el-core-para-diferentes-aplicaciones/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=compartir-el-core-para-diferentes-aplicaciones</link>
					<comments>https://kumbiaphp.com/blog/2020/08/05/compartir-el-core-para-diferentes-aplicaciones/#respond</comments>
		
		<dc:creator><![CDATA[HenryStivens]]></dc:creator>
		<pubDate>Wed, 05 Aug 2020 04:00:15 +0000</pubDate>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Tutoriales y screencast]]></category>
		<category><![CDATA[core]]></category>
		<guid isPermaLink="false">https://kumbiaphp.com/blog/?p=2527</guid>

					<description><![CDATA[<p>Este el tercer video donde mostramos una característca opcional que podemos usar al crear o desplegar nuestras aplicaciones Compartir&#8230;</p>
<p>La entrada <a href="https://kumbiaphp.com/blog/2020/08/05/compartir-el-core-para-diferentes-aplicaciones/">Compartir el core para diferentes aplicaciones</a> se publicó primero en <a href="https://kumbiaphp.com/blog">KumbiaPHP Framework PHP en español</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Este el tercer video donde mostramos una característca opcional que podemos usar al crear o desplegar nuestras aplicaciones</p>
<figure style="text-align: center;"><iframe loading="lazy" src="https://www.youtube.com/embed/E2oh8YiV8Zg" width="560" height="315" frameborder="0" allowfullscreen="allowfullscreen"></iframe><figcaption>Compartir el core de KumbiaPHP</figcaption></figure>
<p>La entrada <a href="https://kumbiaphp.com/blog/2020/08/05/compartir-el-core-para-diferentes-aplicaciones/">Compartir el core para diferentes aplicaciones</a> se publicó primero en <a href="https://kumbiaphp.com/blog">KumbiaPHP Framework PHP en español</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://kumbiaphp.com/blog/2020/08/05/compartir-el-core-para-diferentes-aplicaciones/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2527</post-id>	</item>
		<item>
		<title>Instalación de XAMPP y configuración de VirtualHost</title>
		<link>https://kumbiaphp.com/blog/2020/08/04/instalacion-de-xampp-y-configuracion-de-virtualhost/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=instalacion-de-xampp-y-configuracion-de-virtualhost</link>
					<comments>https://kumbiaphp.com/blog/2020/08/04/instalacion-de-xampp-y-configuracion-de-virtualhost/#respond</comments>
		
		<dc:creator><![CDATA[HenryStivens]]></dc:creator>
		<pubDate>Tue, 04 Aug 2020 11:42:44 +0000</pubDate>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Tutoriales y screencast]]></category>
		<category><![CDATA[apache]]></category>
		<category><![CDATA[Virtua Host]]></category>
		<category><![CDATA[xampp]]></category>
		<guid isPermaLink="false">https://kumbiaphp.com/blog/?p=2511</guid>

					<description><![CDATA[<p>Instalar KumbiaPHP en Windows usando XAMPP Configurar virtual host en XAMPP para KumbiaPHP</p>
<p>La entrada <a href="https://kumbiaphp.com/blog/2020/08/04/instalacion-de-xampp-y-configuracion-de-virtualhost/">Instalación de XAMPP y configuración de VirtualHost</a> se publicó primero en <a href="https://kumbiaphp.com/blog">KumbiaPHP Framework PHP en español</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>Dos nuevos videos publicamos esta semana para iniciarnos en el mundo de KumbiaPHP, el primer video trata sobre la&#8230;</p>
<h2>Instalación de KumbiaPHP usando XAMPP en Windows</h2>


<figure style="text-align: center;"><iframe loading="lazy" src="https://www.youtube.com/embed/6urWXloT-so" width="560" height="315" frameborder="0" allowfullscreen="allowfullscreen"></iframe>
<figcaption>Instalar KumbiaPHP en Windows usando XAMPP</figcaption>
</figure>


<p>El segundo video trata sobre la&#8230;</p>
<h2>Configuración de virtual host en Apache para usarlo con KumbiaPHP</h2>


<figure style="text-align: center;"><iframe loading="lazy" src="https://www.youtube.com/embed/ucvLTi2R660" width="560" height="315" frameborder="0" allowfullscreen="allowfullscreen"></iframe>
<figcaption>Configurar virtual host en XAMPP para KumbiaPHP</figcaption>
</figure>

<p>La entrada <a href="https://kumbiaphp.com/blog/2020/08/04/instalacion-de-xampp-y-configuracion-de-virtualhost/">Instalación de XAMPP y configuración de VirtualHost</a> se publicó primero en <a href="https://kumbiaphp.com/blog">KumbiaPHP Framework PHP en español</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://kumbiaphp.com/blog/2020/08/04/instalacion-de-xampp-y-configuracion-de-virtualhost/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2511</post-id>	</item>
		<item>
		<title>Servidor PHP desde la consola Linux de Windows</title>
		<link>https://kumbiaphp.com/blog/2020/03/04/servidor-php-desde-la-consola-linux-de-windows/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=servidor-php-desde-la-consola-linux-de-windows</link>
					<comments>https://kumbiaphp.com/blog/2020/03/04/servidor-php-desde-la-consola-linux-de-windows/#comments</comments>
		
		<dc:creator><![CDATA[Nelson Rojas]]></dc:creator>
		<pubDate>Wed, 04 Mar 2020 10:50:11 +0000</pubDate>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Tutoriales y screencast]]></category>
		<category><![CDATA[servidor php]]></category>
		<category><![CDATA[windows]]></category>
		<category><![CDATA[wsl]]></category>
		<guid isPermaLink="false">https://www.kumbiaphp.com/blog/?p=2276</guid>

					<description><![CDATA[<p>Crear usuario y contraseña de la consola de linux Servidor PHP local</p>
<p>La entrada <a href="https://kumbiaphp.com/blog/2020/03/04/servidor-php-desde-la-consola-linux-de-windows/">Servidor PHP desde la consola Linux de Windows</a> se publicó primero en <a href="https://kumbiaphp.com/blog">KumbiaPHP Framework PHP en español</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>En esta ocasión vamos a hablar de la característica de <strong><em>Windows 10</em> que nos permite contar con nuestro servidor PHP desde la consola Linux</strong>, y cómo hacer uso de <em>KumbiaPHP</em> con los requerimientos mínimos para dicha consola.&nbsp;</p>
<p>Tendremos un <strong>servidor local de PHP</strong> perfecto para desarrollo, <strong>sin usar WAMP o XAMPP server</strong>.</p>
<p>Antes de comenzar, te dejamos un enlace donde se explican las implicancias del <em>WSL</em> (Windows Subsystem for Linux) <a href="https://es.wikipedia.org/wiki/Windows_Subsystem_for_Linux" target="_blank" rel="noopener noreferrer">https://es.wikipedia.org/wiki/Windows_Subsystem_for_Linux</a></p>
<p>Vamos con los requisitos. Lo primero que necesitamos es habilitar la caracterísca de <em>Subsistema Linux desde Windows</em>.<span id="more-2276"></span></p>
<h2>Instalar WSL en Windows 10</h2>
<p>Para ello hacemos clic en inicio y escribimos <code class="" data-line="">&lt;em&gt;Características de Windows&lt;/em&gt;</code> (en mi caso se verá diferente porque llevo una versión de <em>Windows</em> en inglés)</p>
<p>&nbsp;</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="835" height="677" src="https://www.kumbiaphp.com/blog/wp-content/uploads/2020/02/00.png" alt="" class="wp-image-2277" srcset="https://kumbiaphp.com/blog/wp-content/uploads/2020/02/00.png 835w, https://kumbiaphp.com/blog/wp-content/uploads/2020/02/00-300x243.png 300w, https://kumbiaphp.com/blog/wp-content/uploads/2020/02/00-768x623.png 768w" sizes="auto, (max-width: 835px) 100vw, 835px" /></figure>



<p>Luego buscaremos al final de la lista el <em>Subsistema Linux para Windows</em> (ver imagen siguiente)</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="416" height="369" src="https://www.kumbiaphp.com/blog/wp-content/uploads/2020/02/02.png" alt="" class="wp-image-2278" srcset="https://kumbiaphp.com/blog/wp-content/uploads/2020/02/02.png 416w, https://kumbiaphp.com/blog/wp-content/uploads/2020/02/02-300x266.png 300w" sizes="auto, (max-width: 416px) 100vw, 416px" /></figure>



<p>Lo seleccionamos haciendo clic en la casilla de la izquierda, y finalizamos picando en el botón OK para que los cambios sean aplicados.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="656" height="482" src="https://www.kumbiaphp.com/blog/wp-content/uploads/2020/02/03.png" alt="" class="wp-image-2279" srcset="https://kumbiaphp.com/blog/wp-content/uploads/2020/02/03.png 656w, https://kumbiaphp.com/blog/wp-content/uploads/2020/02/03-300x220.png 300w" sizes="auto, (max-width: 656px) 100vw, 656px" /></figure>



<p>Tendremos que reiniciar para que la configuración se vea actualizada.</p>
<h2>Seleccionar la distribución de Linux en la Tienda de Microsoft</h2>
<p>Una vez hecho eso, iniciaremos a la aplicación <em>Tienda de Microsoft</em> (<em>Microsoft Store</em>) y usando su buscador, escribiremos la palabra <em>linux</em>.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="804" height="633" src="https://www.kumbiaphp.com/blog/wp-content/uploads/2020/02/05.png" alt="" class="wp-image-2280" srcset="https://kumbiaphp.com/blog/wp-content/uploads/2020/02/05.png 804w, https://kumbiaphp.com/blog/wp-content/uploads/2020/02/05-300x236.png 300w, https://kumbiaphp.com/blog/wp-content/uploads/2020/02/05-768x605.png 768w" sizes="auto, (max-width: 804px) 100vw, 804px" /></figure>



<p>La lista de opciones es variada pues se cuenta con <strong><em>Ubuntu</em>, <em>Kali</em>, <em>Debian</em>, <em>OpenSuse</em>, entre otros</strong>. Para cuestiones de demostración he seleccionado la opción Debian (aunque en otra máquina lo he probado con <em>Ubuntu</em> 18.04).</p>
<p>Bastará con seleccionar la opción de vuestro gusto, y luego presionar el botón Obtener (Get en mi caso)</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="807" height="640" src="https://www.kumbiaphp.com/blog/wp-content/uploads/2020/02/06.png" alt="" class="wp-image-2281" srcset="https://kumbiaphp.com/blog/wp-content/uploads/2020/02/06.png 807w, https://kumbiaphp.com/blog/wp-content/uploads/2020/02/06-300x238.png 300w, https://kumbiaphp.com/blog/wp-content/uploads/2020/02/06-768x609.png 768w" sizes="auto, (max-width: 807px) 100vw, 807px" /></figure>



<p>Puede que el instalador te pregunte, si quieres mantener sincronizadas tus máquinas de acuerdo a tu cuenta. En mi caso, prefiero que sólo sea instalado en esta máquina, sin importar la sincronización posterior (para ello te requerirá iniciar sesión con una cuenta de <em>Windows Live</em> &#8211; <em>Hotmail</em>, <em>Outlook</em> u otra)</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="510" height="176" src="https://www.kumbiaphp.com/blog/wp-content/uploads/2020/02/07.png" alt="" class="wp-image-2282" srcset="https://kumbiaphp.com/blog/wp-content/uploads/2020/02/07.png 510w, https://kumbiaphp.com/blog/wp-content/uploads/2020/02/07-300x104.png 300w" sizes="auto, (max-width: 510px) 100vw, 510px" /></figure>



<p>En este diálogo he seleccionado «No, gracias». Luego de la respuesta, ha comenzado el proceso de instalación.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="802" height="633" src="https://www.kumbiaphp.com/blog/wp-content/uploads/2020/02/09.png" alt="" class="wp-image-2283" srcset="https://kumbiaphp.com/blog/wp-content/uploads/2020/02/09.png 802w, https://kumbiaphp.com/blog/wp-content/uploads/2020/02/09-300x237.png 300w, https://kumbiaphp.com/blog/wp-content/uploads/2020/02/09-768x606.png 768w" sizes="auto, (max-width: 802px) 100vw, 802px" /></figure>





<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="802" height="631" src="https://www.kumbiaphp.com/blog/wp-content/uploads/2020/02/10.png" alt="" class="wp-image-2284" srcset="https://kumbiaphp.com/blog/wp-content/uploads/2020/02/10.png 802w, https://kumbiaphp.com/blog/wp-content/uploads/2020/02/10-300x236.png 300w, https://kumbiaphp.com/blog/wp-content/uploads/2020/02/10-768x604.png 768w" sizes="auto, (max-width: 802px) 100vw, 802px" /></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="979" height="514" src="https://www.kumbiaphp.com/blog/wp-content/uploads/2020/02/11.png" alt="" class="wp-image-2285" srcset="https://kumbiaphp.com/blog/wp-content/uploads/2020/02/11.png 979w, https://kumbiaphp.com/blog/wp-content/uploads/2020/02/11-300x158.png 300w, https://kumbiaphp.com/blog/wp-content/uploads/2020/02/11-768x403.png 768w, https://kumbiaphp.com/blog/wp-content/uploads/2020/02/11-940x494.png 940w" sizes="auto, (max-width: 979px) 100vw, 979px" /></figure>



<h2 class="wp-block-heading">Crear usuario y contraseña de la consola de linux</h2>



<p>Cuando la configuración de la <em>consola linux</em> haya finalizado, nos pedirá crear un usuario con nombre y contraseña.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="890" height="272" src="https://www.kumbiaphp.com/blog/wp-content/uploads/2020/02/13.png" alt="" class="wp-image-2286" srcset="https://kumbiaphp.com/blog/wp-content/uploads/2020/02/13.png 890w, https://kumbiaphp.com/blog/wp-content/uploads/2020/02/13-300x92.png 300w, https://kumbiaphp.com/blog/wp-content/uploads/2020/02/13-768x235.png 768w" sizes="auto, (max-width: 890px) 100vw, 890px" /></figure>



<p>Noten que el nombre de usuario de la consola, <strong>no tiene por qué coincidir con el nombre de usuario de la máquina de <em>Windows</em></strong>. Una vez creado el usuario habremos finalizado la instalación de la <em>consola de Linux</em>!</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="826" height="333" src="https://www.kumbiaphp.com/blog/wp-content/uploads/2020/02/14.png" alt="" class="wp-image-2287" srcset="https://kumbiaphp.com/blog/wp-content/uploads/2020/02/14.png 826w, https://kumbiaphp.com/blog/wp-content/uploads/2020/02/14-300x121.png 300w, https://kumbiaphp.com/blog/wp-content/uploads/2020/02/14-768x310.png 768w" sizes="auto, (max-width: 826px) 100vw, 826px" /></figure>



<p>Entonces ya tenemos nuestra estación Linux completamente funcional.&nbsp;</p>
<h2>Actualizar paquetes de Linux</h2>
<p>En los derivados de <em>Debian</em> (como <em>Ubuntu</em> y <em>Kali</em>) les recomiendo comenzar ejecutando el comando:</p>
<pre class="  language-bash"><code class="" data-line="">&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;apt-get&lt;/span&gt; update</code></pre>
<p>Con ello cargarás los repositorios de paquetes que podrás usar posteriormente.</p>
<h2>Instalar PHP y MariaDB (MySql) en la consola Linux de Windows</h2>
<p>Para usar <em>Debian</em> y derivados, con los requerimientos mínimos de desarrollo kumbiero necesitamos hacer la siguiente instalación</p>
<pre class="  language-bash"><code class="" data-line="">&lt;span class=&quot;token function&quot;&gt;sudo&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;apt-get&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; php php-cli php-mysql mariadb-server php-mbstring &lt;span class=&quot;token function&quot;&gt;git&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;wget&lt;/span&gt; unzip</code></pre>
<h2>Instalar KumbiaPHP framework</h2>
<p>Una vez que hemos finalizado la instalación, podemos hacer una prueba descargando la versión de <em>KumbiaPHP</em> desde la <a href="http://www.kumbiaphp.com" target="_blank" rel="noopener noreferrer">página principal del proyecto</a></p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="312" src="https://www.kumbiaphp.com/blog/wp-content/uploads/2020/03/31-1024x312.png" alt="" class="wp-image-2358" srcset="https://kumbiaphp.com/blog/wp-content/uploads/2020/03/31-1024x312.png 1024w, https://kumbiaphp.com/blog/wp-content/uploads/2020/03/31-300x91.png 300w, https://kumbiaphp.com/blog/wp-content/uploads/2020/03/31-768x234.png 768w, https://kumbiaphp.com/blog/wp-content/uploads/2020/03/31-940x286.png 940w, https://kumbiaphp.com/blog/wp-content/uploads/2020/03/31.png 1363w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>Lo hacemos desde el icono de descarga para el formato tar. Hacemos clic con el botón secundario (normalmente el derecho) y copiamos el link desde el botón Copiar enlace (Copy link)</p>
<p>Luego desde la consola escribimos wget y pegamos lo que tenemos en el portapaleles. Deberíamos lograr una línea de ejecución como la siguiente:</p>
<pre class="  language-bash"><code class="" data-line="">&lt;span class=&quot;token function&quot;&gt;wget&lt;/span&gt; https://github.com/KumbiaPHP/KumbiaPHP/archive/v1.0.0.tar.gz</code></pre>
<p>&nbsp;</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="982" height="437" src="https://www.kumbiaphp.com/blog/wp-content/uploads/2020/03/33.png" alt="" class="wp-image-2362" srcset="https://kumbiaphp.com/blog/wp-content/uploads/2020/03/33.png 982w, https://kumbiaphp.com/blog/wp-content/uploads/2020/03/33-300x134.png 300w, https://kumbiaphp.com/blog/wp-content/uploads/2020/03/33-768x342.png 768w, https://kumbiaphp.com/blog/wp-content/uploads/2020/03/33-940x418.png 940w" sizes="auto, (max-width: 982px) 100vw, 982px" /></figure>



<p>Descomprimimos la descarga:</p>
<pre class="  language-bash"><code class="" data-line="">&lt;span class=&quot;token function&quot;&gt;tar&lt;/span&gt; xvfz v1.0.0.tar.gz</code></pre>
<p>Y renombramos la carpeta resultante con un nombre que tenga relación con el trabajo que llevaremos a cabo (usando el comando <code class="" data-line="">mv</code>)</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="579" height="171" src="https://www.kumbiaphp.com/blog/wp-content/uploads/2020/03/35.png" alt="" class="wp-image-2361" srcset="https://kumbiaphp.com/blog/wp-content/uploads/2020/03/35.png 579w, https://kumbiaphp.com/blog/wp-content/uploads/2020/03/35-300x89.png 300w" sizes="auto, (max-width: 579px) 100vw, 579px" /></figure>



<p>Finalizamos la prueba de instalación entrando en la carpeta que hemos creado hasta llegar a <code class="" data-line="">&lt;strong&gt;default/app&lt;/strong&gt;</code></p>
<p>&nbsp;</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="455" height="89" src="https://www.kumbiaphp.com/blog/wp-content/uploads/2020/02/22.png" alt="" class="wp-image-2291" srcset="https://kumbiaphp.com/blog/wp-content/uploads/2020/02/22.png 455w, https://kumbiaphp.com/blog/wp-content/uploads/2020/02/22-300x59.png 300w" sizes="auto, (max-width: 455px) 100vw, 455px" /></figure>



<h2 class="wp-block-heading">Servidor PHP local</h2>



<p>Sin instalar Apache o Nginx,&nbsp; escribiendo el comando:</p>
<pre class=" language-bash"><code class="" data-line="">bin/phpserver</code></pre>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="957" height="642" src="https://www.kumbiaphp.com/blog/wp-content/uploads/2020/02/23.png" alt="" class="wp-image-2292" srcset="https://kumbiaphp.com/blog/wp-content/uploads/2020/02/23.png 957w, https://kumbiaphp.com/blog/wp-content/uploads/2020/02/23-300x201.png 300w, https://kumbiaphp.com/blog/wp-content/uploads/2020/02/23-768x515.png 768w, https://kumbiaphp.com/blog/wp-content/uploads/2020/02/23-940x631.png 940w, https://kumbiaphp.com/blog/wp-content/uploads/2020/02/23-440x294.png 440w" sizes="auto, (max-width: 957px) 100vw, 957px" /></figure>



<p><em>Windows</em> nos preguntará, si acaso queremos permitir conexiones desde redes internas o desde fuera de la red. Para efectos de prueba he seleccionado ambas opciones y he presionado el botón «Permitir acceso» (Allow access)</p>
<p>Entonces, nuestra aplicación recién instalada de KumbiaPHP estará disponible desde la dirección http://0.0.0.0:8001. En caso que no resulte también puedes invocarla usando la url de http://localhost:8001, o usando http://127.0.0.1:8001, o incluso la dirección ip interna de tu máquina como por ejemplo http://192.168.1.101:8001. Esta última opción nos servirá para hacer pruebas desde otros dispositivos conectados a la misma red (por ejemplo desde un tablet, o un móvil)</p>
<p>&nbsp;</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="474" src="https://www.kumbiaphp.com/blog/wp-content/uploads/2020/02/25-1024x474.png" alt="" class="wp-image-2293" srcset="https://kumbiaphp.com/blog/wp-content/uploads/2020/02/25-1024x474.png 1024w, https://kumbiaphp.com/blog/wp-content/uploads/2020/02/25-300x139.png 300w, https://kumbiaphp.com/blog/wp-content/uploads/2020/02/25-768x355.png 768w, https://kumbiaphp.com/blog/wp-content/uploads/2020/02/25-940x435.png 940w, https://kumbiaphp.com/blog/wp-content/uploads/2020/02/25.png 1366w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<h2>Permisos de la base de datos (Mysql, MariaDB, Postresql, otros)</h2>
<p>Un dato final, es si usamos MySQL o MariaDB o Postgresql, Windows nos preguntará si queremos dar acceso a dichos servicios, tal como ha hecho cuando hemos lanzado <code class="" data-line="">&lt;strong&gt;bin/phpserver&lt;/strong&gt;</code>. En dicho caso sólo les recomiendo habilitar el uso en el equipo y la red local. No para el exterior. Aunque esta es una decisión que debe tomar cada uno.</p>
<p><strong>¿Y qué hemos ganado con lanzar KumbiaPHP con el comando bin/phpserver?</strong></p>
<p>Pues la ventana en la que lo hemos lanzado, se ha convertido en una ventana de log de utilización, por la que veremos cada una de las acciones que realice el framework mientras estamos trabajando con él</p>
<p>Y lo más importante, también <strong>veremos los errores al instante, para depurar más rápidamente nuestas aplicaciones</strong>.</p>
<p>&nbsp;</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="632" height="273" src="https://www.kumbiaphp.com/blog/wp-content/uploads/2020/02/27.png" alt="" class="wp-image-2295" srcset="https://kumbiaphp.com/blog/wp-content/uploads/2020/02/27.png 632w, https://kumbiaphp.com/blog/wp-content/uploads/2020/02/27-300x130.png 300w" sizes="auto, (max-width: 632px) 100vw, 632px" /></figure>



<p>Y hasta aquí nuestra publicación :-)</p>
<p>Esperamos que les sea de utilidad y que con ello tengan nuevas opciones de disfrutar programando con el <a href="https://www.kumbiaphp.com/blog/about/">framework más rápido</a> del oeste!</p>
<p>Saludos a todos nuestros colegas kumbieros!</p>
<p><strong>Post data: si eres nuevo por aquí te recomendamos ver algunos de nuestros posts para los recién llegados:</strong></p>
<p>KumbiaPHP essentials</p>
<p><a href="https://www.kumbiaphp.com/blog/2016/05/26/kumbiaphp-essentials/"><img loading="lazy" decoding="async" class="alignnone size-medium" src="https://i.vimeocdn.com/video/572670979.jpg?mw=800&amp;mh=449" alt="KumbiaPHP introducción" width="799" height="449" /></a></p>
<p>Scaffolding con KumbiaPHP</p>
<p><a href="https://www.kumbiaphp.com/blog/2017/04/03/scaffolding-para-crud-abm-sencillos-y-no-tanto-primera-parte/"><img loading="lazy" decoding="async" class="alignnone wp-image-2300 size-large" src="https://www.kumbiaphp.com/blog/wp-content/uploads/2020/02/scaffolding-1024x576.jpg" alt="Scaffolding con KumbiaPHP" width="940" height="529" srcset="https://kumbiaphp.com/blog/wp-content/uploads/2020/02/scaffolding-1024x576.jpg 1024w, https://kumbiaphp.com/blog/wp-content/uploads/2020/02/scaffolding-300x169.jpg 300w, https://kumbiaphp.com/blog/wp-content/uploads/2020/02/scaffolding-768x432.jpg 768w, https://kumbiaphp.com/blog/wp-content/uploads/2020/02/scaffolding-940x529.jpg 940w, https://kumbiaphp.com/blog/wp-content/uploads/2020/02/scaffolding.jpg 1058w" sizes="auto, (max-width: 940px) 100vw, 940px" /></a></p>
<p>Dicho esto,</p>
<p>Larga vida a KumbiaPHP!</p>
<p>La entrada <a href="https://kumbiaphp.com/blog/2020/03/04/servidor-php-desde-la-consola-linux-de-windows/">Servidor PHP desde la consola Linux de Windows</a> se publicó primero en <a href="https://kumbiaphp.com/blog">KumbiaPHP Framework PHP en español</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://kumbiaphp.com/blog/2020/03/04/servidor-php-desde-la-consola-linux-de-windows/feed/</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2276</post-id>	</item>
		<item>
		<title>Exportar tabla HTML a PDF</title>
		<link>https://kumbiaphp.com/blog/2019/04/29/exportar-tabla-html-a-pdf/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=exportar-tabla-html-a-pdf</link>
					<comments>https://kumbiaphp.com/blog/2019/04/29/exportar-tabla-html-a-pdf/#respond</comments>
		
		<dc:creator><![CDATA[HenryStivens]]></dc:creator>
		<pubDate>Sun, 28 Apr 2019 23:29:56 +0000</pubDate>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Tutoriales y screencast]]></category>
		<category><![CDATA[ejemplos]]></category>
		<category><![CDATA[mpdf]]></category>
		<category><![CDATA[pdf]]></category>
		<category><![CDATA[template]]></category>
		<guid isPermaLink="false">https://www.kumbiaphp.com/blog/?p=2078</guid>

					<description><![CDATA[<p>En esta segunda parte veremos como exportar una tabla HTML a PDF usando la librería mPDF. Si no has&#8230;</p>
<p>La entrada <a href="https://kumbiaphp.com/blog/2019/04/29/exportar-tabla-html-a-pdf/">Exportar tabla HTML a PDF</a> se publicó primero en <a href="https://kumbiaphp.com/blog">KumbiaPHP Framework PHP en español</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">En esta segunda parte veremos como exportar una tabla HTML a PDF usando la librería mPDF. Si no has visto la primera parte este es el primer artículo: <a href="https://www.kumbiaphp.com/blog/2018/08/06/crear-pdf-usando-html/">Crear PDF usando HTML</a> donde aprendimos a crear un PDF usando partials y funciones en un modelo.</p>



<p class="wp-block-paragraph">[Actualización: Abril 2020] Hemos creado un nuevo repositorio llamado <a rel="noreferrer noopener" href="https://github.com/KumbiaPHP/Sandbox/" target="_blank">Sandbox en Github</a>  donde van a estar todos los ejemplos y que podrán visualizar en vivo en la página <a rel="noreferrer noopener" href="https://sandbox.kumbiaphp.com/" target="_blank">KumbiaPHP Framework Examples</a> por lo tanto el código se ha mejorado y los links han cambiado.</p>



<h2 class="wp-block-heading">Template PDF</h2>



<p class="wp-block-paragraph">Un template permite ahorrar código que se repite en la vistas, permitiendo así un fácil mantenimiento y separación del contenido. Realizará la carga de librería, la cabecera y el pié de página y por supuesto el contenido que queremos mostrar.</p>



<p class="wp-block-paragraph">Para los que aun no han visto el tema de templates en KumbiaPHP o tienen dudas de su funcionamiento los invito a leer la sección sobre el <a href="https://github.com/KumbiaPHP/Documentation/blob/master/es/view.md">manejo de vistas en KumbiapHP.</a> A continuación el código completo del template y más abajo con capturas se explica cada parte importante.</p>



<span id="more-2078"></span>



<p class="wp-block-paragraph">Archivo: <em>app/views/_shared/templates/pdf/mpdf.phtml</em></p>



<pre class="wp-block-code language-php"><code class="" data-line="">&lt;?php

use Mpdf\Mpdf;

/* Defaults */

// fileName
$fileName = $filename ?? &quot;Reporte-de-$controller_name&quot;;

// Title
$title = $title ?? &quot;Reporte de $controller_name&quot;;

// CSS
$css = $css ?? &#039;css/pdf.css&#039;;

// Destination I show in browser  D download
$destination = isset($download) &amp;&amp; $download ? &#039;D&#039; : &#039;I&#039;;

//Activa el almacenamiento en búfer de la salida
ob_start();

?&gt;
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;

&lt;head&gt;
    &lt;title&gt;&lt;?= $title ?&gt;&lt;/title&gt;
    &lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;&lt;?= $css ?&gt;&quot;&gt;
    &lt;meta name=&quot;author&quot; content=&quot;KumbiaPHP framework&quot;&gt;
    &lt;meta name=&quot;description&quot; content=&quot;PDF output example with KumbiaPHP framework&quot;&gt;
    &lt;meta name=&quot;keywords&quot; content=&quot;kumbiaphp, php, pdf, mpdf, examples&quot;&gt;

&lt;body&gt;
    &lt;htmlpageheader name=&quot;myHeader1&quot;&gt;
        &lt;section id=&quot;page-header&quot;&gt;
            &lt;a href=&quot;https://www.kumbiaphp.com&quot;&gt;&lt;img src=&quot;img/kumbiaphp.svg&quot; alt=&quot;Logo KumbiaPHP&quot;&gt;&lt;/a&gt;
            &lt;p&gt;Powered by&lt;/p&gt;
        &lt;/section&gt;
    &lt;/htmlpageheader&gt;

    &lt;?php View::content() ?&gt;

    &lt;htmlpagefooter name=&quot;myFooter1&quot;&gt;
        &lt;section id=&quot;page-footer&quot;&gt;
            &lt;div id=&quot;printed-date&quot;&gt;{DATE d/m/Y}&lt;/div&gt;
            &lt;div id=&quot;page-number&quot;&gt;{PAGENO}/{nbpg}&lt;/div&gt;
        &lt;/section&gt;
    &lt;/htmlpagefooter&gt;
&lt;/body&gt;

&lt;/html&gt;
&lt;?php
$html = ob_get_clean();
ob_clean();

// Crea una instancia de la clase y le pasa el directorio temporal
$mpdf = new Mpdf(&#091;
    &#039;tempDir&#039; =&gt; APP_PATH . &#039;temp/mpdf&#039;,
    &#039;format&#039; =&gt; &#039;A4&#039;,
    &#039;title2annots&#039; =&gt; true,  // convert headers &lt;hx&gt; in annotations
    &#039;mirrorMargins&#039; =&gt; 0,    // mirror the left and right margin values on odd and even pages 
    &#039;exposeVersion&#039; =&gt; false // security 
    // more variables in https://mpdf.github.io/reference/mpdf-variables/overview.html
]);

// Escribe el contenido HTML (Template + View):
$mpdf-&gt;WriteHTML($html);

// Genera el PDF, ya sea para su descarga o visualización en el navegador
$mpdf-&gt;Output(&quot;$fileName.pdf&quot;, $destination);
</code></pre>



<p class="wp-block-paragraph">El proyecto ya usa el autoload de composer para tener disponible mPDF y simplemente importa <em>Mpdf\Mpdf</em>. Luego se definen algunas variables para personalizar el PDF y se ejecuta la función <a href="https://www.php.net/manual/es/function.ob-start.php">ob_start()</a>. «Esta función activará el almacenamiento en búfer de la salida. Mientras dicho almacenamiento esté activo, no se enviará ninguna salida desde el script (aparte de cabeceras); en su lugar la salida se almacenará en un búfer interno.»</p>



<p class="wp-block-paragraph">Si desean conocer como agregar encabezados y pies de páginas con mPDF un compañero realizó un manual en la Wiki de KumbiaPHP que muestra como agregarlos usando las funciones explicadas en el artículo anterior: <a href="http://wiki.kumbiaphp.com/Exportar_a_PDF_con_cabecera_y_pie_de_pagina">Exportar a PDF con cabecera y pie de pagina</a></p>



<p class="wp-block-paragraph">Ahora en el <em>&lt;body&gt;</em> definimos el contenido de la cabecera y el pie de página, y entre ellos la función <em><a href="https://github.com/KumbiaPHP/Documentation/blob/master/es/view.md#buffer-de-salida">View::content()</a></em> que nos permite mostrar el contenido de la vista.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="442" src="https://www.kumbiaphp.com/blog/wp-content/uploads/2020/04/template-pdf-body-html-1024x442.png" alt="" class="wp-image-2401" srcset="https://kumbiaphp.com/blog/wp-content/uploads/2020/04/template-pdf-body-html-1024x442.png 1024w, https://kumbiaphp.com/blog/wp-content/uploads/2020/04/template-pdf-body-html-300x130.png 300w, https://kumbiaphp.com/blog/wp-content/uploads/2020/04/template-pdf-body-html-768x332.png 768w, https://kumbiaphp.com/blog/wp-content/uploads/2020/04/template-pdf-body-html-940x406.png 940w, https://kumbiaphp.com/blog/wp-content/uploads/2020/04/template-pdf-body-html.png 1111w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption>Contenido del Body</figcaption></figure>



<p class="wp-block-paragraph">mPDF maneja sus propias etiquetas, van entre llaves {} y usamos algunas de ellas:</p>



<ul class="wp-block-list"><li>DATE: Para mostrar la fecha actual</li><li>PAGENO: Número de la página</li><li>nbpg: Número total de páginas del documento</li></ul>



<p class="wp-block-paragraph">Y la parte final del template es la que se encarga de unir el template con la vista, generar el PDF con ese contenido y hacer que el documento se visualice o descargue.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1021" height="541" src="https://www.kumbiaphp.com/blog/wp-content/uploads/2020/04/template-pdf-generate.png" alt="" class="wp-image-2402" srcset="https://kumbiaphp.com/blog/wp-content/uploads/2020/04/template-pdf-generate.png 1021w, https://kumbiaphp.com/blog/wp-content/uploads/2020/04/template-pdf-generate-300x159.png 300w, https://kumbiaphp.com/blog/wp-content/uploads/2020/04/template-pdf-generate-768x407.png 768w, https://kumbiaphp.com/blog/wp-content/uploads/2020/04/template-pdf-generate-940x498.png 940w" sizes="auto, (max-width: 1021px) 100vw, 1021px" /><figcaption>General el PDF con el contenido HTML</figcaption></figure>



<h2 class="wp-block-heading">Controlador PHP</h2>



<p class="wp-block-paragraph">Vamos a crear una nueva vista y para ello empezamos con el método que llamaremos <em>pdf()</em> en el controlador <em><em>templates_examples_controller</em>.php</em> El código se encuentra explicado entre líneas.</p>



<p class="wp-block-paragraph">Archivo: <em>app/controllers/templates_examples_controller.php</em></p>



<pre class="wp-block-code language-php"><code class="" data-line="">public function pdf()
{
    //Usa el tempalte &#039;pdf&#039;
    View::template(&#039;pdf/mpdf&#039;);
    //Modifica el nombre del archivo a descargar
    $this-&gt;fileName = &#039;user-list&#039;;
    //Modifica el título del documento PDF en la cabecera
    $this-&gt;title = &#039;User List&#039;;
    $this-&gt;download = false;

    $this-&gt;data = User::all(); // data to show (model User from db)
}</code></pre>



<h2 class="wp-block-heading">Vista HTML</h2>



<p class="wp-block-paragraph">Ahora crearemos la vista la cual tendrá la tabla, recorriendo uno a uno los registro de la consulta realizada por el modelo en el controlador.</p>



<p class="wp-block-paragraph">Archivo: <em>app/views/templates_examples/pdf.phtml&nbsp;</em></p>



<pre class="wp-block-code language-php"><code class="" data-line="">&lt;?php if (!count($data)) : ?&gt;
    &lt;h2&gt;No hay ningún registro&lt;/h2&gt; 
&lt;?php else : ?&gt;
    &lt;table class=&quot;report&quot;&gt;
    &lt;caption class=&quot;caption&quot;&gt;&lt;?= $title ?&gt;&lt;/caption&gt;
        &lt;thead&gt;
            &lt;tr&gt;
                &lt;th scope=&quot;col&quot;&gt;First Name&lt;/th&gt;
                &lt;th scope=&quot;col&quot;&gt;Last Name&lt;/th&gt;
                &lt;th scope=&quot;col&quot;&gt;Email&lt;/th&gt;
                &lt;th scope=&quot;col&quot;&gt;Birthdate&lt;/th&gt;
            &lt;/tr&gt;
        &lt;/thead&gt;
        &lt;tbody&gt; 
            &lt;?php foreach ($data as $item) : ?&gt;
                &lt;tr&gt;
                    &lt;td&gt;&lt;?= $item-&gt;first_name ?&gt;&lt;/td&gt;
                    &lt;td&gt;&lt;?= $item-&gt;last_name ?&gt;&lt;/td&gt;
                    &lt;td&gt;&lt;?= $item-&gt;email ?&gt;&lt;/td&gt;
                    &lt;td&gt;&lt;?= $item-&gt;birthdate ?&gt;&lt;/td&gt;
                &lt;/tr&gt;
            &lt;?php endforeach ?&gt;
        &lt;/tbody&gt;
    &lt;/table&gt;
&lt;?php endif ?&gt;</code></pre>



<p class="wp-block-paragraph">No hace falta explicar mucho más de la vista anterior ya que es una vista normal en KumbiaPHP, esta vista es reutilizable por ejemplo si se quiere pasar a un documento Excel o devolver la vista mediante AJAX.</p>



<h2 class="wp-block-heading">Enlazar al reporte PDF</h2>



<p class="wp-block-paragraph">Y en donde queramos que esté el enlace al reporte PDF simplemente lo añadimos a la vista deseada, nosotros lo hemos añadio a la página de información de los ejemplos de template.</p>



<p class="wp-block-paragraph">Archivo: <em>app/views/templates_examples/info.pdf.phtml</em></p>



<pre class="wp-block-code language-php"><code class="" data-line="">&lt;a href=&quot;/templates-examples/pdf&quot; target=&quot;_blank&quot;&gt;Export users list&lt;/a&gt;</code></pre>



<p class="wp-block-paragraph">Y al pulsar el botón visualizaremos el documento PDF como el siguiente:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="855" src="https://www.kumbiaphp.com/blog/wp-content/uploads/2020/04/example-pdf-kumbiaphp-1024x855.png" alt="" class="wp-image-2403" srcset="https://kumbiaphp.com/blog/wp-content/uploads/2020/04/example-pdf-kumbiaphp-1024x855.png 1024w, https://kumbiaphp.com/blog/wp-content/uploads/2020/04/example-pdf-kumbiaphp-300x250.png 300w, https://kumbiaphp.com/blog/wp-content/uploads/2020/04/example-pdf-kumbiaphp-768x641.png 768w, https://kumbiaphp.com/blog/wp-content/uploads/2020/04/example-pdf-kumbiaphp-940x785.png 940w, https://kumbiaphp.com/blog/wp-content/uploads/2020/04/example-pdf-kumbiaphp.png 1259w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /><figcaption>Visualización del PDF generado con HTML</figcaption></figure>



<h2 class="wp-block-heading">Descargar código completo</h2>



<p class="wp-block-paragraph">Como siempre, el código completo está disponible para todos en el siguiente repositorio en Github listo para usar: <a href="https://github.com/KumbiaPHP/Sandbox/" target="_blank" rel="noreferrer noopener">https://github.com/KumbiaPHP/Sandbox/</a></p>


<p>La entrada <a href="https://kumbiaphp.com/blog/2019/04/29/exportar-tabla-html-a-pdf/">Exportar tabla HTML a PDF</a> se publicó primero en <a href="https://kumbiaphp.com/blog">KumbiaPHP Framework PHP en español</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://kumbiaphp.com/blog/2019/04/29/exportar-tabla-html-a-pdf/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2078</post-id>	</item>
		<item>
		<title>Errores comunes al subir web o aplicación php a producción</title>
		<link>https://kumbiaphp.com/blog/2018/11/05/errores-comunes-al-subir-web-o-aplicacion-php-a-produccion/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=errores-comunes-al-subir-web-o-aplicacion-php-a-produccion</link>
					<comments>https://kumbiaphp.com/blog/2018/11/05/errores-comunes-al-subir-web-o-aplicacion-php-a-produccion/#comments</comments>
		
		<dc:creator><![CDATA[Nelson Rojas]]></dc:creator>
		<pubDate>Mon, 05 Nov 2018 02:48:01 +0000</pubDate>
				<category><![CDATA[Documentación]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Tutoriales y screencast]]></category>
		<category><![CDATA[deployment]]></category>
		<category><![CDATA[producción]]></category>
		<category><![CDATA[servidor php]]></category>
		<guid isPermaLink="false">https://www.kumbiaphp.com/blog/?p=1972</guid>

					<description><![CDATA[<p>La labor de desarrollo de aplicaciones conlleva problemas que no logramos reconocer a primera vista. Este post tiene por&#8230;</p>
<p>La entrada <a href="https://kumbiaphp.com/blog/2018/11/05/errores-comunes-al-subir-web-o-aplicacion-php-a-produccion/">Errores comunes al subir web o aplicación php a producción</a> se publicó primero en <a href="https://kumbiaphp.com/blog">KumbiaPHP Framework PHP en español</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>La labor de desarrollo de aplicaciones conlleva problemas que no logramos reconocer a primera vista. Este post tiene por finalidad, ayudarnos a detectar los errores más comunes cuando hacemos el paso a producción (deployment) de nuestra aplicación hecha con KumbiaPHP.</p>
<p>Va especialmente dedicado a nuestros colegas que alguna vez han llegado al chat grupal con la frase:</p>
<blockquote><p>Es que no funciona en producción</p></blockquote>
<p>La primera pregunta que debemos resolver es:</p>
<h2>¿Por qué no funciona?</h2>
<p>A continuación presentamos una lista de los temas más comunes que deberíamos tener en cuenta para resolver la pregunta que impulsa este artículo.</p>
<p><span id="more-1972"></span></p>
<ol>
<li><a href="#apache-server">¿El servidor apache está ejecutándose?</a></li>
<li><a href="#mod-rewrite-activo">¿El mod rewrite está activo?</a></li>
<li><a href="#mod-rewrite-activo">¿El mod rewrite está configurado para nuestra ruta en el servidor?</a></li>
<li><a href="#php-instalado">¿PHP está instalado y configurado?</a></li>
<li><a href="#base-datos-activo">¿El servidor de bases de datos está activo?</a></li>
<li><a href="#base-datos-configuracion">¿La cuenta en el servidor de bases de datos es la que corresponde en la configuración de nuestra aplicación?</a></li>
<li><a href="#base-datos-produccion">¿Hemos trasladado todos los cambios desde el servidor de bases de datos de desarrollo hacia el servidor de producción?</a></li>
<li><a href="#permisos-app">¿Nuestra aplicación tiene los permisos bien configurados?</a></li>
<li><a href="#ficheros-ocultos">¿Hemos copiado completamente la aplicación desde el servidor de desarrollo (incluidos todos los archivos .htaccess)?</a></li>
<li><a href="#configurar-path">¿Hemos configurado correctamente la constante PUBLIC_PATH?</a></li>
<li><a href="#estrategia-url">¿Podemos usar PATH_INFO o necesitamos cambiar la estrategia de generación de URL?</a></li>
<li><a href="#activar-errores">Si estamos completamente a ciegas, ¿hemos activado la visualización de errores?</a></li>
<li><a href="#app-too-many-redirects">El sitio presenta un error ERR_TOO_MANY_REDIRECTS al cargarlo</a>.</li>
</ol>
<p><strong>NOTA: </strong> Si es <strong>la primera vez</strong> que haces un paso a producción (deployment) a un servidor dedicado o en un hosting compartido, te recomendamos leer los siguientes artículos que hemos alojado en nuestra wiki.</p>
<ul>
<li style="font-weight: 400;">Pasar a producción: <a href="http://wiki.kumbiaphp.com/Pasar_a_produccion">http://wiki.kumbiaphp.com/Pasar_a_produccion</a></li>
<li>Kumbia en servidor con CPanel: <a href="http://wiki.kumbiaphp.com/KumbiaPHP_en_servidor_con_CPanel">http://wiki.kumbiaphp.com/KumbiaPHP_en_servidor_con_CPanel</a></li>
</ul>
<p>Continuemos entonces con el checklist:</p>
<h2><a id="apache-server"></a>¿El servidor Apache está ejecutándose?</h2>
<p>Nuestra primera tarea será revisar que el servicio de Apache se encuentre activo y en el puerto necesario. Asumiendo que la tarea de despliegue (deployment) se realiza en un servidor linux, podemos revisar si el servicio está activo y si acaso el puerto está escuchando.</p>
<p>Revisemos el servicio web con los siguientes comandos:</p>
<pre>ps -fea | grep -i http
ps -fea | grep -i apache</pre>
<p>Si encontramos resultados, es decir, al menos 2 líneas se visualizan como salida a nuestro comando*, es que el servicio está activo.</p>
<p><a href="https://www.kumbiaphp.com/blog/wp-content/uploads/2018/11/Captura-de-pantalla-2018-11-01-a-las-07.44.28.png"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-1979" src="https://www.kumbiaphp.com/blog/wp-content/uploads/2018/11/Captura-de-pantalla-2018-11-01-a-las-07.44.28.png" alt="" width="848" height="252" srcset="https://kumbiaphp.com/blog/wp-content/uploads/2018/11/Captura-de-pantalla-2018-11-01-a-las-07.44.28.png 848w, https://kumbiaphp.com/blog/wp-content/uploads/2018/11/Captura-de-pantalla-2018-11-01-a-las-07.44.28-300x89.png 300w, https://kumbiaphp.com/blog/wp-content/uploads/2018/11/Captura-de-pantalla-2018-11-01-a-las-07.44.28-768x228.png 768w" sizes="auto, (max-width: 848px) 100vw, 848px" /></a></p>
<p>*el comando <strong>ps</strong> es “<strong>p</strong>rocess <strong>s</strong>tatus” o estado del proceso. Las opciones -fea son para indicar que nos liste los procesos de nuestro usuario como del resto, así como algo de información relacionada con el proceso. Para realizar el filtro entre todos los procesos hemos usado un pipe | o tubería para enviar el resultado del comando ps al comando grep que buscará en la lista si acaso existe algo que contenga el texto “http”, o algo que contenga “apache”. Se usa con -i para que no discrimine entre mayúsculas y minúsculas o alguna combinación de ellas. Para más ayuda sobre estos comando les recomendamos usar el comando man ps o también pueden usar man grep.</p>
<p>NOTA: si usan el comando man (manual) para ps o para grep lo más seguro es que se encuentren con el editor vi. Para salir de él bastará con presionar Esc (escape), luego : (dos puntos) y luego q (la letra q para quit).</p>
<p>Revisemos ahora que el servicio está activo y escuchando peticiones.</p>
<p>Para eso nos bastará en primera instancia abrir un navegador y apuntarlo a la dirección de nuestro servidor. Si tenemos respuesta de la página de bienvenida del servicio (apache) ya tendremos este tema resuelto.</p>
<p>Ahora, si tenemos acceso por consola, podemos probar usando el comando</p>
<pre>netstat -av | grep http</pre>
<p>En mi caso, uso apache y su nombre de servicio es http. En otros Sistemas Operativos o paquetes de software que incluyen Apache, el servicio web puede encontrarse como apache o apache2.</p>
<p><a id="mod-rewrite-activo"></a><a href="https://www.kumbiaphp.com/blog/wp-content/uploads/2018/11/Captura-de-pantalla-2018-11-01-a-las-07.40.01-1.png"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-1978" src="https://www.kumbiaphp.com/blog/wp-content/uploads/2018/11/Captura-de-pantalla-2018-11-01-a-las-07.40.01-1.png" alt="" width="848" height="252" srcset="https://kumbiaphp.com/blog/wp-content/uploads/2018/11/Captura-de-pantalla-2018-11-01-a-las-07.40.01-1.png 848w, https://kumbiaphp.com/blog/wp-content/uploads/2018/11/Captura-de-pantalla-2018-11-01-a-las-07.40.01-1-300x89.png 300w, https://kumbiaphp.com/blog/wp-content/uploads/2018/11/Captura-de-pantalla-2018-11-01-a-las-07.40.01-1-768x228.png 768w" sizes="auto, (max-width: 848px) 100vw, 848px" /></a></p>
<h2><a id="mod-rewrite-activo"></a>¿El mod rewrite está activado?</h2>
<p>Esta pregunta no es difícil de responder si usamos un pequeño archivo PHP al que llamaremos info.php. En él escribiremos &lt;?php phpinfo(); ?&gt; y luego lo abriremos desde el navegador (normalmente http://localhost/info.php)</p>
<p>Así aprovecharemos para revisar que PHP está activo y en la versión del mismo.</p>
<p>Una vez cargue la página de información de php buscaremos (en general con Ctrl + F o Cmd + F) la palabra rewrite. Deberíamos encontrarla en la sección apache2handlers, en la fila Loaded Modules.</p>
<p><a href="https://www.kumbiaphp.com/blog/wp-content/uploads/2018/11/Captura-de-pantalla-2018-11-01-a-las-07.51.29.png"><img loading="lazy" decoding="async" class="alignnone wp-image-1982 size-full" src="https://www.kumbiaphp.com/blog/wp-content/uploads/2018/11/Captura-de-pantalla-2018-11-01-a-las-07.51.29.png" alt="Información del php info" width="953" height="370" srcset="https://kumbiaphp.com/blog/wp-content/uploads/2018/11/Captura-de-pantalla-2018-11-01-a-las-07.51.29.png 953w, https://kumbiaphp.com/blog/wp-content/uploads/2018/11/Captura-de-pantalla-2018-11-01-a-las-07.51.29-300x116.png 300w, https://kumbiaphp.com/blog/wp-content/uploads/2018/11/Captura-de-pantalla-2018-11-01-a-las-07.51.29-768x298.png 768w, https://kumbiaphp.com/blog/wp-content/uploads/2018/11/Captura-de-pantalla-2018-11-01-a-las-07.51.29-940x365.png 940w" sizes="auto, (max-width: 953px) 100vw, 953px" /></a></p>
<p>Como se aprecia en la imagen anterior también está activo mod_php7 :-)</p>
<p>En caso que no lo encontremos, o que el archivo info.php no nos dé información, bastará con hacer la activación desde la consola (en el caso de tener servidor con shell activa). Vamos a asumir que usamos un servidor con un sistema operativo derivado de debian (ubuntu o similar). Entonces escribiremos en la consola como root</p>
<pre>a2enmod rewrite</pre>
<p>Y luego reiniciamos el servicio de apache (también como root)</p>
<pre>service apache2 restart</pre>
<p>Con esto ya deberíamos tener activado el módulo de sobrescritura de url.</p>
<h2><a id="mod-rewrite-activo"></a>¿El mod rewrite está configurado para nuestra ruta en el servidor?</h2>
<p>Bueno, no basta con activar el mod rewrite, hay que configurarlo también.</p>
<pre><strong>Nota del autor:</strong> esto es lo que normalmente hago en mi configuración de apache. 
No sé si es lo más recomendado. Los comentarios son bienvenidos :)</pre>
<p>Para realizar este cambio iremos al archivo de configuración de apache (generalmente alojado en /etc/apache2/apache2.conf)</p>
<p>Lo editaremos y buscaremos una sección llamada Directory.</p>
<p>Buscaremos aquella cuya línea sea Directory /var/www y cambiaremos la opción AllowOverride None por AllowOverride All. Guardaremos la configuración y procederemos a reiniciar el servicio apache.</p>
<p>En las imágenes siguientes se ve el antes y el después de la configuración.</p>
<figure><a href="https://www.kumbiaphp.com/blog/wp-content/uploads/2018/11/Captura-de-pantalla-2018-11-01-a-las-08.04.50.png"><img loading="lazy" decoding="async" class="wp-image-1984 size-full" src="https://www.kumbiaphp.com/blog/wp-content/uploads/2018/11/Captura-de-pantalla-2018-11-01-a-las-08.04.50.png" alt="antes de la configuración" width="593" height="190" srcset="https://kumbiaphp.com/blog/wp-content/uploads/2018/11/Captura-de-pantalla-2018-11-01-a-las-08.04.50.png 593w, https://kumbiaphp.com/blog/wp-content/uploads/2018/11/Captura-de-pantalla-2018-11-01-a-las-08.04.50-300x96.png 300w" sizes="auto, (max-width: 593px) 100vw, 593px" /></a><figcaption>Antes de la configuración</figcaption></figure>
<figure><a href="https://www.kumbiaphp.com/blog/wp-content/uploads/2018/11/Captura-de-pantalla-2018-11-01-a-las-08.06.22.png"><img loading="lazy" decoding="async" class="size-full wp-image-1985" src="https://www.kumbiaphp.com/blog/wp-content/uploads/2018/11/Captura-de-pantalla-2018-11-01-a-las-08.06.22.png" alt="luego de cambiar la configuración" width="593" height="140" srcset="https://kumbiaphp.com/blog/wp-content/uploads/2018/11/Captura-de-pantalla-2018-11-01-a-las-08.06.22.png 593w, https://kumbiaphp.com/blog/wp-content/uploads/2018/11/Captura-de-pantalla-2018-11-01-a-las-08.06.22-300x71.png 300w" sizes="auto, (max-width: 593px) 100vw, 593px" /></a><figcaption>luego de cambiar la configuración</figcaption></figure>
<p>Con estos pasos el mod rewrite estará activo y configurado.</p>
<h2><a id="php-instalado"></a>¿PHP está instalado y configurado?</h2>
<p>Si hemos llevado a cabo los pasos anteriores para saber si el mod rewrite estaba activo, y lo hemos encontrado en el archivo info.php, entonces es que tenemos PHP bien instalado.</p>
<p>En caso que no hayamos logrado entonces deberemos instalar el módulo PHP en nuestro servidor.</p>
<p>Para hacer esta tarea usaremos nuevamente la consola (shell) para hacer la instalación.</p>
<p>La instalación varía un poco entre distribuciones de servidor, pero haremos la instalación pensando en algún derivado de debian (como si fuéramos root)</p>
<pre>apt-get install libapache2-mod-php php</pre>
<p>Una vez que la instalación haya finalizado necesitaremos reiniciar el servicio web (como root)</p>
<pre>service apache2 restart</pre>
<p>Si tenemos aún el archivo info.php, pues lo abriremos desde el navegador (normalmente http://localhost/info.php)</p>
<p>Si logramos ver el resultado de nuestro archivo, entonces ya tendremos claro que PHP está activo en nuestro servidor.</p>
<h2><a id="base-datos-activo"></a>¿El servidor de bases de datos está activo?</h2>
<p>Si usamos MySQL o MariaDB bastará con intentar hacer login con la cuenta que tenemos en la configuración de nuestra aplicación desde la consola.</p>
<pre>mysql nombredelabasededatos -u miusuario -p</pre>
<p>Digitamos la contraseña y presionamos enter para lograr acceso.</p>
<p>Si nos da un error como el que se ve en la imagen siguiente es porque el servicio no está activo.</p>
<p><a href="https://www.kumbiaphp.com/blog/wp-content/uploads/2018/11/Captura-de-pantalla-2018-11-01-a-las-08.11.50.png"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-1986" src="https://www.kumbiaphp.com/blog/wp-content/uploads/2018/11/Captura-de-pantalla-2018-11-01-a-las-08.11.50.png" alt="" width="887" height="154" srcset="https://kumbiaphp.com/blog/wp-content/uploads/2018/11/Captura-de-pantalla-2018-11-01-a-las-08.11.50.png 887w, https://kumbiaphp.com/blog/wp-content/uploads/2018/11/Captura-de-pantalla-2018-11-01-a-las-08.11.50-300x52.png 300w, https://kumbiaphp.com/blog/wp-content/uploads/2018/11/Captura-de-pantalla-2018-11-01-a-las-08.11.50-768x133.png 768w" sizes="auto, (max-width: 887px) 100vw, 887px" /></a></p>
<p>Para activarlo deberemos ejecutar un comando como el que sigue desde la consola (como si fuéramos root):</p>
<pre>service mysqld start</pre>
<p><a href="https://www.kumbiaphp.com/blog/wp-content/uploads/2018/11/Captura-de-pantalla-2018-11-01-a-las-08.12.57.png"><img loading="lazy" decoding="async" class="alignnone size-full wp-image-1988" src="https://www.kumbiaphp.com/blog/wp-content/uploads/2018/11/Captura-de-pantalla-2018-11-01-a-las-08.12.57.png" alt="" width="887" height="250" srcset="https://kumbiaphp.com/blog/wp-content/uploads/2018/11/Captura-de-pantalla-2018-11-01-a-las-08.12.57.png 887w, https://kumbiaphp.com/blog/wp-content/uploads/2018/11/Captura-de-pantalla-2018-11-01-a-las-08.12.57-300x85.png 300w, https://kumbiaphp.com/blog/wp-content/uploads/2018/11/Captura-de-pantalla-2018-11-01-a-las-08.12.57-768x216.png 768w" sizes="auto, (max-width: 887px) 100vw, 887px" /></a></p>
<p>Si ahora logramos acceso y todo va bien, es decir, logramos conectarnos al servidor mysql, sería bueno saber si tenemos acceso a la base de datos que usará la aplicación.</p>
<p>Para eso, estando en la consola interactiva de mysql, escribimos el comando <b>use mibasededatos;</b> (donde mibasededatos es el nombre de la base de datos que está configurado en el archivo database.ini) seguido de punto y coma. Y presionamos enter.</p>
<p>Nos debe aparecer un mensaje como “database changed”.</p>
<p>Seleccionamos alguna de las tablas del sistema (podemos listarlas usando el comando <strong>show tables;</strong>), y escribimos alguna instrucción y le ejecutamos, por ejemplo;</p>
<pre class="  language-sql"><code class="" data-line="">&lt;span class=&quot;token keyword&quot;&gt;SELECT&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;*&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;FROM&lt;/span&gt; tablaseleccionada&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;</code></pre>
<p>Si todo ha ido bien, ya podemos pasar al siguiente punto.</p>
<h2><a id="base-datos-configuracion"></a>¿La cuenta en el servidor de bases de datos es la que corresponde en la configuración de nuestra aplicación?</h2>
<p>Bueno, en el punto anterior ya hemos realizado esta prueba usando el comando:</p>
<pre>mysql nombrebasedatos -u usuario -p</pre>
<p>Si esto no resulta, será necesario crear un usuario de mysql con los permisos necesarios sobre la base de datos correcta. Para eso te recomendamos leer el siguiente artículo que ya explica muy bien cómo lograr esta labor.</p>
<p><a href="https://www.digitalocean.com/community/tutorials/crear-un-nuevo-usuario-y-otorgarle-permisos-en-mysql-es">https://www.digitalocean.com/community/tutorials/crear-un-nuevo-usuario-y-otorgarle-permisos-en-mysql-es</a></p>
<h2><a id="base-datos-produccion"></a>¿Hemos trasladado todos los cambios desde el servidor de bases de datos de desarrollo hacia el servidor de producción?</h2>
<p>A veces el error se produce porque tenemos tablas en el servidor de desarrollo que no hemos pasado al servidor de producción o porque alguna de las tablas de producción no tiene atributos (campos) nuevos que sí hemos estado usando en desarrollo. Hacer una revisión de las estructuras de las tablas será de gran ayuda si comparas cómo es el estado en ambos servidores.</p>
<h2><a id="permisos-app"></a>¿Nuestra aplicación tiene los permisos bien configurados?</h2>
<p>Si hemos leído los artículos de la wiki, y hemos comprobado que los permisos son los correctos, sólo nos quedará pasar al siguiente punto.</p>
<h2><a id="ficheros-ocultos"></a>¿Hemos copiado completamente la aplicación desde el servidor de desarrollo (incluidos todos los archivos ocultos)?</h2>
<p>Por obvia que parezca la pregunta, resulta que en ocasiones el cliente que usamos para copiar los archivos, omite los archivos ocultos que comienzan en punto (los dot files). En KumbiaPHP se usan varios archivos que comienzan en punto, y aunque todos se llaman igual, cada uno cumple una misión diferente dependiendo del lugar en el que esté alojado. Este archivo es el .htaccess.</p>
<p>Personalmente la forma que más me resulta para lidiar con este problema es comprimir el sitio, copiarlo comprimido al servidor de producción y luego descomprimirlo en él. Si esto no fuera posible (porque por ejemplo no tienes acceso a la shell o si el panel web de administración no provee de gestión de archivos), toma en cuenta que el cliente de ftp que uses lleve todo lo que necesitas al servidor de producción.</p>
<h2><a id="configurar-path"></a>¿Hemos configurado correctamente la constante PUBLIC_PATH?</h2>
<p>Aunque también es parte de lo que se habla en los artículos escritos y mencionados de la wiki, uno de nuestros colegas ha escrito un artículo interesante sobre este tema y el siguiente en el blog de KumbiaPHP <a href="https://www.kumbiaphp.com/blog/2018/07/31/no-input-file-specified-arreglar-el-error/">https://www.kumbiaphp.com/blog/2018/07/31/no-input-file-specified-arreglar-el-error/</a></p>
<h2><a id="estrategia-url"></a>¿Podemos usar PATH_INFO o necesitamos cambiar la estrategia de generación de URL?</h2>
<p>Al igual que el punto anterior, nuestra recomendación es leer el artículo que ya se mencionó en él.</p>
<h2><a id="activar-errores"></a>Si estamos completamente a ciegas, ¿hemos activado la visualización de errores?</h2>
<p>Si el servidor no nos da información alguna sobre el error, podemos aprovechar una configuración especial que está alojada dentro del archivo <strong><i>default/public/index.php</i></strong> para activar el registro de los errores y permitir visualizarlos directamente en el navegador web.</p>
<p>Para eso iremos archivo mencionado (<strong>default/public/index.php</strong>) y buscaremos la línea:</p>
<pre><code class="language-php" data-line="">//error_reporting(E_ALL ^ E_STRICT);ini_set(&#039;display_errors&#039;, &#039;On&#039;);</code></pre>
<p>Y le quitaremos los comentarios iniciales, es decir, los dos primeros caracteres iniciales <strong>//</strong></p>
<p>Adicionalmente debemos asegurarnos que KumbiaPHP no esté en modo producción, así que en el mismo archivo <strong><i>default/public/index.php </i></strong>verificamos que la constante PRODUCTION sea igual a false:</p>
<pre><code class="language-php" data-line="">const PRODUCTION = false;</code></pre>
<p>Esto hará que las excepciones que ocurran sean mostradas en pantalla evitando la redirección a la página de error 404, que es comportamiento por defecto de KumbiaPHP cuando está en producción.</p>
<p>Con eso ya tendremos alguna idea a partir de la presentación de los errores en pantalla.</p>
<p>Existe una forma extra de visualizar errores, pero para ello hay que tener acceso al servidor en modo consola (shell) y tener acceso al log de errores del servidor web (apache generalmente). Normalmente este archivo se aloja en <strong><i>/var/log/apache2/error.log</i></strong></p>
<p>Si se tiene acceso a él, usar el comando <strong><i>tail -f error.log</i></strong> será de gran utilidad pues cada vez que recargues tu navegador, los errores se verán reflejados en tu terminal. Los mensajes que recibas serán de gran utilidad al momento de buscar posibles soluciones, o para pedir apoyo a algún colega.</p>
<h2><a id="app-too-many-redirects"></a>El sitio presenta un error ERR_TOO_MANY_REDIRECTS al cargarlo</h2>
<p>Si a pesar de haber eliminado los archivos de la caché este error persiste es momento de revisar nuestra rutina de autenticación. En ocasiones la implementación de la gestión de la sesión del usuario nos puede causar algunos dolores de cabeza, y el consejo aquí es verificar la forma en la cual se lleva a cabo las redirecciones cuando un usuario no tiene los privilegios necesarios y requiere de autenticación. Hay diferentes formas de llevar a cabo la autenticación, pero siempre vale la pena consultar alguna forma que ya haya sido probada. Para tales efectos les recomendamos leer <a href="http://wiki.kumbiaphp.com/Beta2_Sistema_de_Login" target="_blank" rel="noopener noreferrer">http://wiki.kumbiaphp.com/Beta2_Sistema_de_Login</a> o también <a href="https://soyprogramador.liz.mx/implementando-logueo-en-kumbiaphp/" target="_blank" rel="noopener noreferrer">https://soyprogramador.liz.mx/implementando-logueo-en-kumbiaphp/</a> como elementos formativos. Te dejamos como tarea extra mirar código de otras personas. Puedes hacer una búsqueda en <a href="https://github.com/search?q=kumbiaphp" target="_blank" rel="noopener noreferrer">github</a> con la palabra clave kumbiaphp.</p>
<h2>Una recomendación final</h2>
<p><em>Si hemos pasado de PRODUCCION = true a false y viceversa, es necesario recordar eliminar el contenido de la carpeta de cache que genera KumbiaPHP cuando estamos en modo producción. Para ello iremos a la carpeta default/app/temp/cache y borraremos su contenido para evitar que no logremos visualizar los errores porque el framework está presentando los contenidos “cacheados” en vez de las vistas reales.</em></p>
<p>Con todo esto, te deseamos lo mejor y mucho ánimo cuando te encuentres con un problema, pues recuerda que resolverlos es parte de nuestro aprendizaje y nuestra labor como desarrolladores.</p>
<p>Un abrazo cordial,</p>
<p>El equipo de KumbiaPHP</p>
<p>La entrada <a href="https://kumbiaphp.com/blog/2018/11/05/errores-comunes-al-subir-web-o-aplicacion-php-a-produccion/">Errores comunes al subir web o aplicación php a producción</a> se publicó primero en <a href="https://kumbiaphp.com/blog">KumbiaPHP Framework PHP en español</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://kumbiaphp.com/blog/2018/11/05/errores-comunes-al-subir-web-o-aplicacion-php-a-produccion/feed/</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1972</post-id>	</item>
		<item>
		<title>Crear PDF usando HTML</title>
		<link>https://kumbiaphp.com/blog/2018/08/06/crear-pdf-usando-html/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=crear-pdf-usando-html</link>
					<comments>https://kumbiaphp.com/blog/2018/08/06/crear-pdf-usando-html/#comments</comments>
		
		<dc:creator><![CDATA[HenryStivens]]></dc:creator>
		<pubDate>Mon, 06 Aug 2018 10:00:37 +0000</pubDate>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Tutoriales y screencast]]></category>
		<category><![CDATA[ejemplos]]></category>
		<category><![CDATA[mpdf]]></category>
		<category><![CDATA[pdf]]></category>
		<guid isPermaLink="false">https://www.kumbiaphp.com/blog/?p=1915</guid>

					<description><![CDATA[<p>Para crear PDF usando HTML con PHP existen diferentes librerías que nos pueden ayudar a cumplir el objetivo de&#8230;</p>
<p>La entrada <a href="https://kumbiaphp.com/blog/2018/08/06/crear-pdf-usando-html/">Crear PDF usando HTML</a> se publicó primero en <a href="https://kumbiaphp.com/blog">KumbiaPHP Framework PHP en español</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Para crear PDF usando HTML con PHP existen diferentes librerías que nos pueden ayudar a cumplir el objetivo de manera sencilla, esta vez vamos a probar <a href="https://github.com/mpdf/mpdf">mPDF</a>. mPDF es una librería en PHP la cual permite generar archivos <a href="https://es.wikipedia.org/wiki/PDF">PDF</a> usando HTML(Codificado con UTF-8). Está basada en <a href="http://www.fpdf.org/" rel="nofollow">FPDF</a> y HTML2FPDF, con varias mejoras, fue escrito por Ian Back y lanzado bajo licencia <a href="https://github.com/mpdf/mpdf/blob/development/LICENSE.txt">GNU GPL v2</a>.</p>
<h2>Instalación de mPDF</h2>
<p>El método de instalación oficial de mPDF en PHP es via composer y este es el paquete packagist: <a href="https://packagist.org/packages/mpdf/mpdf">mpdf/mpdf</a>.</p>
<p><code class="" data-line="">composer require mpdf/mpdf</code></p>
<h2>Cargando la librería</h2>
<p>Como es un ejemplo básico realizaremos la carga de la librería sólo en el controlador que vamos a usar. De la siguiente manera:</p>
<p>Archivo: <em>default/app/controllers/index_controller.php</em></p>
<pre><code class="language-php" data-line="">&lt;?php

// Require composer autoload
require_once APP_PATH . &#039;../../vendor/autoload.php&#039;;

use Mpdf\Mpdf;

/** 
 *
 * Controller por defecto si no se usa el routes 
 *
 */
class IndexController extends AppController
{
    public function index()
    {
    }
}
</code><code class="" data-line="">
</code></pre>
<h2>Primer ejemplo de crear PDF usando HTML</h2>
<p>Creamos el método <em>example1()</em> donde sin usar vista o template creamos el «Hola mundo» del uso de la librería con el siguiente código:</p>
<p><span id="more-1915"></span></p>
<p>Archivo: <em>default/app/controllers/index_controller.php</em></p>
<pre><code class="language-php" data-line="">public function example1()
{
    //Importante: Sin vista y sin tamplate 
    View::select(null, null);
    //Crea una instancia de la clase y le pasa el directorio default/app/temp/ 
    $mpdf = new Mpdf([&#039;tempDir&#039; =&gt; APP_PATH . &#039;/temp&#039;]);
    //Escribe algo de contenido HTML: 
    $mpdf-&gt;WriteHTML(&#039;¡Hola KumbiaPHP!&#039;);
    //Envía un archivo PDF directamente al navegador $mpdf-&gt;Output(); 
}</code><code class="" data-line=""></code></pre>
<p>Dependiendo de la configuración del navegador nos mostrará en su visualizador de PDFs el documento creado. En caso contrario nos mostrará el diálogo para iniciar la descarga.</p>
<figure><a href="https://www.kumbiaphp.com/blog/wp-content/uploads/2018/07/html-to-pdf-example1.png"><img loading="lazy" decoding="async" class="aligncenter wp-image-1923 size-large" title="Documento PDF a partir de HTML" src="https://www.kumbiaphp.com/blog/wp-content/uploads/2018/07/html-to-pdf-example1-1024x640.png" alt="Ejemplo de crear PDF con HTML" width="940" height="588" srcset="https://kumbiaphp.com/blog/wp-content/uploads/2018/07/html-to-pdf-example1-1024x640.png 1024w, https://kumbiaphp.com/blog/wp-content/uploads/2018/07/html-to-pdf-example1-300x188.png 300w, https://kumbiaphp.com/blog/wp-content/uploads/2018/07/html-to-pdf-example1-768x480.png 768w, https://kumbiaphp.com/blog/wp-content/uploads/2018/07/html-to-pdf-example1-940x588.png 940w, https://kumbiaphp.com/blog/wp-content/uploads/2018/07/html-to-pdf-example1.png 1280w" sizes="auto, (max-width: 940px) 100vw, 940px" /></a><figcaption>Ejemplo de crear PDF con HTML</figcaption></figure>
<h2>Segundo ejemplo ¡Usaremos vistas!</h2>
<p>El primer ejemplo está bien, pero a nosotros nos gusta darle más orden y para mantener la lógica en su lugar. Vamos a crear un modelo llamado <strong>HtmlToPdf</strong> (Pueden llamarlo como deseen) y es donde a partir de ahora vamos a crear los archivos PDF, pero esta vez llamaremos el contenido de un partial, el cual nos servirá para mantener separado el <a href="https://es.wikipedia.org/wiki/HTML">HTML</a> del <a href="https://www.php.net/">PHP</a>. Primero observemos el contenido del partial:</p>
<p>Archivo: <em>default/app/views/_shared/partials/pdf/example2.phtml</em></p>
<p><code class="" data-line="">&lt;h1&gt;¡Hola KumbiaPHP!&lt;/h1&gt;</code></p>
<p>Ahora si el método <em>example2()</em> en el modelo:</p>
<p>Archivo: <em>default/app/models/html_to_pdf.php</em></p>
<pre><code class="language-php" data-line="">&lt;?php 
use Mpdf\Mpdf; 

class HtmlToPdf 
{ 
    public static function example2() 
    { 
        // Activa el almacenamiento en búfer de la salida 
        ob_start(); 
        // Carga el contenido del partial 
        View::partial(&#039;pdf/example2&#039;); 
        // Obtiene en $html el contenido del búfer actual y elimina el búfer de salida actual 
        $html = ob_get_clean(); 
        // Crea una instancia de la clase y le pasa el directorio temporal 
        $mpdf = new Mpdf([&#039;tempDir&#039; =&gt; APP_PATH . &#039;/temp&#039;]); 
        // Escribe algo de contenido HTML: 
        $mpdf-&gt;WriteHTML($html); 
        // Envia un archivo PDF directamente al navegador 
        $mpdf-&gt;Output(); 
    } 
}</code><code class="" data-line="">
</code></pre>
<p>Ahora simplemente en el controlador sin usar vista ni template llamaremos el método <strong>example2()</strong> de la clase modelo <strong>HtmlToPdf</strong></p>
<p>Archivo: <em>default/app/controllers/index_controller.php</em></p>
<pre><code class="language-php" data-line="">public function example2() 
{ 
    //Importante: Sin vista y sin tamplate 
    View::select(null, null); 
    //Llama al ejemplo 2 
    HtmlToPdf::example2(); 
}</code><code class="" data-line="">
</code></pre>
<p>El código anterior hace exactamente lo mismo que el primer ejemplo, la diferencia es que esta vez usamos MVC. En el <strong>modelo</strong> añadimos la lógica para crear el documento pdf a partir de una <strong>vista</strong> parcial (partial), usamos el <strong>controlador</strong> para llamar el método implementado en el modelo.</p>
<p>Podemos añadir todo el HTML que deseemos siempre y cuando sea compatible con mPDF, eso nos da juego para añadir tablas, imágenes, enlaces, añadir estilos con css, etc.</p>
<h2>Ejemplo 3</h2>
<p>Vamos a hacer esta vez que el método del modelo reciba un parámetro <strong>$name</strong> y se lo pase a la vista parcial (partial) <em>pdf/example3</em>.</p>
<pre><code class="language-php" data-line="">public static function example3($name) 
{ 
    // Activa el almacenamiento en búfer de la salida 
    ob_start(); 
    // Carga el contenido del partial pasandole datos 
    View::partial(&#039;pdf/example3&#039;, &#039;&#039;, [&#039;name&#039; =&gt; $name, &#039;date&#039; =&gt; date(DATE_ISO8601)]); 
    // Obtiene en $html el contenido del búfer actual y elimina el búfer de salida actual $
    html = ob_get_clean(); 
    // Crea una instancia de la clase y le pasa el directorio temporal 
    $mpdf = new Mpdf([&#039;tempDir&#039; =&gt; APP_PATH . &#039;/temp&#039;]); 
    // Escribe algo de contenido HTML: 
    $mpdf-&gt;WriteHTML($html); 
    // Obliga la descarga del PDF y se personaliza el nombre 
    $mpdf-&gt;Output(&#039;example3.pdf&#039;, \Mpdf\Output\Destination::DOWNLOAD); 
}</code><code class="" data-line=""></code></pre>
<p>Ahora haremos que el partial reciba el valor de las variables y las imprima para que se muestre en el PDF.</p>
<p>Archivo: <em>default/app/views/_shared/partials/pdf/example3.phtml</em></p>
<pre><code class="language-php" data-line="">&lt;h1&gt;¡Hola &lt;?= $name ?&gt;!&lt;/h1&gt;
&lt;p&gt; Este documento fue generado el &lt;?= $date ?&gt; &lt;/p&gt;</code><code class="" data-line="">
</code></pre>
<p>Si entramos a la URL: <em>http://localhost:8184/index/example3/Henry</em> nos descargará el PDF con el nombre <strong>example3.pdf</strong> y veremos algo como la siguiente captura de pantalla:</p>
<figure><img loading="lazy" decoding="async" class="aligncenter wp-image-1932 size-large" title="Ejemplo 3 De HTML a PDF" src="https://www.kumbiaphp.com/blog/wp-content/uploads/2018/07/Captura-de-pantalla-2018-07-30-a-las-10.59.52-1024x803.png" alt="Ejemplo 3 De HTML a PDF" width="940" height="737" srcset="https://kumbiaphp.com/blog/wp-content/uploads/2018/07/Captura-de-pantalla-2018-07-30-a-las-10.59.52-1024x803.png 1024w, https://kumbiaphp.com/blog/wp-content/uploads/2018/07/Captura-de-pantalla-2018-07-30-a-las-10.59.52-300x235.png 300w, https://kumbiaphp.com/blog/wp-content/uploads/2018/07/Captura-de-pantalla-2018-07-30-a-las-10.59.52-768x602.png 768w, https://kumbiaphp.com/blog/wp-content/uploads/2018/07/Captura-de-pantalla-2018-07-30-a-las-10.59.52-940x737.png 940w, https://kumbiaphp.com/blog/wp-content/uploads/2018/07/Captura-de-pantalla-2018-07-30-a-las-10.59.52.png 1084w" sizes="auto, (max-width: 940px) 100vw, 940px" /><figcaption>Ejemplo 3 De HTML a PDF</figcaption></figure>
<p>Estos fueron tres ejemplos básicos para generar PDF usando HTML con PHP.</p>
<h2 data-tadv-p="keep">Segunda Parte de HTML a PDF</h2>
<p><a href="https://www.kumbiaphp.com/blog/2019/04/29/exportar-tabla-html-a-pdf/">Exportar tabla HTML a PDF</a></p>
<p>Si desean que hagamos un nuevo tutorial con ejemplos avanzados y de la vida real dejen su comentario en la caja de abajo.</p>
<h2>Descargar código completo</h2>
<p>Como siempre, el código completo del ejemplo para crea documentos PDF con PHP está disponible para todos en el siguiente repositorio en Github listo para usar con Docker: <a href="https://github.com/henrystivens/kumbiaphp-mpdf">https://github.com/henrystivens/kumbiaphp-mpdf</a></p>
<h2 data-tadv-p="keep">Nuevos ejemplos de mPDF</h2>
<p>Puedes ver un ejemplo del PDF generado más completo funcionando en <a href="https://sandbox.kumbiaphp.com/templates-examples/info/pdf">ejemplo mPDF</a>  y el código PHP de ejemplo <a href="https://github.com/kumbiaphp/sandbox/blob/master/app/controllers/templates_examples_controller.php">controlador</a> y <a href="https://github.com/kumbiaphp/sandbox/blob/master/app/views/_shared/templates/pdf/mpdf.phtml">template</a> para usar con cualquier vista de HTML.</p>
<p>La entrada <a href="https://kumbiaphp.com/blog/2018/08/06/crear-pdf-usando-html/">Crear PDF usando HTML</a> se publicó primero en <a href="https://kumbiaphp.com/blog">KumbiaPHP Framework PHP en español</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://kumbiaphp.com/blog/2018/08/06/crear-pdf-usando-html/feed/</wfw:commentRss>
			<slash:comments>9</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1915</post-id>	</item>
	</channel>
</rss>
