<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: HappyToDev</title>
    <description>The latest articles on DEV Community by HappyToDev (@happytodev).</description>
    <link>https://dev.to/happytodev</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F471700%2F56696747-6ee2-47cb-b65d-ba87375678f9.png</url>
      <title>DEV Community: HappyToDev</title>
      <link>https://dev.to/happytodev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/happytodev"/>
    <language>en</language>
    <item>
      <title>🇫🇷 Framework Heroes News : la veille sur les frameworks pour la semaine 2024/40</title>
      <dc:creator>HappyToDev</dc:creator>
      <pubDate>Tue, 08 Oct 2024 16:14:19 +0000</pubDate>
      <link>https://dev.to/happytodev/framework-heroes-news-la-veille-sur-les-frameworks-pour-la-semaine-202440-clf</link>
      <guid>https://dev.to/happytodev/framework-heroes-news-la-veille-sur-les-frameworks-pour-la-semaine-202440-clf</guid>
      <description>&lt;h2&gt;
  
  
  Edito
&lt;/h2&gt;

&lt;p&gt;Et voici, votre condensé de la veille sur les frameworks de la semaine 40, du 30 septembre au 06 octobre 2024.&lt;/p&gt;

&lt;p&gt;Pour cette première semaine d'octobre, les contributeurs de Framework Heroes n'ont pas chômé.&lt;/p&gt;

&lt;h2&gt;
  
  
  Catégorie Games
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Godot XR Update - October 2024
&lt;/h3&gt;

&lt;p&gt;Cet article détaille les avancées dans le support XR de Godot, incluant des améliorations en suivi de mouvement, pass-through, et la collaboration avec Meta pour optimiser l'expérience sur les appareils Quest.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://godotengine.org/article/godot-xr-update-oct-2024/" rel="noopener noreferrer"&gt;Lire l'article&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Catégorie web
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Security Tip : Auto-secure Cookies FTW
&lt;/h3&gt;

&lt;p&gt;Où on y découvre que Laravel a mis à jour le comportement des cookies pour qu'ils soient automatiquement sécurisés en correspondant au protocole de la requête (HTTP/HTTPS).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://securinglaravel.com/security-tip-auto-secure-cookies-ftw/" rel="noopener noreferrer"&gt;Lire l'article&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  A Guide to Laravel Pipelines | Ash Allen Design
&lt;/h3&gt;

&lt;p&gt;où l'on apprends comment utiliser la classe Pipeline de Laravel pour décomposer des flux de travail complexes en processus isolés et ciblés, facilitant ainsi la gestion et le test des pipelines dans les applications Laravel.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://ashallendesign.co.uk/blog/laravel-pipeline" rel="noopener noreferrer"&gt;Lire l'article&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  LangCountry launches v4
&lt;/h3&gt;

&lt;p&gt;La version 4 de Laravel LangCountry introduit des macros Carbon pour une mise en forme directe des dates selon les spécifications linguistiques et géographiques.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://laravel-news.com/langcountry-launches-v4" rel="noopener noreferrer"&gt;Lire l'article&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Laravel Roundup - October
&lt;/h3&gt;

&lt;p&gt;Le "Laravel Roundup" d'octobre couvre les dernières nouvelles et mises à jour dans la communauté Laravel, incluant des outils, des packages récemment publiés, et des événements comme des meetups.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://laravel-news.com/laravel-roundup-october" rel="noopener noreferrer"&gt;Lire l'article&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Lunar - Headless E-Commerce for Laravel
&lt;/h3&gt;

&lt;p&gt;Lunar est un package open-source pour Laravel qui introduit des fonctionnalités de commerce électronique headless modernes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://lunarphp.io/" rel="noopener noreferrer"&gt;Lire l'article&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Laravel Form Request and Data Validation Tutorial
&lt;/h3&gt;

&lt;p&gt;Cet article explore comment utiliser les Form Requests de Laravel pour gérer la validation des données et l'autorisation dans une application web.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://devdojo.com/inspector/laravel-form-request-and-data-validation-tutorial" rel="noopener noreferrer"&gt;Lire l'article&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Laravel Herd v1.11 Adds Forge Integration, Dump Updates, and More
&lt;/h3&gt;

&lt;p&gt;La version 1.11 de Laravel Herd introduit une intégration avec Laravel Forge, des améliorations pour le débogage, et permet le partage de configurations de projet.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://laravel-news.com/laravel-herd-1-11-0" rel="noopener noreferrer"&gt;Lire l'article&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Security Tip: Stop Using MD5 and SHA-1!
&lt;/h3&gt;

&lt;p&gt;Cet article recommande d'arrêter d'utiliser les algorithmes MD5 et SHA-1 pour des raisons de sécurité, suggérant plutôt l'adoption de solutions plus sécurisées et performantes pour la vérification d'intégrité et la cryptographie.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://securinglaravel.com/security-tip-stop-using-md5-and-sha-1/" rel="noopener noreferrer"&gt;Lire l'article&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  React Best Practices Every Developer Should Know
&lt;/h3&gt;

&lt;p&gt;Cet article présente une compilation des meilleures pratiques pour les développeurs React, visant à améliorer la qualité et la maintenabilité du code.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://www.freecodecamp.org/news/react-best-practices-ever-developer-should-know/" rel="noopener noreferrer"&gt;Lire l'article&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Building a Google Meet Clone with Next.js and Tailwind CSS - Part Two
&lt;/h3&gt;

&lt;p&gt;Cet article explore la deuxième partie de la création d'un clone de Google Meet, en utilisant Next.js pour la structure et Tailwind CSS pour le style, avec l'intégration de fonctionnalités comme le chat et le partage d'écran.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://tropicolx.hashnode.dev/building-a-google-meet-clone-with-nextjs-and-tailwindcss-part-two" rel="noopener noreferrer"&gt;Lire l'article&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Introduction to Laravel Data V3
&lt;/h3&gt;

&lt;p&gt;Cet article introduit la version 3 du package Laravel Data de Spatie, qui simplifie la création et la gestion des objets de données dans Laravel.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://spatie.be/docs/laravel-data/v3/introduction" rel="noopener noreferrer"&gt;Lire l'article&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Serverless Search with Laravel and Typesense
&lt;/h3&gt;

&lt;p&gt;Cet article explore comment intégrer une fonctionnalité de recherche serverless dans une application Laravel en utilisant Typesense pour une recherche rapide et efficace.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://laravel-news.com/serverless-search-laravel-typesense" rel="noopener noreferrer"&gt;Lire l'article&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Laravel Auth Routes Tutorial
&lt;/h3&gt;

