Nuevo Bundle, nuevo servicio: KnpTimeBundle
En nuestro sitio, puedes crear tu propia mezcla de vinilo. (O podrás hacerlo con el tiempo... ahora mismo, este botón no hace nada). Pero otra gran característica de nuestro sitio es la posibilidad de explorar las mezclas de otros usuarios.
Ahora que lo estoy viendo, podría ser útil si pudiéramos ver cuándo se creó cada mezcla.
Si no recuerdas en qué parte de nuestro código se creó esta página, puedes utilizar un truco. Abajo, en la barra de herramientas de depuración de la web, pasa el ratón por encima del código de estado 200. Ah, ¡ja! Esto nos muestra que el controlador detrás de esta página es VinylController::browse.
¡Genial! Ve a abrir src/Controller/VinylController.php. Aquí está la acción browse:
| // ... lines 1 - 9 | |
| class VinylController extends AbstractController | |
| { | |
| // ... lines 12 - 29 | |
| ('/browse/{slug}', name: 'app_browse') | |
| public function browse(string $slug = null): Response | |
| { | |
| $genre = $slug ? u(str_replace('-', ' ', $slug))->title(true) : null; | |
| $mixes = $this->getMixes(); | |
| return $this->render('vinyl/browse.html.twig', [ | |
| 'genre' => $genre, | |
| 'mixes' => $mixes, | |
| ]); | |
| } | |
| // ... lines 41 - 65 | |
| } |
Por cierto, he actualizado un poco el código desde el primer episodio... así que asegúrate de tener una copia fresca si estás codificando conmigo.
Este método llama a $this->getMixes()... que es una función privada que he creado en la parte inferior:
| // ... lines 1 - 9 | |
| class VinylController extends AbstractController | |
| { | |
| // ... lines 12 - 41 | |
| private function getMixes(): array | |
| { | |
| // temporary fake "mixes" data | |
| return [ | |
| [ | |
| 'title' => 'PB & Jams', | |
| 'trackCount' => 14, | |
| 'genre' => 'Rock', | |
| 'createdAt' => new \DateTime('2021-10-02'), | |
| ], | |
| [ | |
| 'title' => 'Put a Hex on your Ex', | |
| 'trackCount' => 8, | |
| 'genre' => 'Heavy Metal', | |
| 'createdAt' => new \DateTime('2022-04-28'), | |
| ], | |
| [ | |
| 'title' => 'Spice Grills - Summer Tunes', | |
| 'trackCount' => 10, | |
| 'genre' => 'Pop', | |
| 'createdAt' => new \DateTime('2019-06-20'), | |
| ], | |
| ]; | |
| } | |
| } |
Esto devuelve una gran matriz de datos falsos que representa las mezclas que vamos a representar en la página. Eventualmente, obtendremos esto de una fuente dinámica, como una base de datos.
Impresión de fechas en Twig
Observa que cada mezcla tiene un campo de fecha createdAt. Obtenemos estas mezclas en browse()... y las pasamos como una variable mixes a vinyl/browse.html.twig. Vamos a saltar a esa plantilla.
Aquí abajo, utilizamos el bucle for de Twig para recorrer mixes. ¡Es muy sencillo!
| // ... lines 1 - 3 | |
| <div class="container"> | |
| // ... lines 5 - 25 | |
| <div> | |
| <h2 class="mt-5">Mixes</h2> | |
| <div class="row"> | |
| {% for mix in mixes %} | |
| <div class="col col-md-4"> | |
| <div class="mixed-vinyl-container p-3 text-center"> | |
| <img src="https://via.placeholder.com/300" data-src="https://via.placeholder.com/300" alt="Square placeholder img"> | |
| <p class="mt-2"><strong>{{ mix.title }}</strong></p> | |
| <span>{{ mix.trackCount }} Tracks</span> | |
| | | |
| <span>{{ mix.genre }}</span> | |
| </div> | |
| </div> | |
| {% endfor %} | |
| </div> | |
| </div> | |
| </div> | |
| // ... lines 43 - 44 |
Ahora imprimamos también la fecha "creada en". Añade un |, otro <span> y luego digamos {{ mix.createdAt }}.
Sólo hay un problema. Si miras createdAt... es un objeto DateTime. Y no puedes imprimir simplemente objetos DateTime... obtendrás un gran error que te recordará... que no puedes imprimir simplemente objetos DateTime. ¡Qué mundo más cruel!
Afortunadamente, Twig tiene un práctico filtro date. Ya hablamos brevemente de los filtros en el primer episodio: los utilizamos añadiendo un | después de algún valor y el nombre del filtro. Este filtro en particular también toma un argumento, que es el formato en el que debe imprimirse la fecha. Para simplificar las cosas, vamos a utilizar Y-m-d, o "año-mes-día".
| // ... lines 1 - 3 | |
| <div class="container"> | |
| // ... lines 5 - 25 | |
| <div> | |
| <h2 class="mt-5">Mixes</h2> | |
| <div class="row"> | |
| {% for mix in mixes %} | |
| <div class="col col-md-4"> | |
| <div class="mixed-vinyl-container p-3 text-center"> | |
| // ... lines 32 - 35 | |
| <span>{{ mix.genre }}</span> | |
| | | |
| <span>{{ mix.createdAt|date('Y-m-d') }}</span> | |
| </div> | |
| </div> | |
| {% endfor %} | |
| </div> | |
| </div> | |
| </div> | |
| // ... lines 45 - 46 |
Ve y actualiza y... ¡bien! Ahora podemos ver cuándo se creó cada uno, aunque el formato no es muy atractivo. Podríamos hacer más trabajo para arreglar esto... pero sería mucho más genial si pudiéramos imprimir esto en el formato "hace".
Probablemente lo hayas visto antes.... como en los comentarios de una entrada de blog... dicen algo así como "publicado hace tres meses" o "publicado hace 10 minutos".
Así que... la pregunta es: ¿Cómo podemos convertir un objeto DateTime en ese bonito formato "hace"? Bueno, eso me suena a trabajo y, como he dicho antes, el trabajo en Symfony lo hace un servicio. Así que la verdadera pregunta es: ¿Existe un servicio en Symfony que pueda convertir los objetos DateTime al formato "ago"? La respuesta es... no. Pero hay un bundle de terceros que puede darnos ese servicio.
Instalación de KnpTimeBundle
Ve a https://github.com/KnpLabs/KnpTimeBundle. Si miras la documentación de este bundle, verás que nos proporciona un servicio que puede hacer esa conversión. Así que... ¡vamos a instalarlo!
Desplázate hasta la línea composer require, cópiala, gira a nuestro terminal y pégala.
composer require knplabs/knp-time-bundle
¡Genial! Esto agarró knplabs/knp-time-bundle... así como symfony/translation: el componente de traducción de Symfony, que es una dependencia de KnpTimeBundle. Cerca de la parte inferior, también configuró dos recetas. Veamos qué hacen. Ejecuta:
git status
¡Impresionante! Cada vez que instales un paquete de terceros, Composer siempre modificará tus archivos composer.json y composer.lock. Esto también ha actualizado el archivoconfig/bundles.php:
| return [ | |
| // ... lines 4 - 11 | |
| Knp\Bundle\TimeBundle\KnpTimeBundle::class => ['all' => true], | |
| ]; |
Eso es porque acabamos de instalar un bundle - KnpTimeBundle - y su receta se encargó de ello automáticamente. También parece que la receta de traducción añadió un archivo de configuración y un directorio translations/. El traductor es necesario para utilizar KnpTimeBundle... pero no necesitaremos trabajar con él directamente.
Entonces... ¿qué nos ha aportado la instalación de este nuevo bundle? Servicios, por supuesto ¡Busquemos y utilicemos esos a continuación!
13 Comments
Just want to say: THANK YOU for your great Symfony and Vue tutorials. I've learned such a lot. Much more in one single tutorial than in the last five years of learning-by-doing and self-studying. Your pronouniation is clear and distinct. And your humour is uplifting. Also, all the stuff works, no problems to follow. Downloadable code start/finish rounds it up. Keep on making such tutorials please.
Ah, thank you for the great message! We'll keep going :)
Hello, i have a big problem when i download the code. i do everything right but i have critical vulnerabilities with npm install. If i try to run the symfony server, i just have a page entirely of the color of the nav and i can't even right click. With laragon, i have a brocken page with console errors for exemple http://localhost/symfocast/public/_wdt/1f76b0 404 (not found). I tried aswell to run the webite with 8.1 version but it doeasn't change anything.
Hey @AntoineR!
Sorry about the trouble! Let's see if we can figure it out :).
That's probably ok. Well, vulnerabilities are not ok of course. But when you run
npm install, it will install the version of the dependencies when we built this project. And it's not surprising that some of those could have vulnerabilities now. Because this is just a tutorial app, you can ignore those. On a real app, you'll of course want to update your dependencies. But this doesn't hurt anything.Hmm. See the
public/in the URL? Ideally, we'd point the web server directly atpublicso that it is the document root. For example, when I run via the symfony binary, my URL would be something likehttps://127.0.0.1:8000/_wdt/1f76b0- the roothttps://127.0.0.1:8000is pointing at thepublic/directory. You CAN run a Symfony app like this, but it's not standard, and I bet it's the problem. The 404 on this URL tells me that theindex.phpfile inpublic/isn't being seen as the default script and so isn't being executed.Is there a way for you to point the web server setup directly at
public/as the document root?Cheers!
I must have missed something, but how do I pull the new code you refer to in this video?
Hey @Roy!
If you're a subscriber, you can download the course code in the upper right of this page - there's a "Download" button up there where you can get the video, script and course code :). Let me know if you have any trouble.
Cheers!
Hi there,
I completed the previous course and it went well! On downloading a fresh copy of the code for this course and setting it up as per the readme file, the website is up and everthing works, except that the audios do not play and the turbo function is also not working. Any hints as to why this could be ?
Thanks!
Hey @Gitanjali-N
Can you tell me if you get any console errors in your browser? Did you run
yarn watch? I'm guessing this problem could be related to your browser, if you try with a different one, does it work?Also, try hard-refreshing the page
Hi @MolloKhan , thank you so much for your response. Indeed, it worked in another browser-profile window!
Git Versioning
I'm keeping a git version of this course as I code along. One challenge with downloading a fresh copy of the code is that it creates conflicts in my version control. Do you have any thoughts on to address this? If the changes are code specific, I don't think it's too big of a deal as I can just update the specific code changes where they exist. Are there any package changes between the first tutorial and this one-or even subsequent ones?
Thanks
Hey robertocannella,
I'm not sure I understand your problem completely. Do you mean, you have a course code from a different (past) tutorial, and wanted to follow the current course base on the finish code of the previous tutorial? If so, that's not something we recommend. We always recommend users to download a fresh course code for each tutorial to code along with us - this way you will have the exact code as the course author has. The reason behind of this is that we always d some upgrades and minor changes between our courses, so "finish course 1 code" != "start course 2 code", always.
But if you want, of course, you can try to follow the current course base on finish course code from the past tutorial, but be aware of possible changes and conflicts that we may done between courses that you would need to resolve manually. It's up to you :)
Cheers!
can we use Carbon library in a Symfony project ?
Hi,
Of course you can! I don't see any problem with it. It's a cool library!
Cheers!
"Houston: no signs of life"
Start the conversation!