Your first Laravel Project
Published: 2023-06-23 07:12:30

## What is Laravel?

Laravel is a PHP framework

---

## Creating a project
{% collapsible %}

Install the following to get started:

- IDE like Visual Studio Code
- PHP
- A terminal like Git Bash
- A database like mariaDB and/or a visual database manager like TablePlus
- npm (for JavaScript packages)
- composer

Open your terminal and move to where you want to make your project using the terminal command 'cd' followed by the route. And make a directory using 'mkdir', move into it with cd again.
```
cd Documents/WebDesign
mkdir LaravelProject
cd LaravelProject
```
In your terminal run the following command to make a new Laravel base project
```
composer create-project laravel/laravel .
```
You can now test if everything works by running the following command, and going to localhost:8000 in your browser.
```
php artisan serve
```
It works? Great! Moving on...
---
{% endcollapsible %}

## What is what?

If you followed the steps above you might open your project in VSCode or another IDE and start to get a little dizzy! Wow, so many folders and files!

### Routes
{% collapsible %}
Folder:**routes/web.php:**

This file contains all the **routes** your website can access. this can include pages, but also POST/GET/... requests to edit items.

There is a standard route included. **Routes** return **views** which are in essence pages.
```PHP
// 
Route::get('/', function () {
    return view('welcome');
});
```
In this piece of code:
 - the Method is 'get'
 - the endpoint is / ('localhost:8000/')
 - and when this page is requested the route will return a view 'welcome'.

Notes:
- If you want to see all the endpoints you can use the command:
```
php artisan route:list
```
- When creating routes you can **name** them using '**->name('name')**'
{% endcollapsible %}
### Views
{% collapsible %}
Folder:**resources/views**
As stated above, the route returns a view 'welcome'. But what does this mean?

Well in this folder you can spot the '_*.blade.php_' file. When calling a view, Laravel looks in this folder and finds the file with the same name. In this case 'welcome'. The PHP server processes this file and sends back HTML to the user.

Note:
- When returning a view you can pass **variables** using '**->with('name', $value**)'
{% endcollapsible %}

**_At this point you might want to try to create a new route and return a new view. Make the corresponding changes and say hello world!_**

### Controllers
{% collapsible %}
Folder:**app/http/controllers:**

There are a couple of commands that make your life easier in Laravel! they create the base files. (_wow!_)
```
php artisan make:controller ControllerName
```
if you want a full list of artisan make commands use this:
```
php artisan make:help
```
If you never worked with a mvc structure, don't worry.
A **controller** is the step between your **routes** and your **view**. It prepares the data needed. This is where you create functions like '_store_' to save data, '_show_' to return a view, or others to perfom some logic.

**_Lets create a controller using the artisan make: command and tinker with it!_**
```PHP
<?php
namespace App\Http\Controllers;
//MAKE SURE TO IMPORT CORRECTLY
use Illuminate\Contracts\View\View;
use Illuminate\Http\Request;

class TestController extends Controller
{
    function hello() : View {
        return view('hello');
    }
}
```
When you have a controller you're going to want to edit you **web.php** file to use the following syntax:
```PHP
//MAKE SURE TO IMPORT CORRECTLY
use App\Http\Controllers\TestController;

Route::get('/hello', [TestController::class, 'hello']);
```
You'll notice the only part that changed, is where a **function** used to be. now we call the **controller** followed by what function we want to call.
{% endcollapsible %}