&lt;p&gt;Ce tutorial explique comment configurer et utiliser les routes d'authentification fournies par Laravel pour gérer l'inscription, la connexion et la réinitialisation de mot de passe des utilisateurs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://devdojo.com/inspector/laravel-auth-routes-tutorial" rel="noopener noreferrer"&gt;Lire l'article&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Et voilà pour les news de la semaine passée.&lt;/p&gt;

&lt;p&gt;N'oubliez pas que Framework Heroes est fait pour vous et par vous. À ce titre, il a besoin de votre participation. &lt;/p&gt;

&lt;h3&gt;
  
  
  Comment ?
&lt;/h3&gt;

&lt;p&gt;Simplement en venant &lt;a href="https://go.itanea.fr/fhndev2" rel="noopener noreferrer"&gt;partager de temps à autres des news&lt;/a&gt; sur vos frameworks préférés.&lt;/p&gt;

</description>
      <category>godot</category>
      <category>laravel</category>
      <category>security</category>
    </item>
    <item>
      <title>Newsletter "What's up devs ?" is born !</title>
      <dc:creator>HappyToDev</dc:creator>
      <pubDate>Sun, 16 Jun 2024 21:35:38 +0000</pubDate>
      <link>https://dev.to/happytodev/newsletter-whats-up-devs-is-born--pl9</link>
      <guid>https://dev.to/happytodev/newsletter-whats-up-devs-is-born--pl9</guid>
      <description>&lt;p&gt;Hi devs, &lt;/p&gt;

&lt;p&gt;You may know that I publish a weekly French dev newsletter called "&lt;a href="https://happytodev.substack.com"&gt;Quoi de neuf les devs ?&lt;/a&gt;".&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;But today, I'm delighted to announce that its English version is born.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;It's called &lt;strong&gt;"&lt;a href="https://go.itanea.fr/wud1"&gt;What's up devs?&lt;/a&gt;"&lt;/strong&gt; and it's in the same spirit as its French sister: to give you the latest development news every week.&lt;/p&gt;

&lt;p&gt;I'll try to keep the same rhythm as the French version, so I'll publish it every Friday. Occasionally, the newsletter may be published on Saturday, depending on how tired I am ;-)&lt;/p&gt;

&lt;p&gt;So I leave you with this newsletter, which I'm very proud to present to you.&lt;/p&gt;

&lt;p&gt;I hope you enjoy reading it as much as I enjoyed writing it.&lt;/p&gt;

&lt;p&gt;Don't hesitate to give your opinion on the topics and content. I'll be reading your comments very carefully to improve this newsletter.&lt;/p&gt;

&lt;p&gt;In this first issue, we'll be talking about&lt;br&gt;&lt;br&gt;
✅ Go, &lt;br&gt;
✅ PostgreSQL, &lt;br&gt;
✅ CSS, &lt;br&gt;
✅ HTTP/3, &lt;br&gt;
✅ Laravel, &lt;br&gt;
✅ Python, &lt;br&gt;
✅ SQLite&lt;br&gt;
and much more...&lt;/p&gt;

&lt;p&gt;Take care and see you next friday !!&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>newsletter</category>
      <category>developers</category>
    </item>
    <item>
      <title>LinKeeper - Lesson 03 - Tests and ressources</title>
      <dc:creator>HappyToDev</dc:creator>
      <pubDate>Sun, 28 Apr 2024 08:56:38 +0000</pubDate>
      <link>https://dev.to/happytodev/linkeeper-lesson-03-tests-and-ressources-50m6</link>
      <guid>https://dev.to/happytodev/linkeeper-lesson-03-tests-and-ressources-50m6</guid>
      <description>&lt;p&gt;In this episode, we're going to take FilamentPHP a step further.&lt;/p&gt;

&lt;p&gt;But first, we're going to set up our testing environment.&lt;/p&gt;

&lt;p&gt;To do this, we're going to use PestPHP. PestPHP is already present because it was installed at the same time as Laravel.&lt;/p&gt;

&lt;p&gt;To get to grips with Pest, we're going to create two very simple tests. Once we have the basics down, we can develop the rest of our application based on the tests.&lt;/p&gt;

&lt;p&gt;What we'll be looking at today : &lt;/p&gt;



&lt;ul&gt;
&lt;li&gt;
Prior configuration of Pest

&lt;ul&gt;
&lt;li&gt;Using SQLite for testing&lt;/li&gt;
&lt;li&gt;Refresh the database for each test&lt;/li&gt;
&lt;li&gt;Load a default account before each test&lt;/li&gt;
&lt;li&gt;Remove the tests provided by default by PestPHP&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
Checking the administration home page

&lt;ul&gt;
&lt;li&gt;Running the test&lt;/li&gt;
&lt;li&gt;Correct the 403 error&lt;/li&gt;
&lt;li&gt;Run the test again&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
Testing the user profile

&lt;ul&gt;
&lt;li&gt;Run the tests&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
a user can see the list of links associated with them

&lt;ul&gt;
&lt;li&gt;Let's create our tests for the Links page&lt;/li&gt;
&lt;li&gt;Let's create the Links page&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Conclusion &lt;/li&gt;
&lt;/ul&gt;



&lt;h2&gt;
  
  
  Prior configuration of Pest
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Using SQLite for testing
&lt;/h3&gt;

&lt;p&gt;In order to separate your application's database from the one used for testing, we're going to modify the &lt;code&gt;phpunit.xml&lt;/code&gt; file located at the root of your project.&lt;/p&gt;

&lt;p&gt;Simply uncomment the following two lines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;        &lt;span class="c"&gt;&amp;lt;!-- &amp;lt;env name="DB_CONNECTION" value="sqlite"/&amp;gt; --&amp;gt;&lt;/span&gt;
        &lt;span class="c"&gt;&amp;lt;!-- &amp;lt;env name="DB_DATABASE" value=":memory:"/&amp;gt; --&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;        &lt;span class="nt"&gt;&amp;lt;env&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"DB_CONNECTION"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"sqlite"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
        &lt;span class="nt"&gt;&amp;lt;env&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"DB_DATABASE"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;":memory:"&lt;/span&gt;&lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will allow Pest, which is a PHPUnit overlay, to use SQLite as its database engine and use it directly in memory.&lt;/p&gt;

&lt;h3&gt;
  
  
  Refresh the database for each test
&lt;/h3&gt;

&lt;h3&gt;
  
  
  Load a default account before each test
&lt;/h3&gt;

&lt;p&gt;We're going to be doing a lot of work with FilamentPHP administration. So to avoid repeating for each test that we want to connect with a registered user, we'll simply tell Pest that for each test, it will act as if it were connected with the user with id #1. &lt;/p&gt;

&lt;p&gt;To make this user ex&lt;/p&gt;

