How To Update Database Records in Laravel Eloquent

In a previous section of this series, you updated an existing Artisan command in order to support the new lists feature. Although there are commands to insert and delete links, the demo application currently doesn’t have a command to edit existing links. This can be useful to move links between lists, for instance, or update […]

In a previous section of this series, you updated an existing Artisan command in order to support the new lists feature. Although there are commands to insert and delete links, the demo application currently doesn’t have a command to edit existing links. This can be useful to move links between lists, for instance, or update a link description.

In this guide, you’ll create a new Artisan command to update existing links in the database.

From your terminal, first make sure you’re in your project’s root directory, then run the following to bootstrap a new Artisan command:

  • docker-compose exec app php artisan make:command LinkUpdate

This will create a new LinkUpdate.php file located at app/Console/Commands. Open the file in your code editor of choice:

app/Console/Commands/LinkUpdate.php

This file contains boilerplate code for a new Artisan command. You’ll update it to handle editing a link provided its unique id. This is what your handle() method needs to do:

  • Obtain an id provided by the user and check for the existence of a link with a matching id in the database.
  • If a valid link cannot be found, show an error message and exit.
  • If a valid link is found, prompt the user to provide updated values for the link description and link list.
  • Ask the user to confirm changes.
  • When confirmed, update the item in the database.

Start by including a couple use definitions at the top of the file, to facilitate referencing to the Link and LinkList classes later on:

app/Console/Commands/LinkUpdate.php
<?php

namespace AppConsoleCommands;

use AppModelsLink;
use AppModelsLinkList;
use IlluminateConsoleCommand;

...

To obtain the link id, you should set up a mandatory argument in the new link:update command, so that users are required to provide that parameter at run time. Locate the command signature definition at the top of the file and replace it with the highlighted line:

app/Console/Commands/LinkUpdate.php
...

class LinkUpdate extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'link:update {link_id}';
...

If you save the file and try to run the command now without an additional argument, you’ll get an error:

  • docker-compose exec app php artisan link:update
Output
Not enough arguments (missing: "link_id").

In the handle() method, you need to obtain the link id provided by the user and locate it in the database. This can be done with the argument() method that is provided through the parent Command class. Then, you can use the find() Eloquent method to query the database for a link with that id. If the find() method returns null, it means no link with that id was found, so the program should exit in error.

app/Console/Commands/LinkUpdate.php
...
   /**
     * Execute the console command.
     *
     * @return int
     */
    public function handle()
    {
        $link_id = $this->argument('link_id');
        $link = Link::find($link_id);

        if ($link === null) {
            $this->error("Invalid or non-existent link ID.");
            return 1;
        }

        // obtain updated information from user
    }
...

When a valid link is found, you need to prompt the user for the updated link information.You can do so using the ask method, highlighted in the next example:

app/Console/Commands/LinkUpdate.php: function handle()
...
        if ($link === null) {
            $this->error("Invalid or non-existent link ID.");
            return 1;
        }

        $link->description = $this->ask('Link Description (ENTER to keep current)') ?? $link->description;
        $list_name = $this->ask('Link List (ENTER to keep current)') ?? $link->link_list->title;
...

This code will prompt the user for an updated description and list, while keeping the current values as default in case a user doesn’t provide new ones, pressing ENTER to skip the prompt.

Once you have all this information, you can proceed to the update. It’s a good idea to use the confirm() method to have the user confirm the changes before you run the database update. This is how such code would look:

app/Console/Commands/LinkUpdate.php: function handle()
...
        $link->description = $this->ask('Link Description (ENTER to keep current)') ?? $link->description;
        $list_name = $this->ask('Link List (ENTER to keep current)') ?? $link->link_list->title;

        $this->info("Description: $link->description");
        $this->info("Listed in: " . $list_name);

        if ($this->confirm('Is this information correct?')) {
            //code that updates the link
        }
...

Inside the if block, you have to start by checking if the requested list exists, otherwise create a new list with the provided name. Then, you’ll use the associate() method to update the relationship between this link and its “parent” list. The save() method, finally, will persist the changes to the database:

app/Console/Commands/LinkUpdate.php: function handle()
...
        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->link_list()->associate($list)->save();
            $this->info("Updated.");
        }
...

This is the complete LinkUpdate.php file for your reference:

app/Console/Commands/LinkUpdate.php
<?php

namespace AppConsoleCommands;

use AppModelsLink;
use AppModelsLinkList;
use IlluminateConsoleCommand;

class LinkUpdate extends Command
{
    /**
     * The name and signature of the console command.
     *
     * @var string
     */
    protected $signature = 'link:update {link_id}';

    /**
     * The console command description.
     *
     * @var string
     */
    protected $description = 'Update a link in the database';

    /**
     * Create a new command instance.
     *
     * @return void
     */
    public function __construct()
    {
        parent::__construct();
    }

    /**
     * Execute the console command.
     *
     * @return int
     */
    public function handle()
    {
        $link_id = $this->argument('link_id');
        $link = Link::find($link_id);

        if ($link === null) {
            $this->error("Invalid or non-existent link ID.");
            return 1;
        }

        $link->description = $this->ask('Link Description (ENTER to keep current)') ?? $link->description;
        $list_name = $this->ask('Link List (ENTER to keep current)') ?? $link->link_list->title;

        $this->info("Description: $link->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->link_list()->associate($list)->save();
            $this->info("Updated.");
        }

        return 0;
    }
}

Note: For more detailed information on Artisan commands, check our guide on How To Create Artisan Commands to Manage Database Records in Laravel, which is part of our introductory Laravel series.

Save the file when you’re finished. Then, use the link:show command to obtain all links and its respective IDs:

  • docker-compose exec app php artisan link:show
Output
+----+-------------------------------------------------+--------------+----------------------------------+ | id | url | list | description | +----+-------------------------------------------------+--------------+----------------------------------+ | 1 | https://digitalocean.com/community | default | DO Community | | 2 | https://digitalocean.com/community/tags/laravel | default | Laravel Tutorias at DigitalOcean | | 3 | https://digitalocean.com/community/tags/php | default | PHP Tutorials at DigitalOcean | | 4 | https://twitter.com/digitalocean | social | Twitter | | 5 | https://dev.to/digitalocean | social | DEV.to | | 6 | https://laravel.com/docs/8.x/eloquent | default | Laravel Eloquent Docs | +----+-------------------------------------------------+--------------+----------------------------------+

Then, choose an item to edit. For instance, you may want to create a digitalocean list for the links that point to the DigitalOcean website (that would correspond to items with IDs 1, 2, and 3 in the previous example output).

To update the link with ID 1, run:

  • docker-compose exec app php artisan link:update 1
Output
Link Description (ENTER to keep current): > DO Community Link List (ENTER to keep current): > digitalocean Description: DO Community Listed in: digitalocean Is this information correct? (yes/no) [no]: > y Updated.

Then, run the link:show command again to see the updated information:

Output
+----+-------------------------------------------------+--------------+----------------------------------+ | id | url | list | description | +----+-------------------------------------------------+--------------+----------------------------------+ | 1 | https://digitalocean.com/community | digitalocean | DO Community | | 2 | https://digitalocean.com/community/tags/laravel | digitalocean | Laravel Tutorias at DigitalOcean | | 3 | https://digitalocean.com/community/tags/php | digitalocean | PHP Tutorials at DigitalOcean | | 4 | https://twitter.com/digitalocean | social | Twitter | | 5 | https://dev.to/digitalocean | social | DEV.to | | 6 | https://laravel.com/docs/8.x/eloquent | default | Laravel Eloquent Docs | +----+-------------------------------------------------+--------------+----------------------------------+

In this guide, you learned how to update database records with Laravel Eloquent. You have upgraded the demo application to include a new command that allows users to edit existing links in the database.

In the next and final part of this series, you’ll create a new command to delete a list of links.

Source: DigitalOcean