<?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>ejemplos archivos - KumbiaPHP Framework PHP en español</title>
	<atom:link href="https://kumbiaphp.com/blog/tag/ejemplos/feed/" rel="self" type="application/rss+xml" />
	<link>https://kumbiaphp.com/blog/tag/ejemplos/</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.1</generator>

<image>
	<url>https://kumbiaphp.com/blog/wp-content/uploads/2016/01/250-150x150.png</url>
	<title>ejemplos archivos - KumbiaPHP Framework PHP en español</title>
	<link>https://kumbiaphp.com/blog/tag/ejemplos/</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>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>&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>&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>&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>&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">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">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>&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>&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>&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>&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>// 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>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 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>&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>Optimizando la Renderización Condicional en Vistas de KumbiaPHP con return 1;</title>
		<link>https://kumbiaphp.com/blog/2024/10/14/optimizando-la-renderizacion-condicional-en-vistas-de-kumbiaphp-con-return-1/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=optimizando-la-renderizacion-condicional-en-vistas-de-kumbiaphp-con-return-1</link>
					<comments>https://kumbiaphp.com/blog/2024/10/14/optimizando-la-renderizacion-condicional-en-vistas-de-kumbiaphp-con-return-1/#comments</comments>
		
		<dc:creator><![CDATA[HenryStivens]]></dc:creator>
		<pubDate>Mon, 14 Oct 2024 16:52:23 +0000</pubDate>
				<category><![CDATA[Documentación]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[ejemplos]]></category>
		<category><![CDATA[vistas]]></category>
		<guid isPermaLink="false">https://kumbiaphp.com/blog/?p=2823</guid>

					<description><![CDATA[<p>Aprende a optimizar la renderización condicional en vistas de KumbiaPHP usando return 1; para escribir código más limpio y eficiente sin bloques if-else innecesarios.</p>
<p>La entrada <a href="https://kumbiaphp.com/blog/2024/10/14/optimizando-la-renderizacion-condicional-en-vistas-de-kumbiaphp-con-return-1/">Optimizando la Renderización Condicional en Vistas de KumbiaPHP con return 1;</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 el desarrollo web, especialmente al trabajar con motores de plantillas o frameworks MVC como <a href="https://kumbiaphp.com/blog/manuales-y-descargas/">KumbiaPHP</a>, es común <a href="https://github.com/KumbiaPHP/Documentation/blob/master/es/view.md">renderizar</a> condicionalmente partes de una vista basándose en la disponibilidad de datos. Tradicionalmente, los desarrolladores utilizan sentencias <em>if-else</em> para controlar el flujo de renderización de la vista. Sin embargo, el uso excesivo de bloques <em>if-else</em> puede desordenar tu código y dificultar su mantenimiento.</p>



<p class="wp-block-paragraph">En este artículo, exploraremos una forma más limpia y eficiente de gestionar la renderización condicional en KumbiaPHP con return 1;. También profundizaremos en por qué este enfoque es preferible sobre el uso estándar de <em>return;</em> o estructuras <em>if-else</em> anidadas.</p>



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



<h2 class="wp-block-heading">El Enfoque Tradicional: Uso de <em>if-else</em></h2>



<p class="wp-block-paragraph">Considera un escenario donde quieres mostrar un mensaje si no hay datos para mostrar y renderizar el resto de la vista solo cuando los datos están disponibles. Un enfoque típico podría verse así:</p>



<pre class="wp-block-code language-php"><code>&lt;?php if (!$products): ?&gt;
    &lt;h2&gt;No hay productos disponibles&lt;/h2&gt;
&lt;?php else: ?&gt;
    &lt;h1&gt;Lista de Productos&lt;/h1&gt;
    &lt;ul&gt;
        &lt;?php foreach ($products as $product): ?&gt;
            &lt;li&gt;
                &lt;h3&gt;&lt;?= $product-&gt;nombre ?&gt;&lt;/h3&gt;
                &lt;img src=&quot;&lt;?= $product-&gt;imagen_url ?&gt;&quot; alt=&quot;&lt;?= $product-&gt;nombre ?&gt;&quot; /&gt;
                &lt;p&gt;&lt;strong&gt;Categoría:&lt;/strong&gt; &lt;?= $product-&gt;categoria ?&gt;&lt;/p&gt;
                &lt;p&gt;&lt;strong&gt;Descripción:&lt;/strong&gt; &lt;?= $product-&gt;descripcion ?&gt;&lt;/p&gt;
                &lt;p&gt;&lt;strong&gt;Precio:&lt;/strong&gt; $&lt;?= number_format($product-&gt;precio, 2) ?&gt;&lt;/p&gt;
                &lt;p&gt;&lt;strong&gt;Stock:&lt;/strong&gt; &lt;?= $product-&gt;stock ?&gt; unidades disponibles&lt;/p&gt;
                &lt;p&gt;&lt;strong&gt;SKU:&lt;/strong&gt; &lt;?= $product-&gt;sku ?&gt;&lt;/p&gt;
                &lt;a href=&quot;/productos/&lt;?= $product-&gt;id ?&gt;&quot; class=&quot;btn&quot;&gt;Ver Detalles&lt;/a&gt;
            &lt;/li&gt;
        &lt;?php endforeach ?&gt;
    &lt;/ul&gt;
&lt;?php endif; ?&gt;
</code></pre>



<p class="wp-block-paragraph">Aunque esto funciona, envolver todo el código de la vista dentro de un bloque <em>else</em> añade una indentación y complejidad innecesarias, especialmente en vistas más grandes.</p>



<h2 class="wp-block-heading">Renderización condicional en KumbiaPHP con return 1; Una Solución Más Limpia:</h2>



<p class="wp-block-paragraph">Para mejorar la legibilidad y mantener el código más limpio, podemos utilizar <em>return 1</em>; para salir de la vista de manera anticipada si no hay datos. Aquí está cómo se vería el código:</p>



<pre class="wp-block-code language-php"><code>&lt;?php if (!$products) {
    echo &quot;&lt;h2&gt;No hay productos disponibles&lt;/h2&gt;&quot;;
    //View::partial(&#039;sin-datos&#039;); // o enviamos un partial
    return 1;
}?&gt;

&lt;h1&gt;Lista de Productos&lt;/h1&gt;
&lt;ul&gt;
    &lt;?php foreach ($products as $product): ?&gt;
        &lt;li&gt;
            &lt;h3&gt;&lt;?= $product-&gt;nombre ?&gt;&lt;/h3&gt;
            &lt;img src=&quot;&lt;?= $product-&gt;imagen_url ?&gt;&quot; alt=&quot;&lt;?= $product-&gt;nombre ?&gt;&quot; /&gt;
            &lt;p&gt;&lt;strong&gt;Categoría:&lt;/strong&gt; &lt;?= $product-&gt;categoria ?&gt;&lt;/p&gt;
            &lt;p&gt;&lt;strong&gt;Descripción:&lt;/strong&gt; &lt;?= $product-&gt;descripcion ?&gt;&lt;/p&gt;
            &lt;p&gt;&lt;strong&gt;Precio:&lt;/strong&gt; $&lt;?= number_format($product-&gt;precio, 2) ?&gt;&lt;/p&gt;
            &lt;p&gt;&lt;strong&gt;Stock:&lt;/strong&gt; &lt;?= $product-&gt;stock ?&gt; unidades disponibles&lt;/p&gt;
            &lt;p&gt;&lt;strong&gt;SKU:&lt;/strong&gt; &lt;?= $product-&gt;sku ?&gt;&lt;/p&gt;
            &lt;p&gt;&lt;strong&gt;Fecha de Lanzamiento:&lt;/strong&gt; &lt;?= date(&#039;d/m/Y&#039;, strtotime($product-&gt;fecha_lanzamiento)) ?&gt;&lt;/p&gt;
            &lt;p&gt;&lt;strong&gt;Calificación:&lt;/strong&gt; &lt;?= $product-&gt;calificacion ?&gt; estrellas&lt;/p&gt;
            &lt;a href=&quot;/productos/&lt;?= $product-&gt;id ?&gt;&quot; class=&quot;btn&quot;&gt;Ver Detalles&lt;/a&gt;
        &lt;/li&gt;
    &lt;?php endforeach ?&gt;
&lt;/ul&gt;
</code></pre>



<p>En este ejemplo:</p>
<ul>
<li>Si <em>$products</em> está vacío o es <em>false</em>, se muestra el mensaje «No hay productos disponibles» y la ejecución de la vista se detiene gracias a <em>return 1;</em>.</li>
<li>Si <em>$products</em> tiene datos, el código continúa ejecutándose y se muestra la lista detallada de productos sin necesidad de un bloque <em>else</em>.</li>
<li>El código es más limpio y fácil de leer al eliminar la indentación adicional.</li>
</ul>



<h2 class="wp-block-heading">Aplicación en Templates y Partials</h2>



<p class="wp-block-paragraph">La misma técnica puede aplicarse en <strong>templates</strong> y <strong>partials</strong>. Esto es útil cuando necesitas condicionar la inclusión de ciertas secciones o elementos de la interfaz de usuario.</p>



<h3 class="wp-block-heading">Ejemplo en un Partial</h3>



<p class="wp-block-paragraph">En un partial que muestra comentarios de un artículo:</p>



<pre class="wp-block-code language-php"><code>&lt;?php
if (!$comments) {
    echo &quot;&lt;p&gt;No hay comentarios aún. ¡Sé el primero en comentar!&lt;/p&gt;&quot;;
    return 1;
}?&gt;

&lt;div class=&quot;comments&quot;&gt;
    &lt;h3&gt;&lt;?= count($comments) ?&gt; Comentarios&lt;/h3&gt;
    &lt;?php foreach ($comments as $comment): ?&gt;
        &lt;div class=&quot;comment&quot;&gt;
            &lt;p&gt;&lt;strong&gt;&lt;?= $comment-&gt;autor ?&gt;&lt;/strong&gt; dice:&lt;/p&gt;
            &lt;p&gt;&lt;?= $comment-&gt;contenido ?&gt;&lt;/p&gt;
            &lt;p&gt;&lt;em&gt;Publicado el &lt;?= date(&#039;d/m/Y H:i&#039;, strtotime($comment-&gt;fecha_publicacion)) ?&gt;&lt;/em&gt;&lt;/p&gt;
        &lt;/div&gt;
    &lt;?php endforeach ?&gt;
&lt;/div&gt;
</code></pre>



<h2 class="wp-block-heading">Entendiendo <em>View::render()</em> y <em>include</em></h2>



<p class="wp-block-paragraph">En KumbiaPHP, las vistas se renderizan usando el método <em>View::render()</em>, que internamente incluye el archivo de vista:</p>



<pre class="wp-block-code language-php"><code>// Carga la vista
if (!include self::getView()) {
    throw new KumbiaException(&#039;Vista &quot;&#039; . self::getPath() . &#039;&quot; no encontrada&#039;, &#039;no_view&#039;);
}</code></pre>



<p class="wp-block-paragraph">La sentencia <em>include</em> en PHP devuelve <em>false</em> si falla al cargar el archivo (debido a que el archivo no existe, falta de permisos, etc.). Si el archivo incluido ejecuta un <em>return;</em> sin un valor, devuelve <em>null</em>, lo que la validación del  <em>include</em> se interpreta como <em>false</em>. Esto lleva a que <em>View::render()</em> crea que el archivo de vista no pudo ser incluido y lanza una excepción.</p>



<h3 class="wp-block-heading">La Importancia de <em>return 1;</em></h3>



<p class="wp-block-paragraph">Al usar <em>return 1;</em>, la vista devuelve <em>1</em>, lo que <em>include</em> interpreta como una inclusión exitosa. Esto permite que el proceso de renderización continúe sin problemas sin desencadenar una excepción.</p>



<h2 class="wp-block-heading">Beneficios de Usar <em>return 1;</em></h2>



<ul class="wp-block-list">
<li><strong>Código Más Limpio</strong>: Al eliminar bloques <em>else</em> innecesarios, el código es más sencillo y legible.</li>



<li><strong>Facilidad de Mantenimiento</strong>: Menos indentaciones y anidaciones facilitan la comprensión y modificación del código en el futuro.</li>



<li><strong>Consistencia</strong>: Puedes aplicar esta técnica en vistas, templates y partials de manera uniforme.</li>



<li><strong>Mayor Claridad</strong>: Separar la lógica de control del contenido principal mejora la claridad y organización del código.</li>
</ul>



<h2 class="wp-block-heading">Conclusión</h2>



<p class="wp-block-paragraph">Usar <em>return 1;</em> en las vistas de KumbiaPHP es una forma simple pero efectiva de gestionar la renderización condicional sin complicar tu código con estructuras <em>if-else</em> innecesarias. Asegura que tus vistas se ejecuten sin problemas y que el proceso de renderización continúe sin excepciones.</p>



<p class="wp-block-paragraph">Al adoptar este enfoque, puedes escribir vistas más limpias y mantenibles en tus aplicaciones KumbiaPHP. Pruébalo en tu próximo proyecto y experimenta la diferencia que hace en tu base de código.</p>



<p class="wp-block-paragraph"><em>¡Feliz codificación con KumbiaPHP!</em></p>
<p>La entrada <a href="https://kumbiaphp.com/blog/2024/10/14/optimizando-la-renderizacion-condicional-en-vistas-de-kumbiaphp-con-return-1/">Optimizando la Renderización Condicional en Vistas de KumbiaPHP con return 1;</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/2024/10/14/optimizando-la-renderizacion-condicional-en-vistas-de-kumbiaphp-con-return-1/feed/</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2823</post-id>	</item>
		<item>
		<title>Formularios a base de datos fácilmente con 1 línea de código</title>
		<link>https://kumbiaphp.com/blog/2019/05/27/formularios-a-base-de-datos-facilmente-1-linea-de-codigo/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=formularios-a-base-de-datos-facilmente-1-linea-de-codigo</link>
					<comments>https://kumbiaphp.com/blog/2019/05/27/formularios-a-base-de-datos-facilmente-1-linea-de-codigo/#comments</comments>
		
		<dc:creator><![CDATA[HenryStivens]]></dc:creator>
		<pubDate>Mon, 27 May 2019 16:16:18 +0000</pubDate>
				<category><![CDATA[Documentación]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[ejemplos]]></category>
		<guid isPermaLink="false">https://www.kumbiaphp.com/blog/?p=1641</guid>

					<description><![CDATA[<p>En KumbiaPHP existe una implementación que ahorra muchísimo trabajo a la hora de hacer formularios y la intención es&#8230;</p>
<p>La entrada <a href="https://kumbiaphp.com/blog/2019/05/27/formularios-a-base-de-datos-facilmente-1-linea-de-codigo/">Formularios a base de datos fácilmente con 1 línea de código</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 KumbiaPHP existe una implementación que ahorra muchísimo trabajo a la hora de hacer formularios y la intención es aprovechar al máximo las bondades que ofrece el framework. En este sentido tenemos la <strong>Autocarga de objeto</strong>, la cual, como su nombre indica asocia un campo de formulario a una tabla y campo de la base de datos.</p>



<h2 class="wp-block-heading">DDL y modelo para la tabla</h2>



<p class="wp-block-paragraph">Veamos la estructura de la tabla <em>user </em>que hemos visto en ejemplos anteriores:</p>



<pre class="wp-block-code language-sql"><code>CREATE TABLE `user` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `name` varchar(255) NOT NULL,
 `age` int(11) NOT NULL DEFAULT &#039;0&#039;,
 `email` varchar(255) NOT NULL, 
 PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;</code></pre>



<p class="wp-block-paragraph">Y el modelo para este caso lo haremos heredar de la clase <a href="https://github.com/KumbiaPHP/Documentation/blob/master/es/active-record.md">ActiveRecord</a> y lo ubicamos en <em>default/app/models/user.php</em></p>



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

class User extends ActiveRecord
{
    
}</code></pre>



<h2 class="wp-block-heading">Implementación de la autocarga de objeto</h2>



<p class="wp-block-paragraph">KumbiaPHP implementa la&nbsp;<strong>Autocarga de objeto</strong> la cual, siguiendo una convención mínima <strong>modelo.campo</strong> donde para el ejemplo el modelo es <em>user</em>, es decir existe una tabla llamada <em>user</em> en la base de datos y <em>campo</em> serán cada una de las columnas de esa tabla (id, name, age, email).</p>



<p class="wp-block-paragraph">En concordancia con las columnas de la tabla <em>use</em>r se indica el comportamiento de la <em>Autocarga de objeto</em> para que el controller no tenga que recoger uno a uno los valores enviado por POST.</p>



<p class="wp-block-paragraph">Para este caso usaremos el helper <a href="https://github.com/KumbiaPHP/Documentation/blob/master/es/view.md#clase-form"><em>Form</em></a>:</p>



<p class="wp-block-paragraph">Archivo: <em>default/app/views/user/create.phtml</em></p>



<pre class="wp-block-code language-php"><code>&lt;?php View::content() ?&gt;

&lt;?= Form::open() ?&gt;
&lt;?= Form::text(&#039;user.name&#039;) ?&gt; 
&lt;?= Form::email(&#039;user.email&#039;) ?&gt;
&lt;?= Form::number(&#039;user.age&#039;) ?&gt;
&lt;?= Form::submit(&#039;Guardar&#039;) ?&gt;
&lt;?= Form::close() ?&gt;</code></pre>



<p class="wp-block-paragraph">Automáticamente cuando esos valores vayan a la url /<em>user/create</em> KumbiaPHP interpreta que existe una tabla <em>user</em> con los campos <em>name, email</em> y<em> age.<br>
</em></p>



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



<h2 class="wp-block-heading">Aplicando autocarga en el controlador</h2>



<p class="wp-block-paragraph">Ahora vemos el código que se utiliza en <em>controllers/user_controller.php</em> en su acción <em>create()</em>.</p>



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



<pre class="wp-block-code language-php"><code>&lt;?php 
/**
 * Controlador para las acciones y vistas con el usuario 
 */ 
class UserController extends AppController
{ 

    public function index()
    {
        // Se debe implementar la función de listar
    }

    public function create()
    {
        //se verifica si se ha enviado via POST los datos
        if ( ! Input::hasPost(&#039;user&#039;)) {
            return;
        }
            
        //Intenta guardar el usuario
        if ((new User)-&gt;create(Input::post(&#039;user&#039;))) {
            //Mensaje de éxito 
            Flash::valid(&#039;Usuario creado&#039;);
            //Elimina los datos del POST, muestra limpio el formulario
            Input::delete();
            return;
        }
        //Mensaje de fallo 
        Flash::error(&#039;Falló al intentar crear el usuario&#039;);
    }
}</code></pre>



<p class="wp-block-paragraph">Si probamos el formulario y por alguna razón falla al guardar, automáticamente mostrará el formulario con los datos que se intentaron guardar, sin que debamos estar verificando si hay datos en el POST y si los hubiera indicarle al input el value, ya que el helper Form lo hace por nosotros.</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="922" height="825" src="https://www.kumbiaphp.com/blog/wp-content/uploads/2018/12/fomurlario-con-autocarga-de-objeto.png" alt="" class="wp-image-2059" srcset="https://kumbiaphp.com/blog/wp-content/uploads/2018/12/fomurlario-con-autocarga-de-objeto.png 922w, https://kumbiaphp.com/blog/wp-content/uploads/2018/12/fomurlario-con-autocarga-de-objeto-300x268.png 300w, https://kumbiaphp.com/blog/wp-content/uploads/2018/12/fomurlario-con-autocarga-de-objeto-768x687.png 768w" sizes="auto, (max-width: 922px) 100vw, 922px" /></figure>



<p class="wp-block-paragraph">Con esto se ahorra mucho trabajo y le sacamos el máximo provecho a KumbiaPHP Framework.</p>



<h2 class="wp-block-heading">Acceder a un campo del formulario enviado mediante POST</h2>



<p class="wp-block-paragraph">A veces nos consultan como se accede a un campo específico del formulario que viene en el POST en el controlador, y es muy sencillo veamos qué valor trae <em>Input::post(&#8216;user&#8217;):</em></p>



<pre class="wp-block-preformatted">array(3) {
  ['name']=&gt;
  string(8) "John Doe"
  ['email']=&gt;
  string(12) "jd@email.com"
  ['age]=&gt;
  int(30)
}
</pre>



<p class="wp-block-paragraph">Como pueden ver al hacer un <a href="http://php.net/manual/en/function.var-dump.php">var_dump()</a> de la variable nos muestra que es un simple arreglo por lo tanto la manera de acceder es la siguiente:</p>



<pre class="wp-block-code language-php"><code>$name = Input::post(&#039;user.name&#039;);
// or
$name = Input::post(&#039;user&#039;)[&#039;name&#039;];</code></pre>



<p class="wp-block-paragraph">Son casos especiales y lo mejor es que aprovechen al máximo la autocarga.</p>



<h2 class="wp-block-heading">Error común de novatos</h2>



<p class="wp-block-paragraph">Es común ver en quienes inician con KumbiaPHP cometer varios errores y uno de ellos es crear el objeto o registro campo por campo. Lo vemos mejor en el siguiente código de la función <em>create()</em> del controlador <em>UserController</em>:</p>



<pre class="wp-block-code language-php"><code>public function create()
{
    //se verifica si se ha enviado via POST los datos
    if (Input::hasPost(&#039;user&#039;)) {
        $data = Input::post(&#039;user&#039;);
        //Código incorrecto: Obtener del POST el valor de
        //cada input y asignarlo uno a uno al objeto.
        $user = new User();
        $user-&gt;name = $data[&#039;name&#039;];
        $user-&gt;email = $data[&#039;email&#039;];
        $user-&gt;age = $data[&#039;age&#039;];
        //Intenta guardar el usuario
        if ($user-&gt;create()) {
            //Mensaje de éxito
            Flash::valid(&#039;Usuario creado&#039;);
            //Elimina los datos del POST, muestra limpio el formulario
            Input::delete();
            return;
        }
        //Mensaje de fallo
        Flash::error(&#039;Falló al intentar crear el usuario&#039;);
    }
}</code></pre>



<p class="wp-block-paragraph">Funciona si, pero como pueden notar, se agregaron para este caso cinco líneas de código innecesarias. Ahora imaginen que no son tres campos en el formulario, si no que son diez, veinte o más campos por formulario. Ahora multipliquemos eso por el número de formularios de toda la aplicación.</p>



<p class="wp-block-paragraph">El código creado sería muy extenso y se convierte en difícil de leer y mantener.</p>



<p class="wp-block-paragraph">Espero que les sea de utilidad este artículo.</p>



<p class="wp-block-paragraph">PD: Agradecimientos a&nbsp;<span class="tadv-format-panel author"><a href="/blog/author/deivinson/">Deivinson Tejeda</a></span> por el borrador de este artículo.</p>


<p>La entrada <a href="https://kumbiaphp.com/blog/2019/05/27/formularios-a-base-de-datos-facilmente-1-linea-de-codigo/">Formularios a base de datos fácilmente con 1 línea de código</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/05/27/formularios-a-base-de-datos-facilmente-1-linea-de-codigo/feed/</wfw:commentRss>
			<slash:comments>6</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1641</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>&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>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>&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>&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>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>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">&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="  language-php">
</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">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="  language-php"></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>&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">&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="  language-php">
</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">public function example2() 
{ 
    //Importante: Sin vista y sin tamplate 
    View::select(null, null); 
    //Llama al ejemplo 2 
    HtmlToPdf::example2(); 
}</code><code class="  language-php">
</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">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="  language-php"></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">&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="  language-php">
</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>
		<item>
		<title>Select anidado o select dependientes</title>
		<link>https://kumbiaphp.com/blog/2017/11/17/select-anidado-o-select-dependientes/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=select-anidado-o-select-dependientes</link>
					<comments>https://kumbiaphp.com/blog/2017/11/17/select-anidado-o-select-dependientes/#comments</comments>
		
		<dc:creator><![CDATA[HenryStivens]]></dc:creator>
		<pubDate>Fri, 17 Nov 2017 00:58:20 +0000</pubDate>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Tutoriales y screencast]]></category>
		<category><![CDATA[ajax]]></category>
		<category><![CDATA[ejemplos]]></category>
		<category><![CDATA[select]]></category>
		<guid isPermaLink="false">https://www.kumbiaphp.com/blog/?p=1621</guid>

					<description><![CDATA[<p>Con este tutorial vamos a aprender como implementar select anidado o select dependientes usando KumbiaPHP y jquery. Es una&#8230;</p>
<p>La entrada <a href="https://kumbiaphp.com/blog/2017/11/17/select-anidado-o-select-dependientes/">Select anidado o select dependientes</a> se publicó primero en <a href="https://kumbiaphp.com/blog">KumbiaPHP Framework PHP en español</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Con este tutorial vamos a aprender como implementar select anidado o select dependientes usando <strong>KumbiaPHP</strong> y jquery. Es una <a href="http://es.wikipedia.org/wiki/Lista_(inform%C3%A1tica)#Listas_simples_enlazadas">lista simple enlazada</a> con tres niveles: Regiones, comunas y ciudades.</p>
<h2>Implementando el select anidado</h2>
<p>Primero que todo cargamos la librería jquery añadiendo en nuestro template activo la siguiente línea:</p>
<pre><code class="language-php">
&lt;?= Tag::js(&#039;jquery/jquery.min&#039;); ?&gt;
</code></pre>
<h2>La base de datos</h2>
<pre><code class="language-sql">
CREATE TABLE `ciudad` (
  `id` int(4) NOT NULL AUTO_INCREMENT,
  `comuna_id` int(4) NOT NULL,
  `nombre` varchar(100) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `FK_ciudad__comuna` (`comuna_id`),
  CONSTRAINT `FK_ciudad__comuna` FOREIGN KEY (`comuna_id`) REFERENCES `comuna` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

INSERT INTO `ciudad` VALUES (1,1,&#039;Primera Ciudad&#039;),(2,2,&#039;Primera Ciudad&#039;),(3,2,&#039;Segunda Ciudad&#039;),(4,3,&#039;Primera Ciudad&#039;),(5,3,&#039;Segunda Ciudad&#039;),(6,3,&#039;Tercera Ciudad&#039;);

CREATE TABLE `comuna` (
  `id` int(4) NOT NULL AUTO_INCREMENT,
  `region_id` int(4) NOT NULL,
  `nombre` varchar(100) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `FK_comuna__region` (`region_id`),
  CONSTRAINT `FK_comuna__region` FOREIGN KEY (`region_id`) REFERENCES `region` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

INSERT INTO `comuna` VALUES (1,1,&#039;Primera Comuna&#039;),(2,1,&#039;Segunda Comuna&#039;),(3,2,&#039;Primera Comuna&#039;),(4,3,&#039;Primera Comuna&#039;);

CREATE TABLE `region` (
  `id` int(4) NOT NULL AUTO_INCREMENT,
  `nombre` varchar(100) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

INSERT INTO `region` VALUES (1,&#039;Primera Region&#039;),(2,&#039;Segunda Region&#039;),(3,&#039;Tercera Region&#039;);
</code></pre>
<p><span id="more-1621"></span></p>
<h2>Los modelos</h2>
<p>Vamos a tener tres modelos que se encargaran de la consulta de los datos, heredando como no de la clase ActiveRecord:</p>
<p>Archivo: <em>app/models/region.php</em></p>
<pre><code class="language-php">
&lt;?php
class Region extends ActiveRecord
{
    /**
     * Lista todas las regiones
     * @return array
     */
    public function all()
    {
        return $this-&gt;find(&#039;order: nombre&#039;);
    }
}
</code></pre>
<p>Archivo: <em>app/models/comuna.php</em></p>
<pre><code class="language-php">
&lt;?php
class Comuna extends ActiveRecord
{

    /**
     * Lista todas las comunas de una región
     * 
     * @param int $region_id
     * @return array
     */
    public function allByRegion(int $region_id)//validación int de PHP7
    {
        return $this-&gt;find(&quot;region_id = $region_id&quot;, &#039;order: nombre&#039;);
    }
}
</code></pre>
<p>Archivo: <em>app/models/ciudad.php</em></p>
<pre><code class="language-php">
&lt;?php
class Ciudad extends ActiveRecord
{

    /**
     * Lista todas las ciudades de una comuna
     * 
     * @param int $region_id
     * @return array
     */
    public function allByComuna(int $comuna_id)//validación int de PHP7
    {
        return $this-&gt;find(&quot;comuna_id = $comuna_id&quot;, &#039;order: nombre&#039;);
    }
}
</code></pre>
<h2>El controlador</h2>
<p>Usaremos de ejemplo el controlador <em>UserController</em> aunque no implementaremos la funcionalidad de creación de un usuario para enforcarnos en el select anidado. Tendrá dos funciones auxiliares que nos cargarán los respectivos selects sin template, <em>getComunas()</em> y <em>getCiudades()</em>.</p>
<p>Archivo: <em>app/controllers/user_controller.php</em></p>
<pre><code class="language-php">
&lt;?php
/**
 * Controlador para las acciones y vistas con el usuario
 */
class UserController extends AppController
{

    public function index()
    {
        
    }

    public function create()
    {
        //se verifica si se ha enviado via POST los datos
        if (Input::hasPost(&#039;user&#039;)) {
            //
        }
    }

    public function getComunas()
    {
        //No es necesario el template
        View::template(null);
        //Carga la variable $region_id en la vista
        $this-&gt;region_id = Input::post(&#039;region_id&#039;);
    }

    public function getCiudades()
    {
        //No es necesario el template
        View::template(null);
        //Carga la variable $comuna_id en la vista
        $this-&gt;comuna_id = Input::post(&#039;comuna_id&#039;);
    }
}
</code></pre>
<h2>Las vistas</h2>
<p>La primera vista es la de crear un usuario, la cual contendrá los tres selects, aunque en principio solo mostrará el primero y unas capas vacias, ya que los siguientes dependen de qué se seleccione y serán cargados mediante ajax:</p>
<p>Archivo: <em>app/views/user/create.phtml</em></p>
<pre><code class="language-php">&lt;h1&gt;Crear usuario&lt;/h1&gt;
&lt;?= Html::linkAction(&#039;&#039;, &#039;Listar usuarios&#039;, &#039;class=&quot;button&quot;&#039;) ?&gt;
&lt;?php View::content() ?&gt;
&lt;?= Form::open() ?&gt;
  &lt;div class=&quot;row&quot;&gt;
    &lt;div class=&quot;six columns&quot;&gt;
      &lt;label for=&quot;user_region_id&quot;&gt;Región&lt;/label&gt;
      &lt;?= Form::dbSelect(&#039;user.region_id&#039;, &#039;nombre&#039;, array(&#039;region&#039;, &#039;all&#039;), &#039;- Seleccione -&#039;); ?&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;row&quot;&gt;
    &lt;div class=&quot;six columns&quot;&gt;
      &lt;label for=&quot;user_comuna_id&quot;&gt;Comuna&lt;/label&gt;
      &lt;div id=&#039;div_comunas&#039;&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
  &lt;div class=&quot;row&quot;&gt;
    &lt;div class=&quot;six columns&quot;&gt;
      &lt;label for=&quot;user_ciudad_id&quot;&gt;Ciudad&lt;/label&gt;
      &lt;div id=&#039;div_ciudades&#039;&gt;&lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;input class=&quot;button-primary&quot; value=&quot;Enviar&quot; type=&quot;submit&quot;&gt;
&lt;?= Form::close() ?&gt;

&lt;script type=&#039;text/javascript&#039;&gt;
  $(document).on(&#039;change&#039;, &quot;#user_region_id&quot;, function () {
    var region_id = $(&#039;#user_region_id&#039;).val();
     $.ajax({
       type: &quot;POST&quot;,
       url: &quot;&lt;?php echo PUBLIC_PATH . &#039;user/getComunas/&#039;; ?&gt;&quot;,
       data: &quot;region_id=&quot; + region_id,
       success: function (html) {
         $(&quot;#div_comunas&quot;).html(html);
       }
    });
  });
&lt;/script&gt;</code></pre>
<p>La vista anterior con javascript añade un listener para que cuando el valor del select que contiene las regiones cambie, haga un llamado mediante ajax para obtener el listado de comunas por región y este resultado lo carga en la capa <em>div_comunas</em>.</p>
<p>La siguiente vista cargará el select usando el helper <em>Form::dbSelect()</em> usando el método <em>allByRegion()</em> del modelo <em>Comuna</em> y pasándole como parámetro <em>$region_id</em>.<br />
 Archivo: <em>app/views/user/getComunas.phtml</em></p>
<pre><code class="language-php">
&lt;?= Form::dbSelect(&quot;user.comuna_id&quot;, &#039;nombre&#039;, array(&#039;comuna&#039;, &#039;allByRegion&#039;, $region_id), &#039;- Seleccione -&#039;); ?&gt;

&lt;script type=&#039;text/javascript&#039;&gt;
  $(document).on(&#039;change&#039;, &quot;#user_comuna_id&quot;, function () {
    var comuna_id = $(&#039;#user_comuna_id&#039;).val();
      $.ajax({
        type: &quot;POST&quot;,
        url: &quot;&lt;?php echo PUBLIC_PATH . &#039;user/getCiudades/&#039;; ?&gt;&quot;,
        data: &quot;comuna_id=&quot; + comuna_id,
          success: function (html) {
            $(&quot;#div_ciudades&quot;).html(html);
          }
       });
 });
&lt;/script&gt;</code></pre>
<p>La vista anterior con javascript añade un listener para que cuando el valor del select que contiene las comunas cambie, haga un llamado mediante ajax para obtener el listado de ciudades por comuna y este resultado lo carga en la capa <em>div_ciudades</em>.</p>
<p>La siguiente vista es similar a <em>getComunas.phtml,</em> lo que hace es cargar todas las ciudades que pertenezcan a una comunidad usando el helper <em>Form::dbSelect()</em> pasandole como parámetros el nombre del modelo <em>ciudad, </em>el método <em>allByComuna()</em> y el parámetro de consulta <em>$comuna_id.</em></p>
<p>Archivo: <em>app/views/user/getCiudades.phtml</em></p>
<pre><code class="language-php">&lt;?= Form::dbSelect(&quot;user.ciudad_id&quot;, &#039;nombre&#039;, array(&#039;ciudad&#039;, &#039;allByComuna&#039;, $comuna_id), &#039;- Seleccione -&#039;); ?&gt; </code></pre>
<h2>Ejecutando el ejemplo</h2>
<p>Cuando cargamos la url <em>/user/create </em>veremos algo como lo siguiente, en primera instacia solo va mostrar las regiones:</p>
<figure><a href="https://www.kumbiaphp.com/blog/wp-content/uploads/2017/11/Screenshot-from-2017-11-06-16-08-10.png"><img loading="lazy" decoding="async" class="wp-image-1632 size-full" src="https://www.kumbiaphp.com/blog/wp-content/uploads/2017/11/Screenshot-from-2017-11-06-16-08-10-e1510503449909.png" alt="Muestra el primer select anidado" width="996" height="503" srcset="https://kumbiaphp.com/blog/wp-content/uploads/2017/11/Screenshot-from-2017-11-06-16-08-10-e1510503449909.png 996w, https://kumbiaphp.com/blog/wp-content/uploads/2017/11/Screenshot-from-2017-11-06-16-08-10-e1510503449909-300x152.png 300w, https://kumbiaphp.com/blog/wp-content/uploads/2017/11/Screenshot-from-2017-11-06-16-08-10-e1510503449909-768x388.png 768w, https://kumbiaphp.com/blog/wp-content/uploads/2017/11/Screenshot-from-2017-11-06-16-08-10-e1510503449909-940x475.png 940w" sizes="auto, (max-width: 996px) 100vw, 996px" /></a><figcaption>Muestra el primer select anidado</figcaption></figure>
<p>Lo siguientes dos select se mostraran comforme se vaya seleccionando una región y posteriormente una comuna.</p>
<figure><a href="https://www.kumbiaphp.com/blog/wp-content/uploads/2017/11/Screenshot-from-2017-11-06-16-08-27.png"><img loading="lazy" decoding="async" class="wp-image-1630 size-full" src="https://www.kumbiaphp.com/blog/wp-content/uploads/2017/11/Screenshot-from-2017-11-06-16-08-27-e1510503503511.png" alt="Select anidado" width="996" height="568" srcset="https://kumbiaphp.com/blog/wp-content/uploads/2017/11/Screenshot-from-2017-11-06-16-08-27-e1510503503511.png 996w, https://kumbiaphp.com/blog/wp-content/uploads/2017/11/Screenshot-from-2017-11-06-16-08-27-e1510503503511-300x171.png 300w, https://kumbiaphp.com/blog/wp-content/uploads/2017/11/Screenshot-from-2017-11-06-16-08-27-e1510503503511-768x438.png 768w, https://kumbiaphp.com/blog/wp-content/uploads/2017/11/Screenshot-from-2017-11-06-16-08-27-e1510503503511-940x536.png 940w" sizes="auto, (max-width: 996px) 100vw, 996px" /></a><figcaption>Lista enlazada simple de tres niveles</figcaption></figure>
<h2>Descargar código completo</h2>
<p>Como siempre, el código completo está disponible para todos en el siguiente repositorio en Github listo para usar con Docker: <a href="https://github.com/henrystivens/dependent-select">https://github.com/henrystivens/dependent-select</a></p>
<p>La entrada <a href="https://kumbiaphp.com/blog/2017/11/17/select-anidado-o-select-dependientes/">Select anidado o select dependientes</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/2017/11/17/select-anidado-o-select-dependientes/feed/</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1621</post-id>	</item>
		<item>
		<title>Paginación en PHP fácil y rápida</title>
		<link>https://kumbiaphp.com/blog/2017/07/21/paginacion-en-php-facil/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=paginacion-en-php-facil</link>
					<comments>https://kumbiaphp.com/blog/2017/07/21/paginacion-en-php-facil/#comments</comments>
		
		<dc:creator><![CDATA[HenryStivens]]></dc:creator>
		<pubDate>Fri, 21 Jul 2017 05:01:24 +0000</pubDate>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Tutoriales y screencast]]></category>
		<category><![CDATA[ejemplos]]></category>
		<category><![CDATA[paginacion]]></category>
		<guid isPermaLink="false">https://www.kumbiaphp.com/blog/?p=1580</guid>

					<description><![CDATA[<p>Con este tutorial mostraremos como realizar la paginación en PHP de un listado de usuarios usando nuestro framework favorito&#8230;</p>
<p>La entrada <a href="https://kumbiaphp.com/blog/2017/07/21/paginacion-en-php-facil/">Paginación en PHP fácil y rápida</a> se publicó primero en <a href="https://kumbiaphp.com/blog">KumbiaPHP Framework PHP en español</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p>Con este tutorial mostraremos como realizar la paginación en PHP de un listado de usuarios usando nuestro framework favorito <strong>KumbiaPHP</strong>. Utilizaremos como base el proyecto anterior, donde mostramos <a href="https://www.kumbiaphp.com/blog/2017/03/27/subir-imagen-y-datos-con-kumbiaphp/">como subir una imagen y asignarla a un usuario</a>, y cambiaremos el listado normal por un listado paginado.</p>
<h2>En el controlador</h2>
<p>Lo primero es mencionar que el ActiveRecord cuenta con un paginador muy bueno(Ver sección en el manual: <a href="https://github.com/KumbiaPHP/Documentation/blob/master/es/active-record.md#paginando-en-activerecord">Paginando en ActiveRecord</a>), que nos permitirá con una sola línea de código implementar la <strong>paginación en php</strong>. Vamos al controlador de <em>usuarios</em> y añadimos la función <em>page(&#8230;)</em>:</p>
<p>Archivo: <em>app/controllers/user_controller.php</em></p>
<pre><code class="language-php">
public function page(int $page = 1)//validación &#039;int&#039; con php7
{        
    $this-&gt;page = (new User)-&gt;paginate(&quot;page: $page&quot;, &#039;per_page: 7&#039;);
}
</code></pre>
<p>El parametro <em>$page</em> tiene un valor por defecto, así que, si no le pasamos ningun valor será igual a 1. En el llamado a la función <em>paginate()</em> el primer parámetro es <em>page,</em> con el cual le indicamos el número de página que deseamos mostrar. El segundo parámetro es <em>per_page,</em> con el cual le indicamos el número de elementos a mostrar por página.</p>
<p><span id="more-1580"></span></p>
<h2>La vista</h2>
<p>Creamos un nuevo archivo llamado <em>page.html </em>es una vista similar a <em>index.phtml,</em> con la diferencia que para obtener el arreglo de elementos, ojo esto es muy importante, se accede al atributo <em>items </em>del objeto<em> $page</em>. La otra diferencia es que se hace llamado a un partial el cual nos mostrará el paginador con el número de página actual y los números de páginas disponibles. Si, este partial nos ahorra un montón de trabajo ya que en él está toda la lógica de visualización.</p>
<p>Archivo: <em>app/views/user/page.phtml</em></p>
<pre><code class="language-php">&lt;h1&gt;Lista de usuarios&lt;/h1&gt;
&lt;?= Html::linkAction(&#039;create&#039;, &#039;Crear&#039;, &#039;class=&quot;button&quot;&#039;) ?&gt; 
&lt;?php View::content() ?&gt;
&lt;?php if (count($page-&gt;items) &gt; 0) { ?&gt;
    &lt;table class=&quot;u-fu$pagell-width&quot;&gt;
        &lt;thead&gt;
            &lt;tr&gt;            
                &lt;th&gt;Nombre&lt;/th&gt;
                &lt;th&gt;Edad&lt;/th&gt;
                &lt;th&gt;Correo&lt;/th&gt;
                &lt;th&gt;Foto&lt;/th&gt;
                &lt;th&gt;Acciones&lt;/th&gt;
            &lt;/tr&gt;
        &lt;/thead&gt;
        &lt;tbody&gt; 
            &lt;?php foreach ($page-&gt;items as $item) { ?&gt; 
                &lt;tr&gt;
                    &lt;td&gt;&lt;?= $item-&gt;name ?&gt;&lt;/td&gt;
                    &lt;td&gt;&lt;?= $item-&gt;age ?&gt;&lt;/td&gt;
                    &lt;td&gt;&lt;?= $item-&gt;email ?&gt;&lt;/td&gt;
                    &lt;td&gt;&lt;?= $item-&gt;photo ?&gt;&lt;/td&gt;
                    &lt;td&gt;&lt;?= Html::linkAction(&quot;edit/$item-&gt;id&quot;, &#039;Editar&#039;) ?&gt; | &lt;?= Html::linkAction(&quot;update_photo/$item-&gt;id&quot;, &#039;Actualizar foto&#039;) ?&gt;&lt;/td&gt;
                &lt;/tr&gt; 
            &lt;?php } ?&gt;        
        &lt;/tbody&gt;
    &lt;/table&gt;
&lt;?php } else { ?&gt;
    &lt;h2&gt;No hay ningún registro&lt;/h2&gt;
&lt;?php } ?&gt;

&lt;?php View::partial(&#039;paginators/classic&#039;, false, array(&#039;page&#039; =&gt; $page)); ?&gt;
</code></pre>
<p>Existen otros partials que sirven de paginadores, también puedes crear los tuyos para que se adapten a tu diseño.</p>
<h2>Así se ve la paginación en PHP</h2>
<figure><a href="https://www.kumbiaphp.com/blog/wp-content/uploads/2017/07/Captura-de-pantalla-2017-07-18-a-las-10.38.26.png"><img loading="lazy" decoding="async" class="wp-image-1585 size-large" src="https://www.kumbiaphp.com/blog/wp-content/uploads/2017/07/Captura-de-pantalla-2017-07-18-a-las-10.38.26-1024x654.png" alt="Paginación en PHP" width="940" height="600" srcset="https://kumbiaphp.com/blog/wp-content/uploads/2017/07/Captura-de-pantalla-2017-07-18-a-las-10.38.26-1024x654.png 1024w, https://kumbiaphp.com/blog/wp-content/uploads/2017/07/Captura-de-pantalla-2017-07-18-a-las-10.38.26-300x192.png 300w, https://kumbiaphp.com/blog/wp-content/uploads/2017/07/Captura-de-pantalla-2017-07-18-a-las-10.38.26-768x490.png 768w, https://kumbiaphp.com/blog/wp-content/uploads/2017/07/Captura-de-pantalla-2017-07-18-a-las-10.38.26-940x600.png 940w, https://kumbiaphp.com/blog/wp-content/uploads/2017/07/Captura-de-pantalla-2017-07-18-a-las-10.38.26.png 1392w" sizes="auto, (max-width: 940px) 100vw, 940px" /></a><figcaption>Lista de usuarios paginados</figcaption></figure>
<p>Si vas a usar otra acción diferente de <em>page() </em>debes pasarle al partial como parámetro la url de la acción, así:</p>
<p>Archivo: <em>app/views/user/page.phtml</em></p>
<pre><code class="language-php">
&lt;?php View::partial(&#039;paginators/classic&#039;, false, array(&#039;page&#039; =&gt; $page, &#039;url&#039; =&gt; &#039;user/index&#039;)); ?&gt;
</code></pre>
<h2>Descargar código completo</h2>
<p>Como siempre, el código completo está disponible para todos en el siguiente repositorio en Github listo para usar con Docker: <a href="https://github.com/henrystivens/paginate-php">https://github.com/henrystivens/paginate-php </a></p>
<p>La entrada <a href="https://kumbiaphp.com/blog/2017/07/21/paginacion-en-php-facil/">Paginación en PHP fácil y rápida</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/2017/07/21/paginacion-en-php-facil/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1580</post-id>	</item>
		<item>
		<title>ScaffoldController: Modificando comportamientos y contenidos</title>
		<link>https://kumbiaphp.com/blog/2017/04/12/scaffolding-con-kumbiaphp-modificando-comportamientos-y-contenidos-segun-nuestra-necesidad/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=scaffolding-con-kumbiaphp-modificando-comportamientos-y-contenidos-segun-nuestra-necesidad</link>
					<comments>https://kumbiaphp.com/blog/2017/04/12/scaffolding-con-kumbiaphp-modificando-comportamientos-y-contenidos-segun-nuestra-necesidad/#comments</comments>
		
		<dc:creator><![CDATA[Nelson Rojas]]></dc:creator>
		<pubDate>Wed, 12 Apr 2017 13:28:01 +0000</pubDate>
				<category><![CDATA[ActiveRecord]]></category>
		<category><![CDATA[Documentación]]></category>
		<category><![CDATA[Tutoriales y screencast]]></category>
		<category><![CDATA[crud]]></category>
		<category><![CDATA[ejemplos]]></category>
		<category><![CDATA[scaffold]]></category>
		<guid isPermaLink="false">https://www.kumbiaphp.com/blog/?p=1344</guid>

					<description><![CDATA[<p>La entrega anterior hablamos acerca del uso de la técnica de Scaffolding para CRUD con KumbiaPHP usando la clase&#8230;</p>
<p>La entrada <a href="https://kumbiaphp.com/blog/2017/04/12/scaffolding-con-kumbiaphp-modificando-comportamientos-y-contenidos-segun-nuestra-necesidad/">ScaffoldController: Modificando comportamientos y contenidos</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 entrega anterior hablamos acerca del uso de la técnica de<a href="https://www.kumbiaphp.com/blog/2017/04/03/scaffolding-para-crud-abm-sencillos-y-no-tanto-primera-parte/"> Scaffolding para CRUD con KumbiaPHP</a> usando la clase <strong>ScaffoldController</strong>. Espero que muchos se hayan sorprendido gratamente con la funcionalidad que ciertamente ahorra mucho trabajo rutinario, ya que es altamente flexible.</p>
<p>Para que se entusiasmen, dentro de las posibilidades  tenemos: reescribir métodos y modificar comportamientos en controladores, modificar los archivos de vista, e incluso puedes crear tus propios scaffoldings. Pero bueno, vamos paso a paso.</p>
<h2>Manos a la obra con ScaffoldController</h2>
<p>Vamos a trabajar en base a supuestos. Supongamos que queremos mostrar el nombre de la categoría padre para aquellas categorías que estén anidadas.</p>
<p><a href="https://www.kumbiaphp.com/blog/wp-content/uploads/2017/04/index-sin-cambios-1.png"><img loading="lazy" decoding="async" class="alignnone wp-image-1351 size-full" src="https://www.kumbiaphp.com/blog/wp-content/uploads/2017/04/index-sin-cambios-1.png" alt="Lista de categorías" width="958" height="405" srcset="https://kumbiaphp.com/blog/wp-content/uploads/2017/04/index-sin-cambios-1.png 958w, https://kumbiaphp.com/blog/wp-content/uploads/2017/04/index-sin-cambios-1-300x127.png 300w, https://kumbiaphp.com/blog/wp-content/uploads/2017/04/index-sin-cambios-1-768x325.png 768w, https://kumbiaphp.com/blog/wp-content/uploads/2017/04/index-sin-cambios-1-940x397.png 940w" sizes="auto, (max-width: 958px) 100vw, 958px" /></a></p>
<p>Como se ve en la lista, las categorías relacionadas sólo se ven con su identificador.<br />
Por lo tanto, vamos a modificar <strong>la fuente de datos</strong> que pasamos a la vista <strong>Index</strong> para que ésta pueda presentar los contenidos respectivos.</p>
<h2>En el modelo</h2>
<p>Lo que vamos a hacer es crear un método que cumpla con lo que queremos lograr: mostrar el contenido de la tabla de categorías incluyendo el nombre de la categoría padre en aquellas categorías que heredan de otra. De este modo tendremos una modificación como la siguiente:</p>
<p>Archivo: <em>models/categorias.php</em></p>
<pre class=" language-php"><code class=" language-php">&lt;span class=&quot;token delimiter&quot;&gt;&lt;?php&lt;/span&gt;

&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Categorias&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ActiveRecord&lt;/span&gt; 
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;getCategorias&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$page&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; 
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;paginate&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
            &lt;span class=&quot;token string&quot;&gt;&#039;columns: categorias.id, categorias.nombre, cat.nombre as categorias_id, categorias.creada_at, categorias.actualizada_in&#039;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; 
            &lt;span class=&quot;token string&quot;&gt;&#039;join: left outer join categorias cat on categorias.categorias_id = cat.id&#039;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
            &lt;span class=&quot;token string&quot;&gt;&quot;page: $page&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#039;order: categorias.id desc&#039;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;</code></pre>
<h2>En el controlador</h2>
<p>El segundo cambio lo haremos desde el controlador, para cargar los cambios que hemos hecho en el modelo. Lo que <strong>reemplazaremos</strong> (porque es una sobre escritura de index en ScaffoldController) será la función <strong>index</strong> tal como se muestra a continuación.</p>
<p>Archivo: controllers<em>/categorias_controller.php</em></p>
<pre class=" language-php"><code class=" language-php">&lt;span class=&quot;token delimiter&quot;&gt;&lt;?php&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CategoriasController&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ScaffoldController&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$model&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#039;Categorias&#039;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;

    &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;function&lt;/span&gt; &lt;span class=&quot;token function&quot;&gt;index&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$page&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
        &lt;span class=&quot;token variable&quot;&gt;$this&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token property&quot;&gt;data&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Categorias&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;-&lt;/span&gt;&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&lt;span class=&quot;token function&quot;&gt;getCategorias&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token variable&quot;&gt;$page&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
 
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;</code></pre>
<p><span id="more-1344"></span></p>
<h2>Ahora se ve así</h2>
<p>Con esto lograremos que el listado cumpla que el requerimiento solicitado.</p>
<p><a href="https://www.kumbiaphp.com/blog/wp-content/uploads/2017/04/index-con-cambios-1.png"><img loading="lazy" decoding="async" class="alignnone wp-image-1352 size-full" src="https://www.kumbiaphp.com/blog/wp-content/uploads/2017/04/index-con-cambios-1.png" alt="Lista modificada de las categorías" width="967" height="400" srcset="https://kumbiaphp.com/blog/wp-content/uploads/2017/04/index-con-cambios-1.png 967w, https://kumbiaphp.com/blog/wp-content/uploads/2017/04/index-con-cambios-1-300x124.png 300w, https://kumbiaphp.com/blog/wp-content/uploads/2017/04/index-con-cambios-1-768x318.png 768w, https://kumbiaphp.com/blog/wp-content/uploads/2017/04/index-con-cambios-1-940x389.png 940w" sizes="auto, (max-width: 967px) 100vw, 967px" /></a></p>
<h2>¿Por qué funciona?</h2>
<p>Como puede verse, con cambios mínimos hemos logrado adecuar la presentación de la vista <strong>index</strong> sin actualizar su archivo. Lo que hemos hecho principalmente es un reemplazo dentro de la metadata de ActiveRecord. Scaffolding espera contar con todos los atributos de la tabla de categorías (id, nombre, categorias_id, creada_at, actualizada_in). Nosotros hemos modificado la salida cambiando categorias_id por nombre desde categorias (nombre as categorias_id). Así hemos logrado que el pintador de la vista index haga su tarea sin enterarse del reemplazo que hemos hecho a nivel de modelo.</p>
<p>Bueno, eso es todo por esta semana. En la siguiente entrega veremos cómo modificar una vista particular para hacerla parecer según nuestros requerimientos. (<a href="https://www.kumbiaphp.com/blog/2017/05/16/scaffoldcontroller-modificando-vistas/">ver parte 3</a>)</p>
<h2>Últimas recomendaciones</h2>
<p>Recuerden que pueden revisar el código desde: <a href="https://github.com/nelsonrojas/Scaffold-KumbiaPHP" target="_blank" rel="noopener noreferrer">https://github.com/nelsonrojas/Scaffold-KumbiaPHP</a></p>
<p>No olvides visitarnos en <a href="http://slack.kumbiaphp.com/" target="_blank" rel="noopener noreferrer">http://slack.kumbiaphp.com/</a> para contarnos cómo te va usando <a href="https://www.kumbiaphp.com" target="_blank" rel="noopener noreferrer">KumbiaPHP</a>. Si necesitas apoyo procuraremos estar atentos. Además, si te gusta lo que escribimos compártelo ya mismo con tus amigos y colegas.</p>
<p>Saludos y larga vida a KumbiaPHP!</p>
<p>Con cariño desde Talca, Chile: <a href="https://twitter.com/nelsonrojas" target="_blank" rel="noopener noreferrer">@nelsonrojas</a></p>
<p>Ps: Si te perdiste lo que escribimos la semana pasada, puedes leerlo aquí: <a href="https://www.kumbiaphp.com/blog/2017/04/03/scaffolding-para-crud-abm-sencillos-y-no-tanto-primera-parte/">https://www.kumbiaphp.com/blog/2017/04/03/scaffolding-para-crud-abm-sencillos-y-no-tanto-primera-parte/</a></p>
<p>Si quieres ver lo que sigue: <a href="https://www.kumbiaphp.com/blog/2017/05/16/scaffoldcontroller-modificando-vistas/">ScaffoldController: Modificando vistas</a></p>
<p>La entrada <a href="https://kumbiaphp.com/blog/2017/04/12/scaffolding-con-kumbiaphp-modificando-comportamientos-y-contenidos-segun-nuestra-necesidad/">ScaffoldController: Modificando comportamientos y contenidos</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/2017/04/12/scaffolding-con-kumbiaphp-modificando-comportamientos-y-contenidos-segun-nuestra-necesidad/feed/</wfw:commentRss>
			<slash:comments>2</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1344</post-id>	</item>
		<item>
		<title>Scaffolding para CRUD (ABM) sencillos (y no tanto) &#8211; primera parte</title>
		<link>https://kumbiaphp.com/blog/2017/04/03/scaffolding-para-crud-abm-sencillos-y-no-tanto-primera-parte/?utm_source=rss&#038;utm_medium=rss&#038;utm_campaign=scaffolding-para-crud-abm-sencillos-y-no-tanto-primera-parte</link>
					<comments>https://kumbiaphp.com/blog/2017/04/03/scaffolding-para-crud-abm-sencillos-y-no-tanto-primera-parte/#comments</comments>
		
		<dc:creator><![CDATA[Nelson Rojas]]></dc:creator>
		<pubDate>Mon, 03 Apr 2017 10:39:38 +0000</pubDate>
				<category><![CDATA[ActiveRecord]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Tutoriales y screencast]]></category>
		<category><![CDATA[crud]]></category>
		<category><![CDATA[ejemplos]]></category>
		<category><![CDATA[scaffold]]></category>
		<guid isPermaLink="false">https://www.kumbiaphp.com/blog/?p=1288</guid>

					<description><![CDATA[<p>¿Qué es Scaffolding? Cuando comenzó el fenómeno de los frameworks de desarrollo web, una de sus banderas de lucha&#8230;</p>
<p>La entrada <a href="https://kumbiaphp.com/blog/2017/04/03/scaffolding-para-crud-abm-sencillos-y-no-tanto-primera-parte/">Scaffolding para CRUD (ABM) sencillos (y no tanto) &#8211; primera parte</a> se publicó primero en <a href="https://kumbiaphp.com/blog">KumbiaPHP Framework PHP en español</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h2>¿Qué es Scaffolding?</h2>
<p>Cuando comenzó el fenómeno de los frameworks de desarrollo web, una de sus banderas de lucha estuvo de la mano de los scaffoldings (andamios).</p>
<p>Un scaffold es en sí una técnica que proveen muchos frameworks, con la que podrás tener un gestor de datos para una tabla particular escribiendo una cantidad mínima de código (en KumbiaPHP bastan 7 líneas de código – excluyendo 2 líneas de encabezado php – ).</p>
<p>En mis primeros años de kumbiero comencé creando un controlador para las acciones clásicas de CRUD (Create, Read, Update y Delete), un modelo para apuntar la tabla de la base de datos y al menos 3 archivos de vista (index, agregar y editar).</p>
<p>Para hacer el CRUD de otra tabla copiaba el controlador inicial en el nuevo, luego editaba todo lo que correspondía, y lo mismo hacía para el modelo y las vistas.</p>
<p>Como verán es un trabajo arduo, pero no es tanto trabajo… a menos que tengas más de 10 tablas.</p>
<p>Si pueden hacer el ejercicio de mirar el bosque desde lejos, casi todos los CRUDs creados tienen las mismas acciones, y usan las mismas vistas (con sus leves diferencias).</p>
<h2>La iluminación</h2>
<p>Fue entonces que un día de IRC (el chat que usábamos antes), los colegas del core de KumbiaPHP me presentaron a ScaffoldController.</p>
<p>Es un amigo silencioso, puesto que está alojado en default/app/libs, pero además es un amigo confiable, pues hereda de AdminController (eso quiere decir que si damos cierta habilidad de autenticación al AdminController, los controllers que hagamos usando ScaffoldController también estarán asegurados).</p>
<h2>Configuración inicial</h2>
<p>Si este es un proyecto que ha iniciado desde cero, deberá configurar el acceso a la base de datos antes de continuar.</p>
<p>Para eso usaremos el archivo <em>default/app/config/database.ini</em>. En él se definen los entornos de datos que usará nuestra aplicación, los que normalmente son: development (desarrollo) y production (producción)</p>
<p><a href="https://www.kumbiaphp.com/blog/wp-content/uploads/2017/04/database-setting.png"><img loading="lazy" decoding="async" class="alignnone wp-image-1890 size-full" src="https://www.kumbiaphp.com/blog/wp-content/uploads/2017/04/database-setting.png" alt="Archivo databases.ini de KumbiaPHP" width="585" height="339" srcset="https://kumbiaphp.com/blog/wp-content/uploads/2017/04/database-setting.png 585w, https://kumbiaphp.com/blog/wp-content/uploads/2017/04/database-setting-300x174.png 300w" sizes="auto, (max-width: 585px) 100vw, 585px" /></a></p>
<p>Los parámetros de configuración que debemos revisar son:</p>
<ul>
<li><strong>host</strong>: Nombre de red o dirección ip del equipo en el cual está instalada la base de datos.</li>
<li><strong>username</strong>: usuario de la base de datos.</li>
<li><strong>password</strong>: contraseña del usuario de la base de datos.</li>
<li><strong>name</strong>: nombre de la base de datos.</li>
<li><strong>type</strong>: el tipo de base de datos que usará el proyecto, como mysql, pgsql, oracle.</li>
</ul>
<p>Para indicarle al proyecto que debe usar uno u otro entorno de base de datos, será necesario modificar el archivo de configuración <em>default/app/config/config.php</em>. De forma predeterminada la configuración del entorno de base de datos es &#8216;default&#8217;, pero lo dejaremos inicialmente como &#8216;development&#8217;.</p>
<p><a href="https://www.kumbiaphp.com/blog/wp-content/uploads/2017/04/datbase-default.png"><img loading="lazy" decoding="async" class="alignnone wp-image-1891 size-full" src="https://www.kumbiaphp.com/blog/wp-content/uploads/2017/04/datbase-default.png" alt="Archivo config.php de KumbiaPHP" width="473" height="419" srcset="https://kumbiaphp.com/blog/wp-content/uploads/2017/04/datbase-default.png 473w, https://kumbiaphp.com/blog/wp-content/uploads/2017/04/datbase-default-300x266.png 300w" sizes="auto, (max-width: 473px) 100vw, 473px" /></a></p>
<p>Lista la configuración, sigamos con la acción.</p>
<h2>De la teoría a la acción</h2>
<p>Bueno, mucho texto y poca acción (o como versa el dicho “mucho ruido y pocas nueces”).</p>
<p>En nuestro primer ejemplo usaremos la clásica tabla de categorías, con la siguiente estructura:</p>
<pre class="  language-sql"><code class="  language-sql">
&lt;span class=&quot;token keyword&quot;&gt;CREATE&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;TABLE&lt;/span&gt; categorias &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
 id &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;11&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;NOT&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;NULL&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;AUTO_INCREMENT&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
 nombre &lt;span class=&quot;token keyword&quot;&gt;varchar&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;200&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;NOT&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;NULL&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;UNIQUE&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
 categorias_id &lt;span class=&quot;token keyword&quot;&gt;int&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token number&quot;&gt;11&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
 creada_at &lt;span class=&quot;token keyword&quot;&gt;timestamp&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
 actualizada_in &lt;span class=&quot;token keyword&quot;&gt;timestamp&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
 &lt;span class=&quot;token keyword&quot;&gt;PRIMARY&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;KEY&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;`&lt;/span&gt;id&lt;span class=&quot;token punctuation&quot;&gt;`&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;</code></pre>
<p>Ahora crearemos un modelo llamado Categorias.</p>
<p>Archivo: <em>models/categorias.php</em></p>
<pre class="  language-php"><code class="  language-php">
&lt;span class=&quot;token delimiter&quot;&gt;&lt;?php&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;Categorias&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ActiveRecord&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;</code></pre>
<p>Y finalmente <strong>(sí, finalmente)</strong> añadiremos el controlador CategoriasController.</p>
<p>Archivo: <em>controllers/categoria_controller.php</em></p>
<pre class="  language-php"><code class="  language-php">
&lt;span class=&quot;token delimiter&quot;&gt;&lt;?php&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CategoriasController&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ScaffoldController&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
 &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$model&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#039;Categorias&#039;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;</code></pre>
<p><span id="more-1288"></span></p>
<h2>¡Y hemos terminado!</h2>
<p>Así de sencillo ya tenemos nuestro primer CRUD sin dolor.</p>
<p><a href="https://www.kumbiaphp.com/blog/wp-content/uploads/2017/03/VirtualBox_ubuntu_31_03_2017_11_05_35.png"><img loading="lazy" decoding="async" class="alignnone wp-image-1322 size-full" src="https://www.kumbiaphp.com/blog/wp-content/uploads/2017/03/VirtualBox_ubuntu_31_03_2017_11_05_35.png" alt="" width="877" height="571" srcset="https://kumbiaphp.com/blog/wp-content/uploads/2017/03/VirtualBox_ubuntu_31_03_2017_11_05_35.png 877w, https://kumbiaphp.com/blog/wp-content/uploads/2017/03/VirtualBox_ubuntu_31_03_2017_11_05_35-300x195.png 300w, https://kumbiaphp.com/blog/wp-content/uploads/2017/03/VirtualBox_ubuntu_31_03_2017_11_05_35-768x500.png 768w" sizes="auto, (max-width: 877px) 100vw, 877px" /></a></p>
<p><a href="https://www.kumbiaphp.com/blog/wp-content/uploads/2017/03/VirtualBox_ubuntu_31_03_2017_11_12_14.png"><img loading="lazy" decoding="async" class="alignnone wp-image-1321 size-full" src="https://www.kumbiaphp.com/blog/wp-content/uploads/2017/03/VirtualBox_ubuntu_31_03_2017_11_12_14.png" alt="" width="880" height="583" srcset="https://kumbiaphp.com/blog/wp-content/uploads/2017/03/VirtualBox_ubuntu_31_03_2017_11_12_14.png 880w, https://kumbiaphp.com/blog/wp-content/uploads/2017/03/VirtualBox_ubuntu_31_03_2017_11_12_14-300x199.png 300w, https://kumbiaphp.com/blog/wp-content/uploads/2017/03/VirtualBox_ubuntu_31_03_2017_11_12_14-768x509.png 768w" sizes="auto, (max-width: 880px) 100vw, 880px" /></a></p>
<p>Tendremos inicialmente las acciones para index, agregar, editar, ver y eliminar, y sólo hemos escrito 7 líneas.</p>
<h2>Personalizando las vistas</h2>
<p>Y ahora, ¿quién podrá defendernos de la hoja de estilo predeterminada? ¡Excelente pregunta!</p>
<p>Bueno, los muchachos del core ya tuvieron eso previsto para nosotros. Resulta que puedes crear tus propias vistas para usarlas con tus controladores de Scaffold. Basta copiar el contenido de <em>app/views/_shared/scaffold/kumbia</em> en una nueva versión de vistas para tus controladores.</p>
<p><a href="https://www.kumbiaphp.com/blog/wp-content/uploads/2017/03/skeleton.png"><img loading="lazy" decoding="async" class="alignnone wp-image-1306 size-full" src="https://www.kumbiaphp.com/blog/wp-content/uploads/2017/03/skeleton.png" alt="" width="668" height="235" srcset="https://kumbiaphp.com/blog/wp-content/uploads/2017/03/skeleton.png 668w, https://kumbiaphp.com/blog/wp-content/uploads/2017/03/skeleton-300x106.png 300w" sizes="auto, (max-width: 668px) 100vw, 668px" /></a></p>
<p>Supongamos que nos piden usar <a href="http://getskeleton.com/" target="_blank" rel="noopener noreferrer">skeleton</a>. Por lo tanto ahora tendremos una carpeta llamada <em>app/views/_shared/scaffolds/skeleton</em>, con los mismos tres archivos de vistas: crear, index, ver.</p>
<p>Y ¿cómo le decimos a nuestros controladores que usen nuestro nuevo conjunto de vistas?<br />
<strong>Sencillo:</strong></p>
<pre class="  language-php"><code class="  language-php">
&lt;span class=&quot;token delimiter&quot;&gt;&lt;?php&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;CategoriasController&lt;/span&gt; &lt;span class=&quot;token keyword&quot;&gt;extends&lt;/span&gt; &lt;span class=&quot;token class-name&quot;&gt;ScaffoldController&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
 &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$model&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#039;Categorias&#039;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
 &lt;span class=&quot;token keyword&quot;&gt;public&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$scaffold&lt;/span&gt; &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&#039;skeleton&#039;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;</code></pre>
<h2>El resultado final</h2>
<p>Si miramos el resultado tendremos algo como lo que se ve en las siguientes imágenes:</p>
<p><figure id="attachment_1307" aria-describedby="caption-attachment-1307" style="width: 914px" class="wp-caption alignnone"><a href="https://www.kumbiaphp.com/blog/wp-content/uploads/2017/03/index-sk.png"><img loading="lazy" decoding="async" class="wp-image-1307 size-full" src="https://www.kumbiaphp.com/blog/wp-content/uploads/2017/03/index-sk-e1490969789984.png" alt="Vista usando skeleton" width="914" height="392" srcset="https://kumbiaphp.com/blog/wp-content/uploads/2017/03/index-sk-e1490969789984.png 914w, https://kumbiaphp.com/blog/wp-content/uploads/2017/03/index-sk-e1490969789984-300x129.png 300w, https://kumbiaphp.com/blog/wp-content/uploads/2017/03/index-sk-e1490969789984-768x329.png 768w" sizes="auto, (max-width: 914px) 100vw, 914px" /></a><figcaption id="caption-attachment-1307" class="wp-caption-text">Vista usando skeleton</figcaption></figure></p>
<p><figure id="attachment_1308" aria-describedby="caption-attachment-1308" style="width: 910px" class="wp-caption alignnone"><a href="https://www.kumbiaphp.com/blog/wp-content/uploads/2017/03/editar-1.png"><img loading="lazy" decoding="async" class="wp-image-1308 size-full" src="https://www.kumbiaphp.com/blog/wp-content/uploads/2017/03/editar-1-e1490970004190.png" alt="Formulario usando skeleton" width="910" height="336" srcset="https://kumbiaphp.com/blog/wp-content/uploads/2017/03/editar-1-e1490970004190.png 910w, https://kumbiaphp.com/blog/wp-content/uploads/2017/03/editar-1-e1490970004190-300x111.png 300w, https://kumbiaphp.com/blog/wp-content/uploads/2017/03/editar-1-e1490970004190-768x284.png 768w" sizes="auto, (max-width: 910px) 100vw, 910px" /></a><figcaption id="caption-attachment-1308" class="wp-caption-text">Formulario usando skeleton</figcaption></figure></p>
<p>Así de fácil logramos crear nuestro primer CRUD con 8 líneas de código y con nuestro css preferido (o requerido).</p>
<p>Si quieres ver lo que sigue, mira en los enlaces que están a continuación:</p>
<p><strong>Parte 2:</strong> <a href="https://www.kumbiaphp.com/blog/2017/04/12/scaffolding-con-kumbiaphp-modificando-comportamientos-y-contenidos-segun-nuestra-necesidad/">ScaffoldController: Modificando comportamientos y contenidos</a></p>
<p><strong>Parte 3:</strong>  <a href="https://www.kumbiaphp.com/blog/2017/05/16/scaffoldcontroller-modificando-vistas/">ScaffoldController: Modificando vistas</a></p>
<h2>Descarga el ejemplo completo</h2>
<p>Pueden descargar el código del proyecto desde el siguiente repositorio de <a href="https://github.com/nelsonrojas/Scaffold-KumbiaPHP" target="_blank" rel="noopener noreferrer">Github</a></p>
<p>Si buscan el script de la tabla de categorías pueden encontrarlo dentro de <em><a href="https://github.com/nelsonrojas/Scaffold-KumbiaPHP/tree/master/default/app/config/sql" target="_blank" rel="noopener noreferrer">app/config/sql</a></em></p>
<p><strong>¡Larga vida a KumbiaPHP!</strong></p>
<p>La entrada <a href="https://kumbiaphp.com/blog/2017/04/03/scaffolding-para-crud-abm-sencillos-y-no-tanto-primera-parte/">Scaffolding para CRUD (ABM) sencillos (y no tanto) &#8211; primera parte</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/2017/04/03/scaffolding-para-crud-abm-sencillos-y-no-tanto-primera-parte/feed/</wfw:commentRss>
			<slash:comments>5</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">1288</post-id>	</item>
	</channel>
</rss>