&lt;p&gt;To do this, we'll edit the &lt;code&gt;tests\TestCase.php&lt;/code&gt; file and add the following &lt;code&gt;setUp&lt;/code&gt; function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;
    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;setUp&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;parent&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;setUp&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

        &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;actingAs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So before each test is run, the &lt;code&gt;actingAs&lt;/code&gt; function will define the user with id #1 as the logged-in user. Here it's my HappyToDev account.&lt;/p&gt;

&lt;h3&gt;
  
  
  Remove the tests provided by default by PestPHP
&lt;/h3&gt;

&lt;p&gt;When you install Pest, it provides you with two default tests: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;tests\Feature\ExampleTest.php&lt;/li&gt;
&lt;li&gt;tests\Unit\ExampleTest.php&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can delete them or keep them for inspiration.&lt;/p&gt;

&lt;h2&gt;
  
  
  Checking the administration home page
&lt;/h2&gt;

&lt;p&gt;In this test, we'll go to the &lt;code&gt;/admin&lt;/code&gt; page to check that&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;an HTTP 200 code is received&lt;/li&gt;
&lt;li&gt;we can see 'Dashboard' on the page&lt;/li&gt;
&lt;li&gt;we can see the name of our application 'LinKeeper' on the page&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;We'll start by creating a test file using Artisan.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan pest:test GeneralAdminPageTest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;By default, the tests created will be stored directly in the &lt;code&gt;tests\Feature&lt;/code&gt; directory.&lt;/p&gt;

&lt;p&gt;Here are the contents of the file :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Support\Facades\Config&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'can view admin page'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/admin'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nv"&gt;$response&lt;/span&gt;
        &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;assertStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;assertSee&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Dashboard'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;assertSee&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Config&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'APP_NAME'&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Explanation: &lt;/p&gt;

&lt;p&gt;We ask for get access to the &lt;code&gt;/admin&lt;/code&gt; page and we get the response.&lt;/p&gt;

&lt;p&gt;In this response, we check that we do indeed have an HTTP 200 code, that in the HTML code returned we do indeed have the word &lt;code&gt;Dashboard&lt;/code&gt; and that we do indeed see the name of the application defined in our &lt;code&gt;.env&lt;/code&gt; file, in this case &lt;code&gt;LinKeeper&lt;/code&gt;. To do this, use the &lt;code&gt;config()&lt;/code&gt; helper.&lt;/p&gt;

&lt;h3&gt;
  
  
  Running the test
&lt;/h3&gt;

&lt;p&gt;To run the test, at the root of your project, run the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./vendor/bin/pest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Normally you should get a 403 error, so your test will not pass.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4avad67wcaybgdjwn0lg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4avad67wcaybgdjwn0lg.png" alt="Error 403" width="800" height="391"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Correct the 403 error
&lt;/h3&gt;

&lt;p&gt;To correct this, you need to read the &lt;a href="https://filamentphp.com/docs/3.x/panels/installation#allowing-users-to-access-a-panel"&gt;FilamentPHP documentation&lt;/a&gt; which indicates that when you go into production, you need to modify the &lt;code&gt;User&lt;/code&gt; model to avoid hitting a wall with the 403 error.&lt;/p&gt;

&lt;p&gt;I'll leave it to you to implement the necessary changes so that your test can pass.&lt;/p&gt;

&lt;p&gt;If you encounter the slightest difficulty, let me know in the comments.&lt;/p&gt;

&lt;h3&gt;
  
  
  Run the test again
&lt;/h3&gt;

&lt;p&gt;If you have correctly made the changes requested in the documentation, you should get this result when you run your tests.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6ipkk9zxo1sgd6dugy4o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6ipkk9zxo1sgd6dugy4o.png" alt="Test OK" width="800" height="397"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing the user profile
&lt;/h2&gt;

&lt;p&gt;We saw in lesson 2 that we normally have access to the user's profile. Let's set up a test to check this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan pest:test UserProfileTest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and add the following code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'has user profile page'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nf"&gt;actingAs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;find&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/admin/profile'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;assertStatus&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;assertSee&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Profile'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;assertSee&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Save changes'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will allow us to check that when I'm logged in with the user with id #1 (my user) I do indeed get an HTTP 200 code when I go to the &lt;code&gt;/admin/profile&lt;/code&gt; page and I can see the words: 'Profile' and 'Save changes'.&lt;/p&gt;

&lt;p&gt;This is a very simple test, but it validates that the user does indeed have access to this page.&lt;/p&gt;

&lt;h3&gt;
  
  
  Run the tests
&lt;/h3&gt;

&lt;p&gt;As before, run the appropriate command in your terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./vendor/bin/pest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and you should get the following result:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm0n9xpuc5g3c2gicip9y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fm0n9xpuc5g3c2gicip9y.png" alt="Tests OK" width="800" height="387"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now that we've taken our first steps with tests, we'll be able to take a test-driven development approach using PestPHP throughout this project.&lt;/p&gt;

&lt;h2&gt;
  
  
  a user can see the list of links associated with them
&lt;/h2&gt;

&lt;p&gt;This is the next stage in the development of our application.&lt;/p&gt;

&lt;p&gt;As we are using FilamentPHP for the backend, a number of features are being developed by the FilamentPHP teams and the aim here will not be to test how well Filament works as I have no doubt that this has been tested extensively.&lt;/p&gt;

&lt;p&gt;To view the list of links, the user will have a &lt;code&gt;Links&lt;/code&gt; link in the dashboard menu and this link, by FilamentPHP convention, will lead to an &lt;code&gt;admin/links&lt;/code&gt; address.&lt;/p&gt;

&lt;h3&gt;
  
  
  Let's create our tests for the Links page
&lt;/h3&gt;

&lt;p&gt;Let's create a new test, using artisan :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan pest:test PageLinksTest
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;First of all, we want to make sure that the page is accessible.&lt;/p&gt;

&lt;p&gt;To do this, we're going to add the following code to our &lt;code&gt;PageLinksTest&lt;/code&gt; file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="nf"&gt;it&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;"can access the user's links page and see 'Links' on the page"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nv"&gt;$response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/admin/links'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nv"&gt;$response&lt;/span&gt;
        &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;assertOk&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;assertSeeText&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Links'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This code will ask PestPHP to load the &lt;code&gt;/admin/links&lt;/code&gt; page and to check firstly that the page returns the HTTP code 200 and then to ensure that the word 'Links' is present in the page.&lt;/p&gt;

&lt;p&gt;You can run the tests with the &lt;code&gt;--filter&lt;/code&gt; option to execute only the test that matches the regex passed in parameter (&lt;a href="https://pestphp.com/docs/filtering-tests#content---filter"&gt;see doc&lt;/a&gt;). For example with : &lt;/p&gt;

