Laravel and Vue: Creating a Portfolio website with a CRUD

Recap: In order to create and display the profile, we posted a form to the create route.

Now — :

Can we create an update form and post it to an update route? Yeah but …

Do we have to? NO

There is a more efficient way of updating the profile data. We can keep and use the same form for create and update functions. We have to make changes to the controller functions.

We need to change the post profile route in Api.php to run the store() function of ProfileController instead of the create() function.

R̶o̶u̶t̶e̶:̶:̶p̶o̶s̶t̶(̶'̶/̶p̶r̶o̶f̶i̶l̶e̶'̶,̶ ̶'̶P̶r̶o̶f̶i̶l̶e̶C̶o̶n̶t̶r̶o̶l̶l̶e̶r̶@̶c̶r̶e̶a̶t̶e̶'̶)̶;̶
Route::post('/profile', 'ProfileController@store');

Building the store function

What we want from the store() function:

  1. Check whether we have any data in the database or not.
  2. If we don’t have any data in the database, enter the formdata into the database.
  3. If we do have data already, change the data in the database.

1. Let’s check whether we have any profile data

Here we have to collect an array of data. Profile::all() collects all the data from the Profile model (App\Profile.php) and you can check whether this collection of data is empty by using **isEmpty()** .

Profile::all()->isEmpty() is needed here; however, you can also shorten Profile::all() to $profile and then use **$profile->isEmpty()**.

public function store(Request $request)
{
    $profile = Profile::all();
    if ($profile->isEmpty()) {
        return 'profile is empty';
    } else {
        return 'profile is not empty';
    }
}

Status 200 — If you empty the table, posting to the route will get you this:

This is image title

Status 500:— With regards to getting the profile data, if you empty the table, you won’t have any data to render and thus get a 500 error in the network tab with:

message: Undefined offset: 0

You’ll get the same error if you visit the api/profile route.

This is image title

This error is there because we don’t have any data in the Profile table which means Profile::all() will produce an empty array [].

And if Profile::all() will produce an empty array, then there will definitely be no data at **Profile:all[0].**

2. If we don’t have any data in the database, enter the formdata into the database.

We can simply copy the code from the create function

This is image title

public function store(Request $request)
{
    $profile = Profile::all();
    if ($profile->isEmpty()) {
        $profile = new Profile();
        $profile->name = request()->name;
        $profile->img_path = request()->file('userpic')->hashName();
        $profile->save();
        return request()->file('userpic')->store('/public/userpics');
    } else {
        return 'profile is not empty';
    }
}

While this will work, the code is hard to look at.

This is image title

If you have to do this to your eyes, you need to do something called refactoring. It will lessen your eyestrain.

REFACTORING

Refactoring is when you change what the code looks like but it has the same effects.

We can run the create() function using **$this->create()**

public function store(Request $request)
{
    $profile = Profile::all();
    if ($profile->isEmpty()) {
        $this->create();
    } else {
        return 'profile is not empty';
    }
}

Code Explanation:
$this points to things within the same controller.
create() is the create function (we created in Chapter Three).

Now the store() function will run the create() function if there’s no data in profile::all().

TEST: Truncate the table, fill in the name field, select a file and click the submit button. If you see a 200 in the network tab, the refactored store method is working.

3. If we do have data already, change the data in the database.

Point to the update() function in else {}

public function store(Request $request)
{
    $profile = Profile::all();
    if ($profile->isEmpty()) {
        $this->create();
    } else {
        $this->update();
    }
}

To use the update function, we have to simply re-post the form and have our data inserted.

Since we are simply re-posting the form, we can use the same code as the one in the create function for the update function with one exception.

The exception is that the create() code begin with $profile = new Profile() while the update() code begins with **Profile::findOrFail(1)**

**findOrFail(1);** finds the database table record with the id of 1. The next lines of code will set data to that particular row.

**findOrFail(2);** would find the database table record with the id of 2 and so on with other numbers.

We want to change the row with the id of 1 because that’s the data of that row appears on the website.

public function update(Request $request, $id)
{
    $profile = Profile::findOrFail(1);
    $profile->name = request()->name;
    $profile->img_path = request()->file('userpic')->hashName();
    $profile->save();
    return request()->file('userpic')->store('/public/userpics');
}

Posting the form now will get you a 500 Status in the network tab with the following message:

message: Too few arguments to function App\Http\Controllers\ProfileController::update(), 0 passed in … and exactly 2 expected

