#+TITLE: Duckbrain - Manual de inicio #+AUTHOR: KJ #+OPTIONS: #+SETUPFILE: ./readtheorg_inline.theme * Introducción [[https://git.kj2.me/kj/duckbrain][Duckbrain]] es un conjunto de librerías creadas especialmente pensando en hacer algo simple, que cualquiera pueda deshacer y rearmar fácilmente. Gracias a esa versatilidad, puedes usarlo cualquier proyecto, peo por ello debes tener en cuenta que mientras más grande sea el proyecto, mayor será el nivel de ingeniería que se requerirá de tu parte para acondicionar esta herramienta a los requerimientos. Otro punto fuerte que puedo dar de esta herramienta, es que te puede ser tremendamente útil si estás comenzando, ya que al ser tan pequeño y modificable, es más sencillo que lo comprendas y esto más adelante te ayudará a comprender cosas más grandes. Ducho eso, vamos a comenzar... ** Estructura de archivos de Duckbrain Al entrar a la carpeta de Duckbrain encontraras esta estructura de archivos (ignoramos el readme.org porque no es necesario). #+begin_src ditaa . ├── config.php ├── index.php ├── .htaccess └── src ├── Controllers ├── Libs │ ├── Database.php │ ├── Middleware.php │ ├── Model.php │ ├── Neuron.php │ ├── Request.php │ ├── Router.php │ └── View.php ├── Middlewares ├── Models ├── Routers └── Views #+end_src Primero veamos las carpetas y luego los archivos: *** Carpeta src En esta carpeta se encuentra todo el código PHP. Como todo en [[https://git.kj2.me/kj/duckbrain][Duckbrain]], esta ruta se puede cambiar editando una variable en el archivo =index.php=. *** Carpetas: Controllers, Libs, Models, Middlewares, Views y Routers Si sabes de estructuras de diseño, el nombre de estas carpetas ya te debe quedar claro qué va en cada una de ellas, puesto que en el nombre de la carpeta dice lo que va a ir dentro. Si no sabes que es un Model, un Middleware, Controller, etc. entonces requieres buscar ahora mismo lo que es una arquitectura de diseño de software y leerte al menos en qué consiste la arquitectura de MVC, ya que es una arquitectura simple y la que usaremos más adelante en este manual. Al igual que con la carpeta =src=, todo lo puedes cambiar y colocar otra estructura de carpetas y las únicas que requerirían algún tipo de edición de archivos serían las carpetas =Views= y =Router= que se editarían en el archivo =src/Libs/View.php= y el archivo =index.php= respectivamente. Las demás carpetas las puedes borrar cuando quieras y usar otra estructura, pero por lo pronto no lo hagas al menos hasta que hayas pasado la sección [[Mi primera aplicación]] que es cuando ya habrías leído y, con algo de suerte y pericia, asimilado los conocimientos necesarios para hacer lo que te de la gana con este ser de librería al punto de que ya le podrás colocar las tuyas propias, le borrarás alguna de las que viene por defecto porque no la necesites o incluso crees una versión extendida de las que viene por defecto para poder añadirle alguna mejora que necesites. Desde luego, si eres un ansias y sabes lo que son las arquitecturas de diseño, ya has programado en alguna arquitectura de diseño como DDD, MVC, TDD, EDD, etc. antes y sabes PHP, con que te leas el código del archivo =index.php= (son solo 20 líneas de código) y tengas el nivel de PHP para entenderlo y programar en la arquitectura de diseño que desees, entonces con ver esas 20 líneas te deberá bastar y puedes saltarte el resto del este manual y guiarte de ahora en adelante con la documentación API de las librerías o directamente con el LSP de tu editor de código para poco que queda. Para el resto de mortales y gente con menos arrogancia, pueden seguir un ratito más por aquí :P. *** Los archivos en la raíz El =.htaccess= es un archivo que te será útil si usas apache o algún otro servidor web que use estos archivos y lo que lleva es una configuración especial para que funcionen las *rutas virtuales*, o sea, para que podamos crear una ruta tipo =mitsitio.com/mi-ruta-virtual/= y podamos decir que allí muestre un mensaje de ~Hola mundo~, a pesar de que la carpeta =mi-ruta-virtual= no exista, ni haya dentro ningún archivo index que tenga el texto ~Hola mundo~. Si esta aún no lo entendiste, no exasperes que ya lo vas a entender en un momento y ahí podrás volver a repasar esta parte. En caso de que uses nginx, debes configurar el webserver con la regla equivalente al contenido del archivo =.htacess= que sería más o menos esto: #+begin_src nginx location / { try_files $uri $uri/ ./index.php$args; } #+end_src El archivo =index.php= es el punto de entrada de nuestra aplicación, aquí sucederá toda la magia inicial y sólo requiere de 20 míseras lineas para hacer ese gran trabajo y soportar sistemas tan grandes sin despeinarse ante frameworks más complejos como laravel o que son usados por cientos de miles de usuarios en cientos de instalaciones. Esto lo menciono no por creer que ttps://git.kj2.me/kj/duckbrain][Duckbrain podría soportarlo, sino porque es algo que ya sucede, o sea, dichos sistemas ya existen: Los he hecho yo o he estado involucrado en parte del proyecto al punto de poder elegir [https://git.kj2.me/kj/duckbrain][Duckbrain]] como base para el mismo. El archivo =config.php=, como su nombre indica, es el archivo para colocar las configuraciones. *** Los archivos en la carpeta Libs Son básicamente librerías, cada una tiene como nombre lo que hace, no tiene mucho misterio y al igual que antes con las carpetas, si sabes algo de diseño, con leer el nombre de las mismas te debería bastar para saber lo que hacen. Si no lo entiendes, sigue leyendo el manual que hablaremos de casi todas poco a poco. ** Comprendiendo el arranque del sistema Como la intención de este manual es que comprendas [[https://git.kj2.me/kj/duckbrain][Duckbrain]] y no solo seas un robot que copia y pega de la documentación, vamos a calentar comprendiendo el código que lo arranca. Como ya mencionamos antes, el archivo =.htaccess= se encarga de hacer funcionar las rutas virtuales, pero eso como programador que eres te debería hacer saltar una pregunta "¿Cómo es que hace eso?" y la respuesta es simple y puede que ya lo entiendas gracias al código de configuración de nginx que coloqué antes: Supongamos que entramos en la ruta =/hola= (o sea, =misitio.com/hola=), lo que hará el =.htacess= o la configuración nginx será lo siguiente: Primero intenta comprobar si el fichero "hola" existe en la ruta a la que se desea acceder, si no es el caso prueba si existe una carpeta "hola" y si tampoco sucede eso, reenvía todo a =index.php= y le pide que él se encargue de ahí en adelante. Si llega hasta la tercera opción decimos que es una *ruta virtual* (lo que mencionamos en [[Los archivos en la raíz][Los archivos en la raiz]]), porque devolveremos algo desde el PHP simulando un archivo o una carpeta, a pesar de que esa ruta realmente no existe ni como fichero ni como carpeta. Ahora veamos que hace =index.php=, en la primera línea nos dice esto: #+begin_src php require_once('config.php'); #+end_src Aquí carga el archivo =config.php=, o sea, carga la configuración. Para esta parte del manual, solo nos interesa la última línea ya que todo lo demás en realidad no está configurando nada aún. Lo que dice la línea es esto: #+begin_src php define('ROOT_DIR', __DIR__); #+end_src Solo está definiendo una constante =ROOT_DIR= que contiene como valor el directorio en donde está el archivo =config.php=, que también sería la raíz de [[https://git.kj2.me/kj/duckbrain][Duckbrain]]. La siguiente línea también es la definición de una constante: #+begin_src php define('ROOT_CORE', ROOT_DIR.'/src'); #+end_src Esta constante =ROOT_CORE= lo que hace es tener la ruta de src. Hasta aquí acabamos con la definición de constantes, ahora el bloque que viene es donde se poner lo bueno: #+begin_src php spl_autoload_register(function ($className) { $fp = str_replace('\\','/',$className); $name = basename($fp); $dir = dirname($fp); $file = ROOT_CORE.'/'.$dir.'/'.$name.'.php'; if (file_exists($file)) { require_once $file; return; } }); #+end_src Este bloque define un autoloader para PHP. Como su nombre lo indica, lo que hace es cargar los archivos en función del su clase, considerando siempre que dichos archivos estarán dentro de la carpeta configurada en =ROOT_CORE=, que generalmente será =src=. Si aún no te ha hecho clic lo bonito que es tener un autoloader como este, básicamente lo que sucede es que en lugar de que a cada archivo que uses lo tengas que cargar usando la función =include()=, =require()=, =include_once()= o =require_once()=, bastará solo con usar la clase que contiene, siguiendo la convención de que el =namespace= indica las carpetas y el nombre del archivo tiene el mismo nombre de la clase. Si aún no lo entendiste, no pierdas tiempo releyendo el párrafo anterior, en seguida lo vamos a retomar y a explicar mejor. Por lo pronto vamos a por el bloque final: #+begin_src php $routers = glob(ROOT_CORE.'/Routers/*.php'); foreach($routers as $file){ require_once($file); } \Libs\Router::apply(); #+end_src La primera línea de código lista todos los archivos =.php= dentro de nuestra carpeta =src/Routers/=, la segunda parte los incluye todos esos archivos PHP, o sea, ejecuta el código PHP que tengan dentro y la última llama a la clase =\Lib\Router::apply()= y aquí hacemos uso del bloque anterior de la siguiente manera: Hasta ahora, el único archivo que hemos cargado es el de configuración en la primera línea. La clase =\Libs\Router= realmente no está definida y en un PHP normal nos daría error por ello, pero aquí viene al rescate nuestro autoloader, ya que el toma la clase y como se llama =\Lib\Router= comprende que tiene que intentar cargar el archivo en =src/Libs/Router.php= que es donde vendría a estar la clase que estamos necesitando. Como el archivo existe y la clase está definida allí, es capaz de cargarla y de correr la función estática =apply()= y así es como todos terminan felices sin dar ningún error :). Nótese que lo que ha hecho el autoloader es convertir los backslashes o barras invertidas en slashes o barrar normales y luego concatenarlas con =ROOT_CORE= para obtener la ruta de nuestro archivo. Esto es muy importante, así que si no lo entiendes léelo nuevamente (explicación y código) o pide a algún amigo, conocido o random de internet en algún foro o chat de telegram, matrix, steam, discord, reddit, etc. que te lo explique hasta que comprendas perfectamente ese fracmento de código. ** Extra: Namespaces Si eres nuevo en esto puede que no sepas lo que es un namespace, pero si también te dio curiosidad el que la una clase tenga =\= (backslash) en su nombre, entonces tienes futuro en este campo y como no quiero que te vayas de este manual, voy a explicarte rápidamente de donde viene ese backslash. Si abres el archivo =src/Libs/Router.php= verás que en su primera línea dice esto: #+begin_src php namespace Libs; #+end_src Esa línea generalmente será la primera siempre de un archivo PHP que use namespaces, no puede haber ninguna otra línea de código. Lo que hace dicha línea es darle una "familia" a la clase y con dicha familia, también viene el apellido de la misma. De modo que cualquier clase que se cree dentro de un archivo con un namespace, de ahora en adelante tendrá como "apellido" ese namespace en su nombre. De ese modo, como en el archivo Router declaramos la clase =Router=, en realidad estamos creando la clase =Libs\Router= (el backslash del inicio se puede omitir). Puede que ahora mismo no notes la utilidad de esto, pero es algo muy útil realmente y ya verás más adelante la magia que supone. * Primeros pasos Antes de ponernos a programar vamos a asegurarnos de estar en la misma pagina preparando nuestro entorno de trabajo y haciendo el usual Hola mundo. ** Usando un Webserver para el desarrollo Desde luego esta la carpeta con [[https://git.kj2.me/kj/duckbrain][Duckbrain]] supongo que ya la tienes con un webserver nginx o apache en localhost. Si no es el caso, al menos deberás instalarte PHP primero y una ves instalado, abres una terminal en la carpeta donde tienes Duckbrain y ejecutas: #+begin_src bash php -S localhost:80 #+end_src Eso te creará un webserver que podrás acceder escribiendo en el navegador =http://localhost= y verás lo que estemos corriendo en el proyecto. En la terminal, ahora verás los logs de acceso y en caso de que tu código tenga un error, igual aparecerá allí. En el caso de Linux, MAC y FreeBSD los accesos se verán en amarillo para errores no fatales como archivos inexistente y en rojo si es un error fatal que detiene la ejecución de PHP. En Windows no estoy seguro. He conocido gente que usa directamente un hosting y edita los archivos allí. Eso no está mal si estás aprendiendo o para hacer código rápido, pero en lo personal, siempre recomiendo desarrollar en local, ya que es más rápido y con herramientas como Docker o KVM puedes simular la misma configuración que tendría un servidor en producción, con los retoques que necesites para tu entorno de desarrollo. ** Hola mundo Agarren su teclado y su editor de código que vamos a comenzar a hacer la magia. Como es usual, el primer paso para hacer nuetra aplicación, será imprimir un ~hello world~. Para ello vamos a la carpeta =src/Routers= y crearemos un archivo con el nombre de =main.php= y dentro colocaremos el siguiente código: #+begin_src php #+end_src La primera línea define el tipo de base de datos que vamos a usar, mientras que el resto su información. Ya que estamos, voy a configurar también SITE_URL que en realida no es necesario, pero quiero hacerlo para dar a notar que en caso de configurarlo, es obligatorio que la url en termine en =/=. El código terminaría así: #+begin_src php #+end_src Como nuestra base de dato es solo un archivo sqlite, no requerimos de =DB_HOST=, =DB_USER= ni =DB_PASS=. Todas esas líneas podemos eliminarlas o dejarlas tal cual, pues no afectarán en nada. ** Modelos Debo hacer incapié en que nada está escrito en piedra y podemos hacer las cosas de muchas manera con [[https://git.kj2.me/kj/duckbrain][Duckbrain]], pero en este caso, siguiendo la estructura MVC, vamos a crear modelos, vistas y controladores. Comenzando con los modelos, que en realidad para este proyecto sería en singular, vamos a crear un archivo llamado =Note.php= en =src/Models= con el siguiente contenido: #+begin_src php