&lt;p&gt;&lt;code&gt;./vendor/bin/pest --filter "links page"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;PestPHP will only run our last test because 'links page' is present in its description.&lt;/p&gt;

&lt;p&gt;This avoids having to run all the tests each time, especially when you have to iterate several times when setting up your test.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2uzr0c2tly5d7g2z5o3w.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2uzr0c2tly5d7g2z5o3w.png" alt="Tests KO" width="800" height="435"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The test fails and that's normal because the Links page doesn't exist at the moment.&lt;/p&gt;

&lt;p&gt;But now that the test is here and has failed, it tells us exactly what to do: &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Expected response status code [200] but received 404.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We were expecting an HTTP 200 code and instead we get a 404, which means that the requested page doesn't exist. &lt;/p&gt;

&lt;p&gt;We simply need to create it.&lt;/p&gt;

&lt;h3&gt;
  
  
  Let's create the Links page
&lt;/h3&gt;

&lt;p&gt;The 'Links' page will be a FilamentPHP administration page. It will therefore be a resource.&lt;/p&gt;

&lt;p&gt;If I take the definition from the tutorial provided with PestPHP : &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In Filament, resources are static classes used to build CRUD interfaces for your Eloquent models. They describe how administrators can interact with data from your panel using tables and forms.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We therefore understand that each Eloquent model will be associated with a resource in FilamentPHP.&lt;/p&gt;

&lt;p&gt;It is therefore time to create our resource associated with our Link model, which is itself linked to our 'links' table in our database.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan make:filament-resource Link
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In our application tree, under &lt;code&gt;app/Filament/Resources&lt;/code&gt;, we can see a &lt;code&gt;LinkResource&lt;/code&gt; directory and a &lt;code&gt;LinkResource.php&lt;/code&gt; file. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz0e2r4l594titrnwehto.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fz0e2r4l594titrnwehto.png" alt="Arborescence Filament Resources" width="512" height="362"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;LinkResource&lt;/code&gt; directory itself has a &lt;code&gt;Pages&lt;/code&gt; sub-directory which contains the &lt;code&gt;CreateLink.php&lt;/code&gt;, &lt;code&gt;EditLink.php&lt;/code&gt; and &lt;code&gt;ListLinks.php&lt;/code&gt; files. We'll talk about these later in this tutorial, so don't worry about these extra files for now.&lt;/p&gt;

&lt;p&gt;FilamentPHP, via this Artisan command, will generate the following skeleton for you:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="kn"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;App\Filament\Resources&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\Filament\Resources\LinkResource\Pages&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\Filament\Resources\LinkResource\RelationManagers&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;App\Models\Link&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Filament\Forms&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Filament\Forms\Form&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Filament\Resources\Resource&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Filament\Tables&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Filament\Tables\Table&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Database\Eloquent\Builder&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Database\Eloquent\SoftDeletingScope&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LinkResource&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Resource&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;?string&lt;/span&gt; &lt;span class="nv"&gt;$model&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Link&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;protected&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;?string&lt;/span&gt; &lt;span class="nv"&gt;$navigationIcon&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;'heroicon-o-rectangle-stack'&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;form&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Form&lt;/span&gt; &lt;span class="nv"&gt;$form&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;Form&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$form&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;schema&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
                &lt;span class="c1"&gt;//&lt;/span&gt;
            &lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;table&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Table&lt;/span&gt; &lt;span class="nv"&gt;$table&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;Table&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$table&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;columns&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
                &lt;span class="c1"&gt;//&lt;/span&gt;
            &lt;span class="p"&gt;])&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;filters&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
                &lt;span class="c1"&gt;//&lt;/span&gt;
            &lt;span class="p"&gt;])&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;actions&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
                &lt;span class="nc"&gt;Tables\Actions\EditAction&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="p"&gt;])&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;bulkActions&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
                &lt;span class="nc"&gt;Tables\Actions\BulkActionGroup&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
                    &lt;span class="nc"&gt;Tables\Actions\DeleteBulkAction&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
                &lt;span class="p"&gt;]),&lt;/span&gt;
            &lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;getRelations&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;array&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="c1"&gt;//&lt;/span&gt;
        &lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;getPages&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;array&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s1"&gt;'index'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Pages\ListLinks&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="s1"&gt;'create'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Pages\CreateLink&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/create'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="s1"&gt;'edit'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Pages\EditLink&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;route&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'/{record}/edit'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let's not worry about that for the moment. But let's run our test again:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;./vendor/bin/pest &lt;span class="nt"&gt;--filter&lt;/span&gt; &lt;span class="s2"&gt;"links page"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can see that this time our test is green.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8xb44qt2080ztinc3ws8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8xb44qt2080ztinc3ws8.png" alt="Tests OK" width="800" height="193"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If we go to the &lt;code&gt;admin/links&lt;/code&gt; page, we can see that the page does exist (HTTP code 200) and that it does indeed say &lt;strong&gt;'Links'&lt;/strong&gt;. This is why our test turns green.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw63ujncufjdh05d2io2y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw63ujncufjdh05d2io2y.png" alt="Page admin/links" width="800" height="453"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;However, we soon realise that something isn't quite right. There seem to be records but nothing is visible in the table that shows us the links.&lt;/p&gt;

&lt;p&gt;This is normal, we'll need to configure our resource file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;We'll stop here for episode 3.&lt;/p&gt;

&lt;p&gt;In this chapter, we started doing TDD for our application development and touched on resources in FilamentPHP.&lt;/p&gt;

&lt;p&gt;In the next episode, we'll continue our testing strategy with PestPHP and get to know FilamentPHP's resources better.&lt;/p&gt;

&lt;p&gt;As usual, I look forward to your comments below.&lt;/p&gt;

&lt;p&gt;See you soon.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Linkeeper - Lesson 02 - Start playing with Filament</title>
      <dc:creator>HappyToDev</dc:creator>
      <pubDate>Wed, 10 Apr 2024 16:15:15 +0000</pubDate>
      <link>https://dev.to/happytodev/linkeeper-a-linktree-alternative-with-laravel-and-filament-lesson-02-start-playing-with-filament-4n32</link>
      <guid>https://dev.to/happytodev/linkeeper-a-linktree-alternative-with-laravel-and-filament-lesson-02-start-playing-with-filament-4n32</guid>
      <description>&lt;p&gt;Ok, now your application is set.&lt;/p&gt;

&lt;p&gt;We can dive in something more concrete.&lt;/p&gt;



&lt;ul&gt;
&lt;li&gt;an user can signin, login, logout and manage his account&lt;/li&gt;
&lt;li&gt;
a link has a name, a status (published or not) and obviously a link

