KnpTimeBundle: Instala el bundle, obtén su servicio
En nuestro sitio, los clientes disponen de una práctica "Cola de Reparación de Barcos" que enumera todos los barcos que están siendo reparados y su estado. Para este tutorial, hemos añadido un nuevo campo $arrivedAta nuestra clase Starship con algunos getters y setters. Queremos imprimir este campo en la página de inicio.
| // ... lines 1 - 4 | |
| class Starship | |
| { | |
| public function __construct( | |
| // ... lines 8 - 12 | |
| private \DateTimeImmutable $arrivedAt, | |
| ) { | |
| } | |
| // ... lines 16 - 55 | |
| public function getArrivedAt(): \DateTimeImmutable | |
| { | |
| return $this->arrivedAt; | |
| } | |
| } |
Si has olvidado qué controlador es responsable de la página de inicio, siempre puedes pasar el ratón por encima de la información de la página en la barra de herramientas de depuración web y... ¡boom! Dice "MainController :: homepage". Abramos eso - MainController.php - y busquemos la acción homepage(). Aquí abajo, podemos ver que genera una plantilla: main/homepage.html.twig. Ábrela, busca la "Ship Repair Queue" y, aquí abajo, después de {{ ship.name }}, añade una nueva <div> con Arrived at: {{ ship.arrivedAt }}.
| // ... lines 1 - 4 | |
| {% block body %} | |
| // ... lines 6 - 14 | |
| {% for ship in ships %} | |
| // ... lines 16 - 18 | |
| <div class="ml-5"> | |
| // ... lines 20 - 29 | |
| <div> | |
| Arrived at: {{ ship.arrivedAt }} | |
| </div> | |
| </div> | |
| // ... lines 34 - 46 | |
| {% endfor %} | |
| // ... lines 48 - 55 | |
| {% endblock %} |
Ahora, si volvemos al navegador y actualizamos la página de inicio... ah... un error.
Se ha lanzado una excepción durante la renderización de una plantilla ("Objeto de clase
DateTimeImmutableno se ha podido convertir en cadena").
Eso tiene sentido. PHP no puede imprimir simplemente objetos DateTime porque no sabe qué formato queremos. ¿Cómo lo arreglamos? Muy fácil Podemos utilizar un filtro Twig. Aquí detrás, después de arrivedAt, digamos |date. Si refrescamos de nuevo... ¡genial! Aquí tenemos la fecha y la hora en un formato específico.
| // ... lines 1 - 18 | |
| <div class="ml-5"> | |
| // ... lines 20 - 29 | |
| <div> | |
| Arrived at: {{ ship.arrivedAt|date }} | |
| </div> | |
| </div> | |
| // ... lines 34 - 57 |
Podemos pasar un formato DateTime opcional como primer argumento a este filtro |date, pero si lo omitimos, se utilizará el formato por defecto de la aplicación. ¿Cuál exactamente? ¡Buena pregunta! Comprobemos la configuración. En tu terminal, ejecuta:
bin/console config:dump twig
Aquí puedes ver la configuración del formato de fecha de tu aplicación. En realidad, he hecho un poco de trampa al ejecutar este comando. El nombre completo del comando es config:dump-reference. Con los comandos Symfony, puedes acortar el nombre todo lo que quieras siempre que no sea ambiguo con el nombre de otro comando. Si coinciden varios comandos, la consola te preguntará cuál quieres ejecutar.
Bien, volvamos al navegador. Hemos impreso nuestra fecha, pero sería mucho más guay si pudiéramos decir algo como "hace 2 horas" en lugar de esta fecha tan larga. Por desgracia, aún no tenemos un servicio en nuestra aplicación que pueda hacer eso por nosotros. Y desde luego no quiero escribirlo yo. Tengo cosas más divertidas que hacer, como jugar a juegos de mesa. Pero... ¿Existe un bundle con un servicio que pueda hacerlo? Sí Se llama "KnpTimeBundle". Busquémoslo en GitHub. Aquí lo tienes Desplázate hasta la sección "Instalación" y copia este comando. En tu terminal, pega ese comando y ejecútalo:
composer require knplabs/knp-time-bundle
Esto instala el bundle, las dependencias necesarias y también ejecuta algunas recetas. Si lo ejecutamos:
git status
¡Compruébalo! Cada vez que instalamos un nuevo bundle, cambia nuestros archivos composer.json,composer.lock, symfony.lock, y bundles.php. Abrámoslo.
| // ... lines 1 - 2 | |
| return [ | |
| // ... lines 4 - 13 | |
| Knp\Bundle\TimeBundle\KnpTimeBundle::class => ['all' => true], | |
| ]; |
Aquí abajo, podemos ver que se ha añadido KnpTimeBundle a esta matriz. Ahí es donde Symfony activa este bundle en nuestra aplicación. Recuerda, los bundles nos dan servicios, y éste no es una excepción. Pero... ¿qué servicios nos da? Podríamos leer la documentación para saber más sobre esto, pero yo voy a ser perezoso y voy a ejecutar:
bin/console debug:container time
Seleccionaré datetime_formatter, que es la opción 10, para obtener más información. ¡Genial!
Para ver si podemos autocablearlo, ejecutemos otro comando:
bin/console debug:autowiring time
Y... ¡podemos! Si queremos utilizar el formato ago para nuestro objeto de fecha, éste es el typehint que tenemos que utilizar para inyectar este servicio en nuestras clases PHP. Pero, como sólo queremos esto en nuestra plantilla Twig, hay una solución mejor. Este bundle también viene con una integración Twig que proporciona algunos bonitos filtros y funciones Twig. Podemos verlo si ejecutamos
bin/console debug:twig
y buscamos ago. ¡Aquí está! Si este date te resulta familiar, es porque lo es. Es el que hemos utilizado antes. Probemos esta vez con el filtro ago.
| // ... lines 1 - 18 | |
| <div class="ml-5"> | |
| // ... lines 20 - 29 | |
| <div> | |
| Arrived at: {{ ship.arrivedAt|ago }} | |
| </div> | |
| </div> | |
| // ... lines 34 - 57 |
Vuelve aquí, sustituye date por ago... guarda, y abre el navegador. Actualiza la página de inicio y... ¡ahí está! Ahora tenemos este bonito formato "hace". Así, los bundles nos dan servicios, los servicios son herramientas y las herramientas son divertidas.
A continuación, vamos a añadir aún más servicios instalando nuevos componentes Symfony.
14 Comments
Hi. You forget to comment that you have to add a sixth parameter in Repository with the DateTimeImmutable. Something like this:
Hey Javier!
Thanks for the head ups and sorry for the long reply! I just double-checked the course project code you can download from this page, and I do see in both start/ and finish/ directories "new \DateTimeImmutable('...')" lines as 6th arg. It might be so that you downloaded the course code earlier that the final current version, i.e. something was tweaked in the code, so your downloaded version is a little bit incomplete. But no problem, just add those 6th args there, you can re-download the course code again and steal that part from it.
Cheers!
Hi)
I think Javier, like me, just followed the course from the first part without downloading the project.
Maybe you should add some kind of hint to the video so that people don't go to the comments section)
Hey Kostiantyn,
It's still not clear to me, could you add more context please? Are you talking about a missing code block? Could you link to a specific time in this video where do that but do not show it? Or what?
Cheers!
Ммм, та в цілому проблеми немає)
Просто якщо слідувати крок за кроком першою частиною і вручну робити все те, що робить викладач (а не використовувати готовий код проекту), то виходить, що наприкінці першої частини в
StarshipRepository.phpвідсутня дата (там деnew Starship(...)), а в другій частині дата вже додана в цьому файлі, але в відео про це не згадано (лише сказано, що було додано нове поле$arrivedAtв модельStarship:)Тому якщо слідувати курсом вручну, треба ще додати ще
new \DateTimeImmutable('-1 day')і т.д. у цей файл)Ага, тепер зрозумів, дякую :)
Тобто ви почали проходити цей курс на коді проєкту попереднього, тобто продовжуючи https://symfonycasts.com/screencast/symfony . Так, це відома проблема. Ми рекомендуємо скачувати новий код проєкту для кожного нового курсу, навіть якщо він є продовженням. Це насамперед тому що перед кожним новим курсом ми робимо деякі зміни, а саме оновлюємо залежності до останніх версій та трохи змінюємо основний код проєкта так щоб зробити його максимально гладким для проходження з точки зору нового курса а не продовження старого. Якби ми не змінювали код для кожного нового курсу - користувачам доводилось би робити набагато більше змін в коді в нових курсах що заплутувало б користувачів.
Тобто якщо простими словами то ми змінюємо код попередніх проєктів саму тому щоб мати кращі приклади тих тем які ми хочемо показати в курсі і при цьому вимагати менше сторонніх дій від користувачів.
Тож наша офіційна рекомендація для того щоб уникати таких моментів - скачувати новий курс проєкту кожного разу для нового курсу. Або ж мати на увазі що якщо ви продовжуєте попередній курс - в новому коді проєкту точно будуть зроблені деякі зміни. Сподіваюсь це допоможе краще розуміти нашу стратегію :)
Cheers!
Hi Kevin, I thought you might struggle a bit on your first tutorial... But... It's like you've been doing it for years already. I'm going to miss Ryan as the first one who made me truly understand Symfony and all it's magic but I think you're an amazing addition to the team. I'll be more than happy to tune in everytime you publish a new lecture/course!
Thank you so much for the kind words @Julian-K!
While we still miss Rayn, congratulations on doing a great job, and a warm welcome to our new tutor! Thank you all for your efforts in maintaining the same level of professionalism and talent that Rayn provided.
Thank you @Lubna! ❤️
Hi guys! Thank you for the tutorials! I had the impression that single page apps were exercises in scrolling. Boy was I wrong! Love the smaller footprint of Symphony! Great job, guys, you are brilliant to get where you are. I know, I have been trying.
I am going to go do the Laracasts, too, when I am done with everything I can get here. I need a job!
Love you guys, thank you!
Hey David,
Thank you for your feedback about SymfonyCasts courses! And stay tuned for more cool content upcoming, the next Symfony course will be about Symfony Doctrine Relations: https://symfonycasts.com/screencast/symfony7-doctrine-relations
Cheers!
While I also miss Ryan (sooo much) I have to confess I also kinda like your style Kevin ;)
I encountered some glitches that (hopefully) are my faults...
startdirectory so i grabbed the one fromfinishto follow the video.Apart from this: well done so far ;)
Hey @elkuku ,
Whops, my bad, thanks!
I added the missing
php bin/console tailwind:buildcommand to the README file - indeed it's needed to run the project for the first time, or you will hit. an exception saying running that command :)Also, you're right, the code from the start/ directory was missing some changes, I fixed that too. But good workaround to steal that code from the finish/ folder.. or usually it's should be possible to grab it from the code blocks in scripts below the video.
Cheers!
"Houston: no signs of life"
Start the conversation!