One place for hosting & domains

      Laravel

      How To Insert New Database Records in Laravel Eloquent



      Part of the Series:
      A Practical Introduction to Laravel Eloquent ORM

      Eloquent is an object relational mapper (ORM) that is included by default within the Laravel framework. In this project-based series, you’ll learn how to make database queries and how to work with relationships in Laravel Eloquent. To practice the examples explained throughout the series, you’ll improve a demo application with new models and relationships.

      In a previous section of this series, you set up two models for a one-to-many relationship between the LinkList and Link models. In this section, you’ll learn how to insert links and lists in the database using Eloquent models. To limit the scope of this work, you’ll use custom Artisan commands to manage links and lists from the command line, which won’t require a web form.

      One of the biggest advantages of using an ORM system is the ability to manipulate rows in a database table as objects within your codebase. With Eloquent, as with other ORMs, the object itself provides methods that can be used to persist it to the database, saving you the work of writing SQL statements and manually managing data within tables.

      When working with one-to-many relationships in Laravel Eloquent, you have a few different options to save related models. In most cases, you’ll need to first set up the model representing the one side of the relationship, which in this demo is the LinkList model, and save that to the database. After doing that, you’ll be able to reference this model (which, once saved, represents a database record) when setting up the many side of the relationship (the Link model). That also means you’ll need to first have one or more lists in order to be able to create links.

      Before creating a new command to insert lists, however, you should update the existing link:new command to support the list feature.

      Open the following file in your code editor:

      app/Console/Commands/LinkNew.php
      

      You’ll see code like this:

      app/Console/Commands/LinkNew.php

      <?php
      
      namespace AppConsoleCommands;
      
      use AppModelsLink;
      use IlluminateConsoleCommand;
      use IlluminateSupportFacadesDB;
      
      class LinkNew extends Command
      {
          /**
           * The name and signature of the console command.
           *
           * @var string
           */
          protected $signature="link:new";
      
          /**
           * The console command description.
           *
           * @var string
           */
          protected $description = 'Create a New Link';
      
          /**
           * Create a new command instance.
           *
           * @return void
           */
          public function __construct()
          {
              parent::__construct();
          }
      
          /**
           * Execute the console command.
           *
           * @return int
           */
          public function handle()
          {
              $url = $this->ask('Link URL:');
      
              if (!filter_var($url, FILTER_VALIDATE_URL)) {
                  $this->error("Invalid URL. Exiting...");
                  return 1;
              }
      
              $description = $this->ask('Link Description:');
      
              $this->info("New Link:");
              $this->info($url . ' - ' . $description);
      
              if ($this->confirm('Is this information correct?')) {
                  $link = new Link();
                  $link->url = $url;
                  $link->description = $description;
                  $link->save();
      
                  $this->info("Saved.");
              }
      
              return 0;
          }
      }
      
      

      The handle() method is where the command executes its procedures. This is what it does:

      1. The ask() method, made available through the parent IlluminateConsoleCommand class, is a method used to obtain input from a user in the command line. This will prompt a user for a link, and validate the input to make sure it’s a valid URL.
      2. The script then asks for an optional description.
      3. Once values for url and description are obtained, the script will prompt for a confirmation using the confirm() method, available through the parent IlluminateConsoleCommand.
      4. When a confirmation is submitted with y or yes, the script will set up a new link object and save it to the database using the save() method, available through the model’s parent IlluminateDatabaseEloquentModel class.
      5. The script outputs a message to inform the user that the link was saved to the database, using the info output method.

      Note about return values: in the context of command line applications running on bash, non-zero return values are used to signal that the application exited in error, while 0 means it exited with success.

      If you run the link:new command now, it will break before it is finished because the database expects every link to be connected to a list. You’ll need to let the user choose which list a link should be included in, using a default list if none is provided by the user.

      The following code will ask the user to specify a list or leave it blank to use the default list. Then, it will try to locate the list or create a new list using the specified slug in case the list doesn’t exist yet. To retrieve a list provided by the user, this code uses the firstWhere method to find a list based on its slug field. Finally, it saves the new link using the links() relationship that can be accessed from the LinkList object.

      Substitute the current content in your LinkNew command class with:

      app/Console/Commands/LinkNew.php

      <?php
      
      namespace AppConsoleCommands;
      
      use AppModelsLink;
      use AppModelsLinkList;
      use IlluminateConsoleCommand;
      use IlluminateSupportFacadesDB;
      
      class LinkNew extends Command
      {
          /**
           * The name and signature of the console command.
           *
           * @var string
           */
          protected $signature="link:new";
      
          /**
           * The console command description.
           *
           * @var string
           */
          protected $description = 'Create a New Link';
      
          /**
           * Create a new command instance.
           *
           * @return void
           */
          public function __construct()
          {
              parent::__construct();
          }
      
          /**
           * Execute the console command.
           *
           * @return int
           */
          public function handle()
          {
              $url = $this->ask('Link URL');
      
              if (!filter_var($url, FILTER_VALIDATE_URL)) {
                  $this->error("Invalid URL. Exiting...");
                  return 1;
              }
      
              $description = $this->ask('Link Description');
              $list_name = $this->ask('Link List (leave blank to use default)') ?? "default";
      
              $this->info("New Link:");
              $this->info($url . ' - ' . $description);
              $this->info("Listed in: " . $list_name);
      
              if ($this->confirm('Is this information correct?')) {
                  $list = LinkList::firstWhere('slug', $list_name);
                  if (!$list) {
                      $list = new LinkList();
                      $list->title = $list_name;
                      $list->slug = $list_name;
                      $list->save();
                  }
      
                  $link = new Link();
                  $link->url = $url;
                  $link->description = $description;
                  $list->links()->save($link);
      
                  $this->info("Saved.");
              }
      
              return 0;
          }
      }
      
      

      Save and close the file when you’re done. Then, run the command with:

      • docker-compose exec app php artisan link:new

      You’ll be prompted to provide a URL, a description, and a list name, in case you don’t want to save this link to the default list.

      Once you save your new link, if you run the link:show command, you should see the new link added to the results. However, there is no information included in the output about lists yet. You’ll need to update the LinkShow command to include a column that displays this information.

      Open the app/Console/Commands/LinkShow.php file in your code editor:

      app/Console/Commands/LinkShow.php
      

      This is how the class should look like now:

      app/Console/Commands/LinkShow.php

      <?php
      
      namespace AppConsoleCommands;
      
      use AppModelsLink;
      use IlluminateConsoleCommand;
      
      class LinkShow extends Command
      {
          /**
           * The name and signature of the console command.
           *
           * @var string
           */
          protected $signature="link:show";
      
          /**
           * The console command description.
           *
           * @var string
           */
          protected $description = 'List links saved in the database';
      
          /**
           * Create a new command instance.
           *
           * @return void
           */
          public function __construct()
          {
              parent::__construct();
          }
      
          /**
           * Execute the console command.
           *
           * @return int
           */
          public function handle()
          {
              $headers = [ 'id', 'url', 'description' ];
              $links = Link::all(['id', 'url', 'description'])->toArray();
              $this->table($headers, $links);
      
              return 0;
          }
      }
      

      You’ll see that the current handle() method is fetching a certain number of fields and converting the result to an array. By default, results come from Eloquent as an Eloquent Collection, so this function converts them to an array in order to use that data within the table() method. The problem is that when the array conversion is made, you lose the relationship between class models (Link and LinkList), which makes it more difficult to access information about the list that a link is connected to.

      You’ll need to change this code so that it fetches the full Link object, including the related objects from the database. To create an array that is suitable for using with the table() method, you can iterate through the collection of results returned by Link::all().

      Replace the current contents in the app/Console/Commands/LinkShow.php file with the following code:

      app/Console/Commands/LinkShow.php

      <?php
      
      namespace AppConsoleCommands;
      
      use AppModelsLink;
      use IlluminateConsoleCommand;
      
      class LinkShow extends Command
      {
          /**
           * The name and signature of the console command.
           *
           * @var string
           */
          protected $signature="link:show";
      
          /**
           * The console command description.
           *
           * @var string
           */
          protected $description = 'List links saved in the database';
      
          /**
           * Create a new command instance.
           *
           * @return void
           */
          public function __construct()
          {
              parent::__construct();
          }
      
          /**
           * Execute the console command.
           *
           * @return int
           */
          public function handle()
          {
              $headers = [ 'id', 'url', 'list', 'description' ];
              $links = Link::all();
      
              $table_rows = [];
              foreach ($links as $link) {
                  $table_rows[] = [ $link->id, $link->url, $link->link_list->slug, $link->description ];
              }
      
              $this->table($headers, $table_rows);
      
              return 0;
          }
      }
      
      

      Now, if you run the link:show method, you’ll see an additional column showing the list slug:

      Output

      +----+-----------------------------------------------------------------------------------------+-----------+--------------------------------------+ | id | url | list | description | +----+-----------------------------------------------------------------------------------------+-----------+--------------------------------------+ | 1 | https://digitalocean.com | default | DigitalOcean Website | | 2 | https://digitalocean.com/community/tutorials | tutorials | DO Tutorials | | 3 | https://www.digitalocean.com/community/tutorials/initial-server-setup-with-ubuntu-20-04 | tutorials | Initial server setup on ubuntu 20.04 | +----+-----------------------------------------------------------------------------------------+-----------+--------------------------------------+

      Later in this tutorial series, you’ll update the front end and main route code to show links organized into lists. For now, you’ll use the command line to add, migrate, and validate your changes to the database and models.

      The next tutorial in this series will demonstrate another way of inserting new records in the database using Eloquent models, this time through the use of database seeders.

      This tutorial is part of an ongoing weekly series about Laravel Eloquent. You can subscribe to the Laravel tag if you want to be notified when new tutorials are published.



      Source link

      How To Create a One-To-Many Relationship in Laravel Eloquent



      Part of the Series:
      A Practical Introduction to Laravel Eloquent ORM

      Eloquent is an object relational mapper (ORM) that is included by default within the Laravel framework. In this project-based series, you’ll learn how to make database queries and how to work with relationships in Laravel Eloquent. To practice the examples explained throughout the series, you’ll improve a demo application with new models and relationships.

      The demo Landing Laravel application that you set up as a prerequisite for this series contains a single database table to store links. In this tutorial you’ll modify this initial database structure to include a second table, which you will use to organize links into lists.

      For the links and lists example we’re going to use in this series, each link is part of only one list, but each list can have multiple links. This kind of relationship is also known as a one-to-many relationship.

      A one-to-many relationship happens when one item, which we’ll call type A, can be linked to several items of type B, but the opposite doesn’t hold true: an item of type B can only be linked to one item of type A. Transposing this scenario to the current demo application models, A is the list type, and B is the link type.

      To get started, you’ll need to create a model and a database table to represent a List of links. Then, you’ll update the existing Link model and table to include the relationship between both models. Because the term List is reserved for PHP internals, you won’t be able to name your new model with that term. You can call this new model LinkList instead.

      First, make sure you’re in the application directory:

      Create a new model using artisan:

      • docker-compose exec app php artisan make:model LinkList

      This will generate a new model class in the app/Model directory:

      app/Model/LinkList.php
      

      If you look at your app/Console/Commands directory, you’ll notice that there’s already a class file named LinkList.php. This is not to be confused with the Eloquent model you just created. This class contains a CLI command that lists all the links in the database via artisan.

      To avoid confusion in the future, now is a good moment to rename that class and its command signature to a different name. In this case use the class name LinkShow since that name also describes what the class does. To rename the app/Console/Commands/LinkList.php file to another valid name, run this command in your terminal:

      • mv app/Console/Commands/LinkList.php app/Console/Commands/LinkShow.php

      Then, open the file app/Console/Commands/LinkShow.php in your code editor to change the class name from LinkList to LinkShow, and the command signature from link:list to link:show, like the highlighted lines in the following code listing. This is how the file should look like once you’re finished:

      app/Console/Commands/LinkShow.php

      <?php
      
      namespace AppConsoleCommands;
      
      use AppModelsLink;
      use IlluminateConsoleCommand;
      
      class LinkShow extends Command
      {
          /**
           * The name and signature of the console command.
           *
           * @var string
           */
          protected $signature = 'link:show';
      
          /**
           * The console command description.
           *
           * @var string
           */
          protected $description = 'List links saved in the database';
      
          /**
           * Create a new command instance.
           *
           * @return void
           */
          public function __construct()
          {
              parent::__construct();
          }
      
          /**
           * Execute the console command.
           *
           * @return int
           */
          public function handle()
          {
              $headers = [ 'id', 'url', 'description' ];
              $links = Link::all(['id', 'url', 'description'])->toArray();
              $this->table($headers, $links);
      
              return 0;
          }
      }
      

      Save and close the file when you’re done. To check that everything worked as expected, run your newly renamed link:show artisan command:

      • docker-compose exec app php artisan link:show

      You’ll receive output like this:

      Output

      +----+-------------------------------------------------+----------------------------------+ | id | url | description | +----+-------------------------------------------------+----------------------------------+ | 1 | https://digitalocean.com/community | DigitalOcean Community | | 2 | https://digitalocean.com/community/tags/laravel | Laravel Tutorias at DigitalOcean | | 3 | https://digitalocean.com/community/tags/php | PHP Tutorials at DigitalOcean | +----+-------------------------------------------------+----------------------------------+

      The new app/Model/LinkList.php class that you generated with the previous artisan make:model command contains generic code for a new Eloquent class. Unlike other ORMs such as Doctrine, Eloquent doesn’t alter database structures, handling only data itself. Eloquent models are usually lean, with class properties automatically inferred from the model’s table structure.

      This approach to handling data-only with Eloquent means that you don’t need to set up any properties for the LinkList class because they will be inferred from the database table structure for that model.

      Structural database operations are typically handled in Laravel via database migrations. Migrations allow developers to programmatically define structural changes to the database, such as creating, modifying, and deleting tables.

      You’ll now create a new migration to set up the lists table in the database.

      The artisan command line tool included by default with Laravel contains several helper methods to bootstrap new components such as controllers, models, migrations, among others. To create a new migration using artisan, run:

      • docker-compose exec app php artisan make:migration create_link_lists_table

      Output

      Created Migration: 2021_07_07_152554_create_link_lists_table

      This command will generate a new file under the database/migrations directory in your Laravel application, using an auto-generated name based on the current date and time, and the migration name. That file contains generic code that you’ll modify to set up the lists table.

      Using your code editor, open the generated migration file. The file currently looks like this:

      database/migrations/2021_07_07_152554_create_link_lists_table.php

      <?php
      
      use IlluminateDatabaseMigrationsMigration;
      use IlluminateDatabaseSchemaBlueprint;
      use IlluminateSupportFacadesSchema;
      
      class CreateLinkListsTable extends Migration
      {
          /**
           * Run the migrations.
           *
           * @return void
           */
          public function up()
          {
              Schema::create('link_lists', function (Blueprint $table) {
                  $table->id();
                  $table->timestamps();
              });
          }
      
          /**
           * Reverse the migrations.
           *
           * @return void
           */
          public function down()
          {
              Schema::dropIfExists('link_lists');
          }
      }
      
      

      The migration runs the up() method when executed with the artisan migrate command. This is where your table definition goes, and by default it creates an id primary key field and two timestamp fields (created_at and updated_at), defined with the timestamps() Schema method. Those fields are automatically filled by Eloquent when a model is created and updated, respectively. The down() method is called when the migration is rolled back with the artisan rollback command, and typically executes code to drop the table or revert structural changes.

      You’ll change the up method to include the following fields:

      • title: a string representing the title of this List
      • description: a string representing the description of a List
      • slug: a unique, short string based on the title, typically used to create user-friendly URLs

      In a one-to-many relationship, the many side (which in this scenario corresponds to the links table) is the one to hold the column reference (or foreign key) to the other element (corresponding to the lists table). That means you’ll have to modify the links table later on, in order to include a reference field that will link that table to the lists table.

      The lists table, on the other hand, doesn’t need any special field to reference its links.

      Replace the current content in your migration file with the following code:

      database/migrations/2021_07_07_152554_create_link_lists_table.php

      <?php
      
      use IlluminateDatabaseMigrationsMigration;
      use IlluminateDatabaseSchemaBlueprint;
      use IlluminateSupportFacadesSchema;
      
      class CreateLinkListsTable extends Migration
      {
          /**
           * Run the migrations.
           *
           * @return void
           */
          public function up()
          {
              Schema::create('link_lists', function (Blueprint $table) {
                  $table->id();
                  $table->timestamps();
                  $table->string('title', 60);
                  $table->string('slug', 60)->unique();
                  $table->text('description')->nullable();
              });
          }
      
          /**
           * Reverse the migrations.
           *
           * @return void
           */
          public function down()
          {
              Schema::dropIfExists('link_lists');
          }
      }
      
      

      Save the file when you’re done.

      Next, open the existing links migration file in your code editor. In the demo project, you’ll find the migration at the following path:

      2020_11_18_165241_create_links_table.php
      

      First, include a use directive pointing to the fully qualified class name for the LinkList class, at the beginning of the file and right after the last use line:

      …
      use IlluminateSupportFacadesSchema;
      use AppModelsLinkList;
      ...
      

      Next, include the following line in the table definition, within the up method and right after the line that sets up the description field:

      $table->text('description');
      $table->foreignIdFor(LinkList::class);
      

      The foreignIdFor() method creates a foreign key column to the referenced Eloquent model. It uses default nomenclature to set up a field that is linked to the primary key field of the referenced table.

      This is how the full migration class should look like when you’re done:

      database/migrations/2020_11_18_165241_create_links_table.php

      <?php
      
      use IlluminateDatabaseMigrationsMigration;
      use IlluminateDatabaseSchemaBlueprint;
      use IlluminateSupportFacadesSchema;
      use AppModelsLinkList;
      
      class CreateLinksTable extends Migration
      {
          /**
           * Run the migrations.
           *
           * @return void
           */
          public function up()
          {
              Schema::create('links', function (Blueprint $table) {
                  $table->id();
                  $table->string('url', 200);
                  $table->text('description');
                  $table->foreignIdFor(LinkList::class);
                  $table->timestamps();
              });
          }
      
          /**
           * Reverse the migrations.
           *
           * @return void
           */
          public function down()
          {
              Schema::dropIfExists('links');
          }
      }
      

      Save the file when you’re finished editing it. Next, wipe the database and then run the migration command again to recreate your database structure with the updated migrations files:

      • docker-compose exec app php artisan db:wipe
      • docker-compose exec app php artisan migrate

      Configuring Eloquent Model Relationships

      The database tables are now set up, but you still need to configure the Eloquent models to define the relationship between them.

      On the List model, which is the one side of the relationship, you’ll set up a new method named links. This method will work as a proxy to access the links that are related to each list, using the hasMany method from the parent IlluminateDatabaseEloquentModel class.

      In your code editor, open the file app/Model/LinkList.php. Replace the current generic code with the following content:

      app/Model/LinkList.php

      <?php
      
      namespace AppModels;
      
      use IlluminateDatabaseEloquentFactoriesHasFactory;
      use IlluminateDatabaseEloquentModel;
      
      class LinkList extends Model
      {
          use HasFactory;
      
          public function links()
          {
              return $this->hasMany(Link::class);
          }
      }
      
      

      Save the file when you’re done.

      Next, you’ll edit the many side of the relationship to include a reference back to the List model, so that links can access their respective list. This is done with the belongsTo method from the parent Model class. This method is used to define the inverse side of the one-to-many relationship.

      Open the Link model in your code editor:

      app/Model/Link.php
      

      Replace the current content in your Link.php file with the following code:

      app/Model/Link.php

      <?php
      
      namespace AppModels;
      
      use IlluminateDatabaseEloquentModel;
      
      class Link extends Model
      {
          public function link_list()
          {
              return $this->belongsTo(LinkList::class);
          }
      }
      
      

      Save the file when you’re done.

      With both models updated, your database is now configured completely, but it is currently empty. In the next section of this series, you’ll learn how to insert new records in the database using Eloquent models.

      This tutorial is part of an ongoing weekly series about Laravel Eloquent. You can subscribe to the Laravel tag if you want to be notified when new tutorials are published.



      Source link

      How To Build a Responsive About Me Page with Laravel, Sail, and Tailwind CSS


      Introduction

      Laravel Sail is a Docker development environment included by default in Laravel since version 8. It allows you to quickly get a PHP development environment up and running, tailored for running Laravel applications with built-in support for NPM / Node.

      In this guide, you’ll bootstrap a new Laravel application with Laravel Sail and create a styled “about me” landing page using Tailwind CSS, a utility-first CSS framework designed for rapidly building custom user interfaces. At the end, you’ll have a base that you can use to further develop a Laravel application using Tailwind CSS for the front end and Sail for the development environment.

      Laravel Tailwind Responsive About Me Page

      If you’d prefer to follow along from an existing codebase rather than creating the project from scratch, you can access the finished demo application code at do-community/laravel-tailwind-starter on GitHub.

      Prerequisites

      Although the code shared in this guide should work seamlessly across multiple environments and systems, the instructions explained here were tested within an Ubuntu 20.04 local system running Docker and Docker Compose. Regardless of your base operating system, here’s what you’ll need to set up in order to get started:

      • Docker installed on your local machine. If you’re running Ubuntu 20.04, you can follow Steps 1 and 2 of How To Install and Use Docker on Ubuntu 20.04 to set it up. Windows and MacOS users need to install Docker Desktop instead.
      • Docker Compose installed on your local machine. Docker Compose comes included by default with Docker Desktop for both Windows and MacOS systems, but Linux users need to install the Compose executable, following Step 1 of How To Install and Use Docker Compose on Ubuntu 20.04.
      • A code editor for PHP (optional). A code editor helps making code easier to read and to format, and can improve your productivity by pointing out issues before you execute your code. You can follow our guide on How To Set Up Visual Studio Code for PHP Projects to set up VSCode, a free code editor, within your local development environment.

      Step 1 — Creating a New Laravel Application Using the Laravel Builder Script

      To get started, you’ll download and execute the official Laravel builder script, which will pull in the necessary Docker container images to build your development environment and then bootstrap a new application in your current folder. This installation method doesn’t require you to have PHP installed on your system, requiring only that you download and execute the builder script that will set up the Docker environment where you can run the actual Laravel installer.

      At the end, the script asks for your sudo password to make sure the application folder has correct permissions for your system user. You can access the script URL from your browser to verify its contents before running the next command. In this example, we’re using the name myapp, but you are free to replace this with a different name:

      curl -s https://laravel.build/myapp | bash
      

      Output

      Unable to find image 'laravelsail/php80-composer:latest' locally latest: Pulling from laravelsail/php80-composer 852e50cd189d: Pull complete 0266fc315b01: Pull complete … Application ready! Build something amazing. Sail scaffolding installed successfully. Please provide your password so we can make some final adjustments to your application's permissions. [sudo] password for sammy: Thank you! We hope you build something incredible. Dive in with: cd myapp && ./vendor/bin/sail up

      When the installation is finished, access the new application directory and get the Sail environment up with:

      • cd myapp
      • ./vendor/bin/sail up

      This will bring the environment up in foreground mode, so you can follow up with the logs from all running containers. You’ll see a few different services getting started, using different ports to communicate between each other:

      Output

      ... mailhog_1 | [HTTP] Binding to address: 0.0.0.0:8025 ... laravel.test_1 | Starting Laravel development server: http://0.0.0.0:80 ... meilisearch_1 | Server listening on: "http://0.0.0.0:7700" ... mysql_1 | 2021-06-23T01:15:24.327234Z 0 [System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections. Version: '8.0.25' socket: '/var/run/mysqld/mysqld.sock' port: 3306 MySQL Community Server - GPL. ... selenium_1 | 01:14:57.417 INFO [SeleniumServer.boot] - Selenium Server is up and running on port 4444 ... redis_1 | 1:M 23 Jun 2021 01:14:54.243 * Running mode=standalone, port=6379. …

      These are services configured by default within Sail environments. For more information about each of them, refer to the official Sail documentation.

      Next, access the application from your browser at:

      http://localhost
      

      If all steps were successful, you’ll see a page like this:
      Laravel welcome page

      The application is now bootstrapped.

      You can now stop the Sail environment that is running on your terminal by typing CTRL+C.

      Step 2 — Using Laravel Sail

      Laravel Sail offers several shortcuts to manage your development environment. Most commands and arguments are based on the default Docker Compose API.

      Controlling the Environment

      To bring the environment up in background mode, you can run:

      To stop a Sail environment that was previously initiated in background mode, run:

      This won’t delete attached networks or volumes.

      To bring back an environment that was previously stopped with a sail stop command, you can use:

      To stop an environment and also delete all associated resources such as volumes and networks, you can use the sail down command. Please notice that this command will delete any data that was previously created and is only available inside containers, such as records stored in a database.

      Output

      Stopping laravel-tailwind-starter_laravel.test_1 ... done Stopping laravel-tailwind-starter_redis_1 ... done Stopping laravel-tailwind-starter_selenium_1 ... done Stopping laravel-tailwind-starter_mysql_1 ... done Stopping laravel-tailwind-starter_mailhog_1 ... done Stopping laravel-tailwind-starter_meilisearch_1 ... done Removing laravel-tailwind-starter_laravel.test_1 ... done Removing laravel-tailwind-starter_redis_1 ... done Removing laravel-tailwind-starter_selenium_1 ... done Removing laravel-tailwind-starter_mysql_1 ... done Removing laravel-tailwind-starter_mailhog_1 ... done Removing laravel-tailwind-starter_meilisearch_1 ... done Removing network laravel-tailwind-starter_sail

      Checking Status and Logs

      If your environment is down, bring it back up with:

      When your environment is up and running, you can check the status of all active containers with:

      Output

      Name Command State Ports --------------------------------------------------------------------------------------------------------------------------------- myapp_laravel.test_1 start-container Up 0.0.0.0:80->80/tcp,:::80->80/tcp, 8000/tcp myapp_mailhog_1 MailHog Up 0.0.0.0:1025->1025/tcp,:::1025->1025/tcp, 0.0.0.0:8025->8025/tcp,:::8025->8025/tcp myapp_meilisearch_1 tini -- /bin/sh -c ./meili ... Up (healthy) 0.0.0.0:7700->7700/tcp,:::7700->7700/tcp myapp_mysql_1 docker-entrypoint.sh mysqld Up (healthy) 0.0.0.0:3306->3306/tcp,:::3306->3306/tcp, 33060/tcp myapp_redis_1 docker-entrypoint.sh redis ... Up (healthy) 0.0.0.0:6379->6379/tcp,:::6379->6379/tcp myapp_selenium_1 /opt/bin/entry_point.sh Up 4444/tcp

      The output from the sail ps command will tell you which containers related to that specific environment are currently active, which ports are being redirected, and more importantly, in which state each container is. In the previous example output, all services are up.

      To check the containers logs when you’re running your environment in background mode, you can use:

      This will show you the latest logs from all services.

      Attaching to laravel-tailwind-starter_laravel.test_1, laravel-tailwind-starter_mailhog_1, laravel-tailwind-starter_mysql_1, laravel-tailwind-starter_redis_1, laravel-tailwind-starter_selenium_1, laravel-tailwind-starter_meilisearch_1
      ...
      mysql_1         | 2021-06-24T15:08:06.435530Z 0 [System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections. Version: '8.0.25'  socket: '/var/run/mysqld/mysqld.sock'  port: 3306  MySQL Community Server - GPL.
      ...
      meilisearch_1   | [2021-06-24T15:16:38Z INFO  actix_web::middleware::logger] 127.0.0.1:60874 "GET /health HTTP/1.1" 200 22 "-" "Wget" 0.000056
      ...
      laravel.test_1  | [Thu Jun 24 15:08:07 2021] PHP 8.0.7 Development Server (http://0.0.0.0:80) started
      ...
      
      selenium_1      | 15:08:06.864 INFO [SeleniumServer.boot] - Selenium Server is up and running on port 4444
      ...
      redis_1         | 1:M 24 Jun 2021 15:08:05.280 * Ready to accept connections
      ...
      mailhog_1       | 2021/06/24 15:08:05 Serving under http://0.0.0.0:8025/
      

      You can also see logs per service by providing an additional argument to the command call:

      • ./vendor/bin/sail logs redis

      Output

      Attaching to laravel-tailwind-starter_redis_1 redis_1 | 1:C 24 Jun 2021 15:08:05.278 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo redis_1 | 1:C 24 Jun 2021 15:08:05.278 # Redis version=6.2.4, bits=64, commit=00000000, modified=0, pid=1, just started ... redis_1 | 1:M 24 Jun 2021 15:08:05.280 * RDB memory usage when created 0.77 Mb redis_1 | 1:M 24 Jun 2021 15:08:05.280 * DB loaded from disk: 0.000 seconds redis_1 | 1:M 24 Jun 2021 15:08:05.280 * Ready to accept connections

      Running Artisan and Composer

      While working on your Laravel application, you’ll often be required to run artisan commands to build, test, and manage your application. You’ll also need to run composer commands to manage your PHP dependencies. In addition to the default Docker Compose API, Sail offers helpful shortcuts to execute these commands in your application container (myapp_laravel.test_1 in the example output). With a regular Docker Compose setup, running Artisan would look like this:

      With Docker Compose Only

      docker-compose exec app php artisan
      

      With Sail, the equivalent call is shortened to:

      Running Artisan With Sail

      • ./vendor/bin/sail artisan

      You can run Composer in a similar way:

      Running Composer With Sail

      • ./vendor/bin/sail composer

      For more information about all features and commands available, please visit the official Laravel Sail Documentation.

      You’re now familiar with how to manage your Sail development environment and how to run commands on the application container. In the next step, you’ll set up Tailwind CSS to design and style your landing page.

      Step 3 — Setting Up Tailwind CSS with Laravel

      Next, you’ll install and set up Tailwind CSS to build a landing page.

      Make sure your Sail environment is up and running, then install Laravel’s front end dependencies with the npm command, which is used to download and manage JavaScript packages :

      • ./vendor/bin/sail npm install

      Output

      ... added 1327 packages, and audited 1328 packages in 20s 99 packages are looking for funding run `npm fund` for details ...

      Then, install Tailwind and its dependencies with:

      • ./vendor/bin/sail npm install -D tailwindcss@latest postcss@latest autoprefixer@latest

      Output

      ... added 9 packages, removed 22 packages, changed 7 packages, and audited 1315 packages in 5s 99 packages are looking for funding run `npm fund` for details ...

      Next, you’ll need to create a configuration file for Tailwind. To do that, you’ll use npx, which stands for Node package executer and allows you to execute a Node package. The following npx command will generate a new default Tailwind configuration for your application:

      • ./vendor/bin/sail npx tailwindcss init

      This will create a new configuration file named tailwind.config.js in your project’s root directory with the following content:

      tailwind.config.js

      module.exports = {
        purge: [],
        darkMode: false, // or 'media' or 'class'
        theme: {
          extend: {},
        },
        variants: {
          extend: {},
        },
        plugins: [],
      }
      

      Although there are different ways to set up Tailwind within a project, in this guide we’ll configure Tailwind with Laravel Mix and webpack. Both libraries are used to compile and output front end resources.

      Open the file webpack.mix.js using your code editor. It will look like this:

      mix.js('resources/js/app.js', 'public/js')
          .postCss('resources/css/app.css', 'public/css', [
              //
          ]);
      

      Laravel Mix uses PostCSS to compile CSS resources. Remove the // characters and include the following highlighted line, which will add Tailwind CSS in the list of CSS resources to process:

      Remove the // characters and include the following highlighted line, which requires Tailwind as a PostCSS plugin:

      webpack.mix.js

        mix.js("resources/js/app.js", "public/js")
          .postCss("resources/css/app.css", "public/css", [
           require("tailwindcss"),
          ]);
      

      Save the file after making this change.

      Next, include Tailwind within the application’s main CSS file. Open resources/css/app.css in your code editor and add the following 3 lines to this file:

      resources/css/app.css

      @tailwind base;
      @tailwind components;
      @tailwind utilities;
      

      Save when finished.

      Next, you’ll need to build the front end assets with NPM:

      • ./vendor/bin/sail npm run dev

      You will receive output that is similar to the following, with a line like the the highlighted Compiled Successfully portion that indicates you have integrated all of the components into your Sail environment:

      Output

      Laravel Mix v6.0.24 ✔ Compiled Successfully in 5515ms ┌───────────────────────────────────────────────────────────────────┬──────────┐ │ File │ Size │ ├───────────────────────────────────────────────────────────────────┼──────────┤ │ /js/app.js │ 597 KiB │ │ css/app.css │ 3.81 MiB │ └───────────────────────────────────────────────────────────────────┴──────────┘ webpack compiled successfully

      Tailwind is now configured and you have built the front end assets for your site.. In the next step, you’ll create a new landing page for your application.

      Step 4 — Creating a Landing Page

      With Tailwind’s configuration in place, you can now start building your application’s front end views. In Laravel, templates are typically stored in the resources/views directory. The page you saw before when opening the application from a browser (http://localhost) is defined in a single template called welcome.blade.php, in that directory.

      In your code editor, open a new file called index.blade.php in the resources/views directory.

      The following example template defines an “about me” HTML page with a few unstyled elements. It uses an example avatar image but you may replace it with an image of your own.

      Create a new img directory in the public application folder:

      Save your preferred image to this new directory, under the name profile_image.png.

      In the following example, notice the use of the highlighted {{ asset… }} helper lines to define paths for both the CSS and the image files. This function outputs the correct public path for application resources located in the public directory.

      Copy this content to your own index.blade.php:

      resources/views/index.blade.php

      <!doctype html>
      <html lang="en">
      <head>
          <meta charset="utf-8">
          <title>Sammy the Shark - About Page</title>
          <meta name="description" content="My Application Description">
          <meta name="author" content="Sammy">
          <meta name="viewport" content="width=device-width, initial-scale=1.0" />
          <link href="https://www.digitalocean.com/community/tutorials/{{ asset('css/app.css') }}" rel="stylesheet">
      </head>
      <body>
      <div>
          <img src="https://www.digitalocean.com/community/tutorials/{{ asset('img/profile_image.png') }}" width="200" alt="avatar"/>
          <h1>Sammy the Shark</h1>
          <p>Content Creator</p>
          <p>Hello, I'm Sammy. I am a friendly shark interested in Linux, coding, and community.
              You can find out more about me in the following links:</p>
          <div>
              <div><a href="https://twitter.com/digitalocean">Twitter</a></div>
              <div><a href="https://www.linkedin.com/company/digitalocean">LinkedIn</a></div>
              <div><a href="https://instagram.com/thedigitalocean">Instagram</a></div>
          </div>
      </div>
      </body>
      </html>
      

      Save the file when you’re finished editing its contents.

      Now edit the routes/web.php file to modify the main route so that it uses the newly created template. Open that file using your code editor, and replace welcome with index to change the view used by the main application endpoint. This is how the updated route declaration will look like once you’re finished:

      routes/web.php

      Route::get('/', function () {
          return view("https://www.digitalocean.com/community/tutorials/index');
      });
      

      Save the file. You can now reload the application page in your browser to see the new index page. You’ll see a page like this:
      Laravel about me page with tailwind - base template

      By default, Tailwind removes all styling from elements, which gives you freedom to build up your views by combining and mixing Tailwind CSS utility classes. In the next section, you’ll learn how to combine some of these utility classes in order to create a responsive “about me” page.

      Step 5 — Styling Your Landing Page with Tailwind CSS

      Building responsive pages is an important front end development requirement, since users may access your website or application from many different devices, each with different screen sizes.

      Tailwind offers selectors that are able to apply styles per screen size. This way, you can create responsive containers by setting up the smallest width as default, and appending the additional responsive sizes for bigger screens. For instance, an element set with class="w-3/4 lg:w-1/2" will set a default width of 3 quarters the width of the parent element, which will be valid for smaller screens, but for larger screens (lg: selector), it will use half the width of the parent element.

      Notice that you can combine the responsive selectors with any utility class, not only those associated with an element’s size. You can, for instance, hide an element at a certain breakpoint, change its colors, or even turn it into a grid with a variable number of columns.

      You can find all available responsive selectors and their equivalent breaking points at the official Tailwind documentation.

      The following template sets up a responsive content area at the center of the page, using background gradients and an example avatar image. For the buttons, it uses a grid flow system that will break the container into three columns starting at medium screens, but will make the buttons occupy the full container size when the page is accessed from smaller screens.

      Open the resources/views/index.blade.php file that you created in the previous step in your code editor and replace the contents with the following template:

      resources/views/index.blade.php

      <!doctype html>
      <html lang="en">
      <head>
          <meta charset="utf-8">
          <title>Sammy the Shark - About Page</title>
          <meta name="description" content="My Application Description">
          <meta name="author" content="Sammy">
          <meta name="viewport" content="width=device-width, initial-scale=1.0" />
          <link href="https://www.digitalocean.com/community/tutorials/{{ asset("css/app.css') }}" rel="stylesheet">
      </head>
      <body class="bg-gradient-to-r from-blue-400 via-purple-600 to-blue-700">
      
      <div class="w-3/4 lg:w-1/2 mx-auto rounded-md bg-gray-200 shadow-lg m-20 p-10 text-center">
          <img src="https://www.digitalocean.com/community/tutorials/{{ asset("img/profile_image.png') }}" class="w-32 lg:w-1/6 bg-blue-600 mx-auto rounded-lg mb-4" alt="avatar"/>
          <h1 class="text-3xl">Sammy the Shark</h1>
          <p class="text-gray-500 pb-4">Content Creator</p>
          <p class="text-gray-700 mb-6">Hello, I'm Sammy. I am a friendly shark interested in Linux, coding, and community.
              You can find out more about me in the following links:</p>
      
          <div class="grid grid-cols-1 md:grid-cols-3 grid-flow-row gap-6">
              <div class="px-4 py-2 bg-blue-600 text-gray-100 rounded-md mr-4 hover:bg-blue-700"><a href="https://twitter.com/digitalocean">Twitter</a></div>
              <div class="px-4 py-2 bg-blue-600 text-gray-100 rounded-md mr-4 hover:bg-blue-700"><a href="https://www.linkedin.com/company/digitalocean">LinkedIn</a></div>
              <div class="px-4 py-2 bg-blue-600 text-gray-100 rounded-md mr-4 hover:bg-blue-700"><a href="https://instagram.com/thedigitalocean">Instagram</a></div>
          </div>
      
      </div>
      </body>
      </html>
      

      This template will produce the following page:

      Final result - Laravel about me page with Tailwind

      And this is how the page adapts to different screen sizes:

      Laravel Tailwind Responsive About Me Page

      In the updated template, each HTML element has a number of Tailwind classes and selectors applied to them. Tailwind uses specific nomenclature for its utility classes to create responsive layouts. Each of the following is used in the example template to create the final result:

      • bg-gradient-to-r: creates a gradient from left to right, using the specified colors.
      • w-1/3: sets the width of the element to one third (1/3) of the parent’s element width. There are many different ways to set up an element’s width within Tailwind.
      • mx-auto: centers the element.
      • rounded-md: creates rounded corners, “medium” (md) in size.
      • shadow-lg: creates a shadow effect, “large” (lg) in size.
      • mr-* and other m variants: used to set up an element’s margins.
      • pb-* and other p variants: used to set up an element’s padding.
      • hover:bg-blue-700: changes the background color of the selected element on mouse hover.

      Check Tailwind’s official documentation for a complete reference of all available utility classes.

      Conclusion

      In this tutorial, you’ve bootstrapped a new Laravel application using Laravel Sail and Tailwind CSS. You also created a responsive “about me” landing page using Tailwind’s powerful utility classes.

      If you’d like to build a more complex landing page and learn more about Tailwind in the process, you can follow our guide on How To Build a Styled Landing Page with Tailwind CSS for detailed instructions on how to create a complete website page with this framework.

      If you’d like to learn more about Laravel in a project-based guide, you can refer to our How To Build a Links Landing Page in PHP with Laravel series. For more PHP content, check our PHP tag.





      Source link