&lt;ul&gt;
&lt;li&gt;Let's think about table schema&lt;/li&gt;
&lt;li&gt;Let's migrate&lt;/li&gt;
&lt;li&gt;Define model and relationship&lt;/li&gt;
&lt;li&gt;
We need fake datas to plays with

&lt;ul&gt;
&lt;li&gt;The factories&lt;/li&gt;
&lt;li&gt;The seeder&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;What we need to manage our links.&lt;/p&gt;

&lt;p&gt;Remember what I said in the first part : &lt;/p&gt;

&lt;blockquote&gt;
&lt;ul&gt;
&lt;li&gt;an user can signin, login, logout and manage his account&lt;/li&gt;
&lt;li&gt;a user can see a list of their links&lt;/li&gt;
&lt;li&gt;an user can add, edit or delete a link&lt;/li&gt;
&lt;li&gt;an user can have a shareable link to share his links with the world&lt;/li&gt;
&lt;li&gt;a link has a name, a status (published or not) and obviously a link. May be we will add some options later.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  an user can signin, login, logout and manage his account
&lt;/h2&gt;

&lt;p&gt;This is done with Filament. In fact, no completely, we can login, logout but not register or even manage our own account.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv6qm92bcpnywky1s4al9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv6qm92bcpnywky1s4al9.png" alt="Signin view" width="800" height="726"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But, you will see it's very easy to add register and profile page for users.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;app/Providers/Filament/AdminPanelProvider.php&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flh2ru1xnud0vunw8tq38.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Flh2ru1xnud0vunw8tq38.png" alt="Path to AdminPanelProvider.php" width="584" height="354"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;you have to add only 2 lines under login() function call to implement both functionnalities :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AdminPanelProvider&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;PanelProvider&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;panel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Panel&lt;/span&gt; &lt;span class="nv"&gt;$panel&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;Panel&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$panel&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'admin'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'admin'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;login&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="c1"&gt;// Lesson 2 : here we add registration and profile page&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;registration&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="c1"&gt;// registration&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;profile&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;      &lt;span class="c1"&gt;// profile management&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
                &lt;span class="s1"&gt;'primary'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Color&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nc"&gt;Amber&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;])&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;discoverResources&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;in&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;app_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Filament/Resources'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'App\\Filament\\Resources'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;discoverPages&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;in&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;app_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Filament/Pages'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'App\\Filament\\Pages'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;pages&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
                &lt;span class="nc"&gt;Pages\Dashboard&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;])&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;discoverWidgets&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;in&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;app_path&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Filament/Widgets'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'App\\Filament\\Widgets'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;widgets&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
                &lt;span class="nc"&gt;Widgets\AccountWidget&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="nc"&gt;Widgets\FilamentInfoWidget&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;])&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;middleware&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
                &lt;span class="nc"&gt;EncryptCookies&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="nc"&gt;AddQueuedCookiesToResponse&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="nc"&gt;StartSession&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="nc"&gt;AuthenticateSession&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="nc"&gt;ShareErrorsFromSession&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="nc"&gt;VerifyCsrfToken&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="nc"&gt;SubstituteBindings&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="nc"&gt;DisableBladeIconComponents&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="nc"&gt;DispatchServingFilamentEvent&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;])&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;authMiddleware&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
                &lt;span class="nc"&gt;Authenticate&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Go back to your login page : &lt;code&gt;http://linkeeper.com/admin/login&lt;/code&gt; and you will see&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx3274bw47b1gvcs59fm5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx3274bw47b1gvcs59fm5.png" alt="Signin page with register link" width="800" height="762"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;that the link for signup has been added.&lt;/p&gt;

&lt;p&gt;If you login, you will see under your menu the new sub menu 'Profile'&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwvvd09d3qj7sr2q59ukj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwvvd09d3qj7sr2q59ukj.png" alt="Image description" width="800" height="266"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It allows you to edit your nickname,  your e-mail address and change your password.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmw5hvzh55vbyfsbc52m3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmw5hvzh55vbyfsbc52m3.png" alt="Image description" width="800" height="743"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So, after this very cool step we can check the first functionnality : &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;✅ an user can signin, login, logout and manage his account&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;an user can add, edit or delete a link&lt;/li&gt;
&lt;li&gt;an user can have a shareable link to share his links with the world&lt;/li&gt;
&lt;li&gt;a link has a name, a status (published or not) and obviously a link. May be we will add some options later.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  a link has a name, a status (published or not) and obviously a link
&lt;/h2&gt;

&lt;p&gt;I know it is not in the order of the list, but first it's me writing, second I need to define table &lt;code&gt;links&lt;/code&gt; and its fields before an user can add link, right ?&lt;/p&gt;

&lt;p&gt;So let me do this ! 🤣&lt;/p&gt;

&lt;h3&gt;
  
  
  Let's think about table schema
&lt;/h3&gt;

&lt;p&gt;Ok, what will be the fields in our table &lt;code&gt;links&lt;/code&gt; ?&lt;/p&gt;

&lt;p&gt;Of course an &lt;code&gt;id&lt;/code&gt;, an &lt;code&gt;url&lt;/code&gt;, a short &lt;code&gt;description&lt;/code&gt;, a &lt;code&gt;published&lt;/code&gt; status (published or not), a &lt;code&gt;user_id&lt;/code&gt; foreign key and finally the classicals &lt;code&gt;created_at&lt;/code&gt; and &lt;code&gt;updated_at&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;user_id&lt;/code&gt; is to define the relationship between a user and a link.&lt;/p&gt;

&lt;p&gt;In fact, we can resume this relation by :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a user can have 0, 1 or many links&lt;/li&gt;
&lt;li&gt;a link (unique by its &lt;code&gt;id&lt;/code&gt;) belongs to one and only one user&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is why we use a one-to-many relationship.&lt;/p&gt;

&lt;p&gt;What do you thing, is something missing ? Tell me in the comment if you think I forgot something.&lt;/p&gt;

&lt;p&gt;Ok, now we have to prepare the migration for &lt;code&gt;links&lt;/code&gt; table.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan make:migration create_links_table
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwe2824mexb8q2fr00bkt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwe2824mexb8q2fr00bkt.png" alt="Image description" width="800" height="69"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we have to edit this migration to add fields to the table. So, let's edit the migration file&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?php&lt;/span&gt;