### models
{% collapsible %}
Folder:**app/models:**
If you ever did some object oriented programming models will feel a bit familiar. You can create an instance of an existing **model**, link it to a **database** (we'll check it out right after this short intro!)

First lets create a new model with the folowing command:
```PHP
php artisan make:model ModelName
```
{% endcollapsible %}

### connecting to a database
{% collapsible %}
I will be using TablePlus.
First lets configure the .env file on the root level.
![Image DB connection in tablePlus](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cf61l26o1rvctli380um.png)
```env
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=DevArticle <- name of database you're gonna create
DB_USERNAME=root
DB_PASSWORD=super secret password
```
Great! Now just create a **new database** (ctrl+k & new in tablePlus) and next we're gonna set up **migrations** for your **model**.
Once migrations are done everything should be connected.
{% endcollapsible %}
### migrations
{% collapsible %}
Folder:**database/migrations:**
Migrations are pieces of code that generate (up) and destroy (down) tables in your database.
you can create a **migration** using the following command:
```
php artisan make:migration create_ModelName+s_table
```
Once you have your migration it should look like this:
```
    public function up(): void
    {
        Schema::create('modelName+s', function (Blueprint $table) {
            $table->id();
            $table->timestamps();
        });
    }
    public function down(): void
    {
        Schema::dropIfExists('modelName+s');
    }
```
You can add aditional **columns** by adding more tows to the up function.The syntax is the following $table->type('column_name'). For example `$table->text('last_name')` or `$table->integer('age')`
{% endcollapsible %}
### Shortcut!
{% collapsible %}
However when creating a **model** you normaly want a **controller** and **migration** to go along with it. This can be achieved with:
```
php artisan make:model ModelName -cm
```
{% endcollapsible %}

### Lets make something!
{% collapsible %}
1. Let's make a **model**, **migration** and **controller** for an object called '**_Car_**' and lets add some columns in your migration.
```
    public function up(): void
    {
        Schema::create('cars', function (Blueprint $table) {
            $table->id();
            $table->text('model');
            $table->text('make');
            $table->text('color');
            $table->timestamps();
        });
    }
```
In the code above, we create colums with type '_text_'. There are a lot of types, make sure to look up what type you need for your use case.

When you have edited the **migration** you can run the following command to create the corresponding tables:
```
php artisan migrate
```
2. Lets create two **endpoints** for a form, to create a new Car instance.
```
Route::get('/create',[CarController::class, 'form'])->name('createCar');
Route::post('/store',[CarController::class, 'store'])->name('storeCar');
```
```
use App\Models\Car;
use Illuminate\Contracts\View\View;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Redirect;
class CarController extends Controller
{
    function form() : View {
        return view('createCar');
    }
    function store(Request $request) : RedirectResponse {
        $car = new Car();
        $car->model = $request->input('model');
        $car->make = $request->input('make');
        $car->color = $request->input('color');
        $car->save();
        
        return Redirect::back();
    }
}
```
In the **store** function we create a new instance of the Car model. Then we add the properties using the $request->input('inputname') to access the submitted form data. Lastly we **save** and **redirect** back to the page we where just at.
Now just the views are left!

Lets create the **createCar.blade.php**, we'll want the basic html structure (_untill we get to layouts_), and add the following form.
```PHP
    <form action="{{route('storeCar')}}" method="post">
        @csrf
        <label>Model
        <input type="text" name='model' id='model'>
        </label>
        <label>Make
        <input type="text" name='make' id='make'>
        </label>
        <label>Color
        <input type="text" name='color' id='color'>
        </label>
        <button type="submit">Save</button>
    </form>
```
In **blade** files we can use the **@ directives** for a few things. One of them is **@csrf** which adds a layer of protection to forms.

If you implemented these changes you can go to **/create** and create a new instance of a car. Check your database after saving (make sure to refresh), and there should be a car present!

In the next part we will check out layout and component files. and we'll display the data we just saved.
{% endcollapsible %}
### Blade layouts
{% collapsible %}
While there are a lot of diffrent ways to display pages in Laravel (Inertia/Vue for example). The method it ships with is **blade files**. We've been using them so far like a simple PHP file. But they are so much more!

#### Directives
Directives always start with '@'. These are the ones you'll use most often:
** @extends('file') **
This is used for layout files.
** @include('component',['var' => "data",'var2' => "data"]) **
this is used for components you want to use multiple times that require data.
** @yield('sectionName') & @section('sectionName') @endsection **
You can use @yield in the layout file to indicate where to insert a section from another file.
The @section() @endsection is used to indicate what content is suposed to go where.

There are also directives that are used for logic. This means you no longer have to open and close php tags all the time! some examples include:
@if(), @elseif(), @else, @endif
@foreach(), @endforeach
@for(), @endfor
@while(), @endwhile

In forms we ALWAYS use @csrf, also optionally we can use @method() to change the way we submit (GET/POST/PUT/...)

#### Layout
Lets make a layout file. First in the views folder create a subfolder called layout. In this folder we create a file layout.blade.php
```php
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>@yield('title')</title>
</head>
<body>
    @yield('content')
</body>
</html>
```
and lets apply this layout file to all our views like this:
```php
@extends('layout.layout')
@section('title')
    Hello
@endsection
@section('content')
    <h1>Hello world!</h1>
@endsection
```
You can also add layout parts like header, footer, navigation, etc into the layout folder and @include() them.

Okay now lets create a blade file to show all cars. (add the necessary route and controller logic)
web.php
```php
Route::get('/cars', [CarController::class, 'show'])->name('showCars');
```
CarController.php
```php
    function show() : view {
        $cars = Car::all();
        return view('cars')
        ->with('cars',$cars);
    }
```
cars.blade.php
```php
@extends('layout.layout')
@section('title')
    Car Collection
@endsection
@section('content')
    <h1>Cars</h1>
    @if(!$cars->isEmpty())
        @foreach($cars as $car)
            <div>
                <h3>{{$car->make}}</h3>
                <p>{{$car->model}}</p>
                <p>{{$car->color}}</p>
            </div>
        @endforeach
    @else
        <h1>Add some cars first!</h1>
    @endif
@endsection
```
{% endcollapsible %}
### Extra
{% collapsible %}
#### packages
There are a ton of packages. These can add functionality to your project, or make coding easier.
The main two types are npm and composer. Npm uses node.js and composer is php oriented.

We'll start with a simple php debug bar.
(https://github.com/barryvdh/laravel-debugbar)
In your terminal use the following command:
```
composer require barryvdh/laravel-debugbar --dev
```
(this might take a few minutes depending on the package)
Using --dev makes sure the package is only used in development.

If you refresh, there should be a Laravel icon in the bottom left, click it for the debug bar!
_wow so easy!_

#### css
Folder:**resources/css/app.css**
In the head of the **layout** file you can add the following line:
```
@vite("resources/css/app.css")
```
Now we will need to open a second **terminal** and navigate to the root of your project again. Here we want to run the following commands:
```
npm install
npm run dev
```
Make sure your final css is compiled into the app.css file and your good to go!
#### slugs
Slugs are pieces in your **url** that signify a **value** like an id or name. in your **web.php** file you determine where the slugs are expected:
```php
Route::get('/car/{id}', [CarController::class, 'showCar'])->name('showCar');
```
Then you can use it in your **controller** like this:
```php
    function showCar($id) : view {
        $car = Car::find($id);
        return view('car')
        ->with('car',$car);
    }
```
{% endcollapsible %}

If you followed all the steps you are set up and ready for a real project!