Let’s examine the top of the function 🔎

public function update(Request $request, $id)

Within the (), it says **Request $request, $id** .

These are the 2 arguments, the 500 message is talking about.

Error explanation: If a function has $variables in between the () brackets, there is an expectation that when the code runs, it will be holding the $variables/arguments. Human translation:

public function speak($aStick) means SPEAK WHILE HOLDING A STICK

BUT

public function speak() just means SPEAK

A human cannot SPEAK WHILE HOLDING A STICK unless someone passes them a stick.

Just like that, **public function update(Request $request, $id)**cannot work until $request and $id are passed to it.

PASSING ARGUMENTS

If you look at the the store() function, you can see that it runs while holding $request. So you can simply pass $request to the update function by writing $request inside the brackets

public function store(Request $request)
{
    $profile = Profile::all();
    if ($profile->isEmpty()) {
        $this->create();
    } else {
        $this->update($request);
    }
}

Now you’ll get a 500 status with a similar message. This message will say something like

1 passed and exactly 2 expected

The other argument is $id. This we can simply just declare $id within else{}like so:

	public function store(Request $request)
{
    $profile = Profile::all();
    if ($profile->isEmpty()) {
        $this->create();
    } else {
        $id = 1;
        $this->update($request, $id);
    }
}

Fill in the form, click submit and the network tab will give you Status 200.

Refresh the page and you’ll see the changes you made using the form.

Our current refactored code is working 👍 😃 which means our Store() function is working 👍 😄

HOWEVER, the last 4 lines of the create() function and the update() function are the same. If this is an issue for you, you need refactor more.

MORE REFACTORING

The last 4 lines of both functions do the same things with **$profile** therefore we should pass $profile from both of these functions to a new function that contains the four lines.

Let’s make a function called insertData that accepts $profile as an argument.

	public function create()
{
    $profile = new Profile();
    $this->insertData($profile);
}
public function update(Request $request, $id)
{
    $profile = Profile::findOrFail(1);
    $this->insertData($profile);
}

public function insertData($profile) {
    $profile->name = request()->name;
    $profile->img_path = request()->file('userpic')->hashName();
    $profile->save();
    return request()->file('userpic')->store('/public/userpics');
}

You can test the update function by posting the form and reloading the page.

The create() function can be tested by first truncating the table and then posting and reloading.

Now we are using 3 functions in total when we want to create or update:

  • To create, we have to go through store(), create() and insertData()
  • To update, we have to go through store(), update() and insertData()

If you wish to eliminate the middle man, you can refactor a third time.

ELIMINATING THE MIDDLE FUNCTION

If you feel that the middle functions are too short to deserve existence, you can delete the lines that call for those functions to be run and simply copy and paste the inner code like so:

public function store(Request $request)
{
    $profile = Profile::all();
    if ($profile->isEmpty()) {
        $̶t̶h̶i̶s̶-̶>̶c̶r̶e̶a̶t̶e̶(̶)̶;̶
        $profile = new Profile();
        $this->insertData($profile);
    } else {
        $̶i̶d̶ ̶=̶ ̶1̶;̶
        $̶t̶h̶i̶s̶-̶>̶u̶p̶d̶a̶t̶e̶(̶$̶r̶e̶q̶u̶e̶s̶t̶,̶ ̶$̶i̶d̶)̶;̶
        $profile = Profile::findOrFail(1);
        $this->insertData($profile);
    }
}

The create() and update() functions are no longer required.

  • You can use the create functionality of CRUD without the create() function.

AND

  • You can use the update functionality of CRUD without the update() function.
public function store(Request $request)
{
    $profile = Profile::all();
    if ($profile->isEmpty()) {
        $profile = new Profile();
        $this->insertData($profile);
    } else {
        $profile = Profile::findOrFail(1);
        $this->insertData($profile);
    }
}

You can set the meaning of the $variables within the brackets () therefore more refactoring can be done like this:

public function store(Request $request)
{
    $profile = Profile::all();
    if ($profile->isEmpty()) {
        $this->insertData($profile = new Profile());
    } else {
        $this->insertData($profile = Profile::findOrFail(1));
    }
}

Remember to remove the semicolon at the end when you cut and paste

With all this refactoring, we have gone from potentially using $profile 10 times in the store() function to 4 times.

In the next chapter, we’ll be looking at form validation.

#php #laravel #vue #vuejs

Laravel and Vue: Creating a Portfolio website with a CRUD
1 Likes63.75 GEEK