&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Database\Migrations\Migration&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Database\Schema\Blueprint&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kn"&gt;use&lt;/span&gt; &lt;span class="nc"&gt;Illuminate\Support\Facades\Schema&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="kd"&gt;extends&lt;/span&gt; &lt;span class="nc"&gt;Migration&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="cd"&gt;/**
     * Run the migrations.
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;up&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Schema&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'links'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Blueprint&lt;/span&gt; &lt;span class="nv"&gt;$table&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="nv"&gt;$table&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;id&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="nv"&gt;$table&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'url'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nv"&gt;$table&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'description'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;nullable&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
            &lt;span class="nv"&gt;$table&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'published'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nv"&gt;$table&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;foreignId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'user_id'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;constrained&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'users'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;onDelete&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'cascade'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="nv"&gt;$table&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;timestamps&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
        &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="cd"&gt;/**
     * Reverse the migrations.
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;down&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;Schema&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;dropIfExists&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'links'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Let's migrate
&lt;/h3&gt;

&lt;p&gt;Ok, it's time to migrate. For that, we can use (again) Artisan.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="n"&gt;php&lt;/span&gt; &lt;span class="n"&gt;artisan&lt;/span&gt; &lt;span class="n"&gt;migrate&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Remember if you make something wrong or you want to modify immediately the schema, you can rollback your migration with :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="n"&gt;php&lt;/span&gt; &lt;span class="n"&gt;artisan&lt;/span&gt; &lt;span class="n"&gt;migrate&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;rollback&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And if you want to see the status of your migrations, you can use :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;&lt;span class="n"&gt;php&lt;/span&gt; &lt;span class="n"&gt;artisan&lt;/span&gt; &lt;span class="n"&gt;migrate&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Look at this screenshot captured before running the last migration.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxf2v2tzlf2ba3l9yba3t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxf2v2tzlf2ba3l9yba3t.png" alt="Image description" width="800" height="184"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We can see two things : &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;first the migration for the &lt;code&gt;links&lt;/code&gt; table was not run already&lt;/li&gt;
&lt;li&gt;second the three first migrations was launched in the same sequence : the sequence number [1]&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Define model and relationship
&lt;/h3&gt;

&lt;p&gt;The next step is to define the &lt;code&gt;Link&lt;/code&gt; model and adapt &lt;code&gt;User&lt;/code&gt; model.&lt;/p&gt;

&lt;p&gt;We will use again Artisan :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan make:model Link
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgfdmp8zwp3xvv04xmebs.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgfdmp8zwp3xvv04xmebs.png" alt="Image description" width="800" height="112"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now we have to tell the model that a link belongs to an user.&lt;/p&gt;

&lt;p&gt;Add this function to the model class &lt;code&gt;Link&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;belongsTo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To finish with the model, we have to update the model &lt;code&gt;User&lt;/code&gt; by adding it a function &lt;code&gt;links&lt;/code&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;links&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nv"&gt;$this&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;hasMany&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;Link&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;class&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  We need fake datas to plays with
&lt;/h3&gt;

&lt;p&gt;After defining our database schema, let's do something very important.&lt;/p&gt;

&lt;p&gt;Create fake datas to play with. Please do not use production datas from your database during development.&lt;br&gt;
For many reasons such as ethics, confidentiality and security. We are professionals, so let's act accordingly.&lt;/p&gt;
&lt;h4&gt;
  
  
  The factories
&lt;/h4&gt;

&lt;p&gt;By default Laravel comes with &lt;code&gt;User&lt;/code&gt; factory, so we just need to create a &lt;code&gt;Link&lt;/code&gt; factory.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan make:factory Link
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the generated &lt;code&gt;definition&lt;/code&gt; function we put this code :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;definition&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;array&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
            &lt;span class="s1"&gt;'url'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;fake&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;url&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="s1"&gt;'description'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;fake&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;sentence&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="s1"&gt;'published'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;fake&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;boolean&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Factories use Faker to generate fake datas but very close to real datas.&lt;/p&gt;

&lt;p&gt;In this code, we generate :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;an url&lt;/li&gt;
&lt;li&gt;a description based on a sentence of 5 words. In fact, as I let the second parameter of &lt;code&gt;sentence&lt;/code&gt; method by default (true), sentence will generate sentences with approximately 5 words. It could be four, five, six or even seven words.&lt;/li&gt;
&lt;li&gt;true or false for the &lt;code&gt;published&lt;/code&gt; field with a minimum true percentage of 80%&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  The seeder
&lt;/h4&gt;

&lt;p&gt;Laravel comes with &lt;code&gt;database/seeders/DatabaseSeeder.php&lt;/code&gt; &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdv63g7jmzuqb9jofvh20.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdv63g7jmzuqb9jofvh20.png" alt="Path to DatabaseSeeder.php" width="584" height="492"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We have to edit it to use our factory.&lt;/p&gt;

&lt;p&gt;Here it is the code :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;    &lt;span class="cd"&gt;/**
     * Seed the application's database.
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt;&lt;span class="p"&gt;():&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;factory&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;
            &lt;span class="s1"&gt;'name'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'Happytodev'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'email'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="s1"&gt;'happytodev@gmail.com'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
            &lt;span class="s1"&gt;'email_verified_at'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;now&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
            &lt;span class="s1"&gt;'password'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Hash&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;make&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'Password*'&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
            &lt;span class="s1"&gt;'remember_token'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nc"&gt;Str&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="p"&gt;]);&lt;/span&gt;

        &lt;span class="nc"&gt;User&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;factory&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;each&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nc"&gt;Link&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;factory&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
                    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nb"&gt;count&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
                    &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;create&lt;/span&gt;&lt;span class="p"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'user_id'&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$user&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
            &lt;span class="p"&gt;});&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Some explanations :&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;First I create my own user to connect easily each time with my own email&lt;/li&gt;
&lt;li&gt;Second part does this

&lt;ul&gt;
&lt;li&gt;create 10 fake users&lt;/li&gt;
&lt;li&gt;for every user create between 2 and 10 links, during the creation we told that the &lt;code&gt;user_id&lt;/code&gt; fiels must be filled with the current created &lt;code&gt;user-&amp;gt;id&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And now, the magic could begin.&lt;/p&gt;

&lt;p&gt;Let's go back in your terminal, and launch simply this command :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan db:seed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvtpnnyw793fuibqibihi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvtpnnyw793fuibqibihi.png" alt="Seeding database" width="800" height="136"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Go into your DB viewer, and check the tables &lt;code&gt;users&lt;/code&gt; and &lt;code&gt;links&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You should see something like that : &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;users&lt;/code&gt; table&lt;br&gt;
&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnwcdnbm1hs3tn3x5r6qy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fnwcdnbm1hs3tn3x5r6qy.png" alt="Users table" width="800" height="249"&gt;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;code&gt;links&lt;/code&gt; table&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fagfg85t03wym6rl5w8i4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fagfg85t03wym6rl5w8i4.png" alt="Links table" width="800" height="631"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you want to check everything works fine, we can go a walk in Tinker.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan tinker
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Tinker will let us to play with our datas and check the relationship is currently working.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User::find(6)-&amp;gt;links()-&amp;gt;get(['id', 'url', 'published', 'user_id']);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we ask to find every link for the user with id = 6. We ask too to get only interesting fields.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foatqw2v70x4nqhq8o16j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foatqw2v70x4nqhq8o16j.png" alt="Tinker query results" width="800" height="583"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Seeing these results, we can improve immediately something.&lt;/p&gt;

&lt;p&gt;What if, we only want the published links ?&lt;/p&gt;

&lt;p&gt;So you can do it like this :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;&amp;gt; User::find(6)-&amp;gt;links()-&amp;gt;where('published', 1)-&amp;gt;get(['id', 'url', 'published', 'user_id']);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But there is a better way to do this and don't repeat yourself later. We can use Scopes.&lt;/p&gt;

&lt;p&gt;A scope can add a bunch of query to your query. Scopes can be global or local. I let you consult &lt;a href="https://laravel.com/docs/11.x/eloquent#query-scopes"&gt;the documentation&lt;/a&gt; to see more.&lt;/p&gt;

&lt;p&gt;Here we will use a local scope.&lt;/p&gt;

&lt;p&gt;Go to your &lt;code&gt;link&lt;/code&gt; model and add this function :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight php"&gt;&lt;code&gt;    &lt;span class="cd"&gt;/**
     * Scope a query to only include published links.
     */&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;scopePublished&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;Builder&lt;/span&gt; &lt;span class="nv"&gt;$query&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kt"&gt;void&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nv"&gt;$query&lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="nf"&gt;where&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s1"&gt;'published'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, if in Tinker we use the following query :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;User::find&lt;span class="o"&gt;(&lt;/span&gt;6&lt;span class="o"&gt;)&lt;/span&gt;-&amp;gt;links&lt;span class="o"&gt;()&lt;/span&gt;-&amp;gt;published&lt;span class="o"&gt;()&lt;/span&gt;-&amp;gt;get&lt;span class="o"&gt;([&lt;/span&gt;&lt;span class="s1"&gt;'id'&lt;/span&gt;, &lt;span class="s1"&gt;'url'&lt;/span&gt;, &lt;span class="s1"&gt;'published'&lt;/span&gt;, &lt;span class="s1"&gt;'user_id'&lt;/span&gt;&lt;span class="o"&gt;])&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;we will obtain only the published links from user with id = 6.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc2gxinb0av40mmo3fpoe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fc2gxinb0av40mmo3fpoe.png" alt="Tinker query using scope" width="800" height="520"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And voilà, we can cross this point in our list :&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;✅ an user can signin, login, logout and manage his account&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a user can see a list of their links&lt;/li&gt;
&lt;li&gt;an user can add, edit or delete a link&lt;/li&gt;
&lt;li&gt;an user can have a shareable link to share his links with the world&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;✅ a link has a name, a status (published or not) and obviously a link. May be we will add some options later.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Well, we'll stop here for today.&lt;/p&gt;

&lt;p&gt;In this longer chapter, we saw introduction to : &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;how to add functionnality to login page in Filament&lt;/li&gt;
&lt;li&gt;models&lt;/li&gt;
&lt;li&gt;factory&lt;/li&gt;
&lt;li&gt;seeder&lt;/li&gt;
&lt;li&gt;Tinker&lt;/li&gt;
&lt;li&gt;scopes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As usual, I wait for your comments below.&lt;/p&gt;

&lt;p&gt;See you.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>filament</category>
      <category>php</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Linkeeper - Lesson 01 - Installation</title>
      <dc:creator>HappyToDev</dc:creator>
      <pubDate>Wed, 10 Apr 2024 15:00:00 +0000</pubDate>
      <link>https://dev.to/happytodev/linkeeper-a-linktree-alternative-with-laravel-and-filament-lesson-01-installation-3na3</link>
      <guid>https://dev.to/happytodev/linkeeper-a-linktree-alternative-with-laravel-and-filament-lesson-01-installation-3na3</guid>
      <description>&lt;p&gt;In this little serie, we will learn the basics about Laravel through a little application &lt;strong&gt;LinKeeper&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;It goal is to keep your links and share them to the world.&lt;/p&gt;

&lt;p&gt;So, what we need ?&lt;/p&gt;

&lt;p&gt;We have to bring solutions to these definitions : &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;an user can signin, login, logout and manage his account&lt;/li&gt;
&lt;li&gt;a user can see a list of their links&lt;/li&gt;
&lt;li&gt;an user can add, edit or delete a link&lt;/li&gt;
&lt;li&gt;an user can have a shareable link to share his links with the world&lt;/li&gt;
&lt;li&gt;a link has a name, a status (published or not) and obviously a link. May be we will add some options later.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The purpose here is to discover the basic concepts of Laravel and FilamentPHP. &lt;/p&gt;

&lt;p&gt;In this serie, I will use Laravel 11 and FilamentPHP 3.&lt;/p&gt;

&lt;p&gt;Let's go and beginning with the very basic : the install&lt;/p&gt;



&lt;ul&gt;
&lt;li&gt;
Installing Laravel

&lt;ul&gt;
&lt;li&gt;Launch install with Laravel Installer&lt;/li&gt;
&lt;li&gt;Laravel is installed 🎉&lt;/li&gt;
&lt;li&gt;Check the install&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;
FilamentPHP install

&lt;ul&gt;
&lt;li&gt;Create a first user&lt;/li&gt;
&lt;li&gt;Check the install&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;Change the name of application&lt;/li&gt;
&lt;/ul&gt;



&lt;h2&gt;
  
  
  Installing Laravel
&lt;/h2&gt;

&lt;p&gt;As every Laravel project, we have to launch the laravel install.&lt;/p&gt;

&lt;p&gt;If you have the laravel installer it's as easy as type &lt;code&gt;laravel new linkeeper&lt;/code&gt; in your favorite terminal.&lt;/p&gt;

&lt;p&gt;If you prefer &lt;strong&gt;composer&lt;/strong&gt;, just use this command instead &lt;code&gt;composer create-project laravel/laravel linkeeper&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Follow theses steps, which consisting to keep default choices and click enter three times 😉.&lt;/p&gt;

&lt;h3&gt;
  
  
  Launch install with Laravel Installer
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd0wdg2axdm0ap58rswe1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd0wdg2axdm0ap58rswe1.png" alt="Image description" width="800" height="429"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh60of4shtatfn6h0aujf.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fh60of4shtatfn6h0aujf.png" alt="Image description" width="800" height="588"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3igfo4q2x30ux4lf6fgu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3igfo4q2x30ux4lf6fgu.png" alt="Image description" width="800" height="225"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Laravel is installed 🎉
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg93yt41em82iuzjl1izq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg93yt41em82iuzjl1izq.png" alt="Image description" width="800" height="176"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As we have choose sqlite as database there is no more configuration needed, except &lt;code&gt;APP_NAME&lt;/code&gt;, &lt;code&gt;APP_TIMEZONE&lt;/code&gt; if you want.&lt;/p&gt;

&lt;p&gt;For more simplicity, I let the language setting with default value. Feel free to change it if you need.&lt;/p&gt;

&lt;h3&gt;
  
  
  Check the install
&lt;/h3&gt;

&lt;p&gt;Personnaly, I work on Mac with Herd. I can check &lt;a href="http://linkeeper.test"&gt;http://linkeeper.test&lt;/a&gt; on my browser.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy24tx1r07a3l0a9jrpt6.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fy24tx1r07a3l0a9jrpt6.png" alt="Image description" width="800" height="565"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Everything seems ok !&lt;/p&gt;

&lt;p&gt;If you need to work with &lt;code&gt;https&lt;/code&gt;, it's perfectly possible with Herd in a single click.&lt;/p&gt;

&lt;p&gt;Go to Herd settings, choose 'Sites' tab and search for your current url. Here : &lt;code&gt;linkeeper.test&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Look for the lock and click on it to activate https.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpljg79uxsrb2dsrrogw2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpljg79uxsrb2dsrrogw2.png" alt="Image description" width="800" height="215"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F43h6inu9d35bkg0zf3eo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F43h6inu9d35bkg0zf3eo.png" alt="Image description" width="800" height="213"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Easy, peasy ! No ?&lt;/p&gt;

&lt;h2&gt;
  
  
  FilamentPHP install
&lt;/h2&gt;

&lt;p&gt;Now, we have to install FilamentPHP. Sincerely, you don't need me for these steps, you just have to look at the incredible documentation of Laravel and Filament.&lt;/p&gt;

&lt;p&gt;But, if you are already here, let's keep forwarding together 🤣&lt;/p&gt;

&lt;p&gt;So, just copy / paste the 'Get Started' tutorial :&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;composer require filament/filament:&lt;span class="s2"&gt;"^3.2"&lt;/span&gt; &lt;span class="nt"&gt;-W&lt;/span&gt;

php artisan filament:install &lt;span class="nt"&gt;--panels&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Let the default choice when Filament ask for id : &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmhril0xcfyidi8cv4mto.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fmhril0xcfyidi8cv4mto.png" alt="Image description" width="800" height="143"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And voilà! Filament is installed.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create a first user
&lt;/h3&gt;

&lt;p&gt;We need an user to start play with Filament.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;php artisan make:filament-user
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here too, answer questions for your name, email and password.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdh4lt53gw9ofkfks4fly.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdh4lt53gw9ofkfks4fly.png" alt="Image description" width="800" height="321"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Check the install
&lt;/h3&gt;

&lt;p&gt;Let's go to the link provided to ensure that everything is ok.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg016xqdeekj4ftm047s0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg016xqdeekj4ftm047s0.png" alt="Image description" width="800" height="707"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Enter your credentials and if everything is ok, you will see something like that : &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5je5w47q1pz7k283mjwg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5je5w47q1pz7k283mjwg.png" alt="Image description" width="800" height="249"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Change the name of application
&lt;/h2&gt;

&lt;p&gt;As you can see in the top left corner the name of the app is "Laravel", let's change this for "LinKeeper".&lt;/p&gt;

&lt;p&gt;Open your project in your favorite IDE or if you prefer for this minor change, type &lt;code&gt;nano .env&lt;/code&gt;in your terminal.&lt;/p&gt;

&lt;p&gt;You just have to change the &lt;code&gt;APP_NAME&lt;/code&gt; key : &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbvas4lbahg6qgmun6nbr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbvas4lbahg6qgmun6nbr.png" alt="Image description" width="752" height="362"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If your name has spaces, you have to use the quote for your name.&lt;/p&gt;

&lt;p&gt;ctrl + x to exit, say 'yes' when nano asked you if you want to save your file and confirm the name of the file (.env) by pressing return key.&lt;/p&gt;

&lt;p&gt;Your &lt;code&gt;.env&lt;/code&gt; file is now saved, you can reload your page and you will see the name of the app changed in the top left corner.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faitesaoxaatn0qu60sm8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/cdn-cgi/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Faitesaoxaatn0qu60sm8.png" alt="Image description" width="800" height="223"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the end of this first part. In the next episode, we'll see how to start playing with Filament and models.&lt;/p&gt;

&lt;p&gt;Don't hesitate to comment if you have question or if you see a mistake.&lt;/p&gt;

</description>
      <category>laravel</category>
      <category>filament</category>
      <category>php</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>Quoi de neuf les devs ? #80 avec l'interview de Gabin Aurèche</title>
      <dc:creator>HappyToDev</dc:creator>
      <pubDate>Tue, 09 Apr 2024 10:05:06 +0000</pubDate>
      <link>https://dev.to/happytodev/quoi-de-neuf-les-devs-80-avec-linterview-de-gabin-aureche-2oih</link>
      <guid>https://dev.to/happytodev/quoi-de-neuf-les-devs-80-avec-linterview-de-gabin-aureche-2oih</guid>
      <description>&lt;p&gt;Hello à toutes et à tous 😉,&lt;/p&gt;

&lt;p&gt;J'ai le plaisir de vous partager le nouveau numéro de "Quoi de neuf les devs ?" sorti samedi dernier.&lt;/p&gt;

&lt;p&gt;J'y recevais &lt;a class="mentioned-user" href="https://dev.to/gabinaureche"&gt;@gabinaureche&lt;/a&gt;, il est dev et donne également très régulièrement des conseils sur les structures d’entreprise, sur l’argent en entreprise. &lt;/p&gt;

&lt;p&gt;Comme chaque semaine, vous retrouverez les autres rubriques avec toujours le plein d’actualité sur le monde du dev.&lt;/p&gt;

&lt;p&gt;Cette semaine, parmi tous les sujets abordés, on parlera entre autres de&lt;br&gt;
✅ Go, &lt;br&gt;
✅ QR Code,&lt;br&gt;
✅ Redis, &lt;br&gt;
✅ Side project, &lt;br&gt;
✅ Email, &lt;br&gt;
✅ FFmpeg,&lt;br&gt;
✅ et bien d’autres sujets encore&lt;/p&gt;

&lt;p&gt;Bonne lecture!&lt;/p&gt;

&lt;p&gt;Si le contenu vous plait et que vous souhaitez me soutenir, abonnez vous et rejoignez plus de 1700 pros de l'IT d'ores et déjà abonné.e.s.&lt;/p&gt;

&lt;p&gt;PS : Quel.le dev souhaiteriez vous voir interviewé.e dans un prochain numéro ?&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>newsletter</category>
      <category>interview</category>
    </item>
  </channel>
</rss>
