IDE, Integrated Development Environments

Assignments Laravel II

Assignment Lara.2.0

I found a tutorial for you to help understand where databases enter into the Laravel world: Creating a Basic Laravel 5 MVC Application in 10 Minutes. This assignment consists of finishing the code, so that there's something to show.

Before starting the tutorial, you must navigate you terminal application to your project folder [htdocs]. Here you do

laravel new cars
cd cars

Create a database with the same name as the project. In casu cars. Assign all permissions for that database to a named user using his password. This creates such a user:

grant all privileges on cars.* to nobody@localhost identified by 'test';

Now you must deal with the following anomalies, first point. Why they still exist is not easy to say, but …

  • In app/Providers/AppServiceProvider.php we must add a line
    use Illuminate\Support\Facades\Schema;

    after the other use statement.

    In the function boot place the statement:

    Schema::defaultStringLength(191);
  • The file .env must be updated with the database name and the user, nobody whom the application impersonates. These are the database parameters.
  • The artisan command in the beginning of the tutorial will give you the file <timestamp>_create_cars_table.php in the migrations folder database/migrations. The tutorial will make you work on that.
  • The routes go into routes/web.php as you might remember from the previous lesson.
Assignment Lara.2.0 Model Solution

The solution from my hand may be cloned from https://github.com/neinalways/cars.git.

Figure B.7. The Screen from the Tutorial
The Screen from the Tutorial

The answer to what puzzles you :) or rather what should puzzle you.

    public function show($id) {
        $car = Car::find($id);                          // nml
        return view('cars.show', array('car' => $car)); // nml
    }

You have been looking for the find() method in the Car class, but without finding it. It isn't there. You can see that Car inherits from Model. Now the model knows cars and therefore has been capable of creating a proper find() to reflect the actual cars table in the database, and the view depends on that by using the actual column names from that table.

Your laravel turorials indicate that you may test by starting the laravel built in web server by issuing the following CLI command from the project root directory:

php artisan serve

And consequently issuing the following URL in your browser

http://localhost:8000/cars/1

The web server may be stopped by issuing Ctrl-C from the keyboard in the CLI where it was started. The response is a command prompt.

Alternatively you may use your XAMPP Apache server to test by issuing the following URL:

http://localhost/cars/public/index.php/cars/1

The cars/1 at the right hand end of the URL is the route, the left cars in the latter is the project name. The first method doesn't need that because the web server is started within that application.

Laravel / JavaScript project Uge 8/2019

Laravel Uge88 First Steps

What follows is NOT a solution, but rather some fragments explored so that they could be useful for other projects as well.

Getting Started
cd [htdocs]
laravel new uge88
cd uge88
composer install
Create the Database
In mysql, from the command line do
create database uge88;
grant all privileges on uge88.* to nobody@localhost identified by 'test';
Edit the Database Params
Find the hidden file .env and locate the database access params from keywords, and edit to
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=uge88
DB_USERNAME=nobody
DB_PASSWORD=test

Invoke Laravel Authentication

Authentication
This you get for free from Laravel. Just do
php artisan make:auth
from your command line. This uses several views and controllers that were aleready in place. It also update the routes.

Models and Migration Files

Figure B.8. Project ER Model

The Model(s) and Migration
Create models and migration files corresponding to what your ER diagram tells you:
php artisan make:model -m Klasse
php artisan make:model -m Rekvirent
php artisan make:model -m Reserverer
php artisan make:model -m Lokale
Update app/Klasse.php (one example model)
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Klasse extends Model {
    public $timestamps = false;     // dumps timestamps from table
    public $incrementing = false;   // if no autoincrementing
    protected $table = 'klasse';    // change default snake-case name
    protected $keyType = 'string';  // if key is not integer

    protected $fillable = [
        'klassebetegnelse',
    ];
}
Update database/migrations/2019_02_22_142108_create_klasses_table.php
<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateKlassesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('klasse', function (Blueprint $table) {
            $table->string('klassebetegnelse', 16)->primary();
            $table->foreign('klassebetegnelse')->references('rekvirent')->on('rekvirent');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down() {
        Schema::dropIfExists('klasse');
    }
}
Update app/User.php (another example model)
<?php

namespace App;

use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable
{
    use Notifiable;

    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable = [
        'initialer', 'name', 'email', 'password',
    ];

    /**
     * The attributes that should be hidden for arrays.
     *
     * @var array
     */
    protected $hidden = [
        'password', 'remember_token',
    ];

    /**
     * The attributes that should be cast to native types.
     *
     * @var array
     */
    protected $casts = [
        'email_verified_at' => 'datetime',
    ];

    public function rekvirent() {
        return $this->belongsTo('App\Rekvirent');
    }

}
Update database/migrations/2014_10_12_000000_create_users_table.php
<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateUsersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('users', function (Blueprint $table) {
            $table->increments('id');
            $table->string('initialer',16)->unique();
            $table->foreign('initialer')->references('rekvirent')->on('rekvirent');
            $table->enum('profil', array('admin', 'regular'))->default('regular');
            $table->string('name', 40);
            $table->string('email', 64)->unique();
            $table->timestamp('email_verified_at')->nullable();
            $table->binary('password');
            $table->rememberToken();
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('users');
    }
}

Routing

Routing
Routing is done with routes/web.php. Edit that to show
<?php
Route::get('/', function() {
    return view('welcome');
});

Route::auth();
Route::get('/home', 'HomeController@index');

Route::resource('klasse', 'KlasseController');
Route::resource('lokale', 'LokaleController');
Route::resource('reserverer', 'ReservererController');
Route::resource('display', 'DisplayController');
Route::resource('display', 'DisplayController');

User, View and Controller, Register Form

User Form View
The user form is augmented to include local adaptations re the ER diagram
@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <div class="card">
                <div class="card-header">{{ __('Register') }}</div>

                <div class="card-body">
                    <form method="POST" action="{{ route('register') }}">
                        @csrf

                        <div class="form-group row">
                            <label for="initialer" class="col-md-4 col-form-label text-md-right">{{ __('Initialer') }}</label>

                            <div class="col-md-6">
                                <input id="initialer" type="text" class="form-control{{ $errors->has('initialer') ? ' is-invalid' : '' }}" name="initialer" value="{{ old('initialer') }}" required autofocus>

                                @if ($errors->has('initialer'))
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $errors->first('initialer') }}</strong>
                                    </span>
                                @endif
                            </div>
                        </div>

                        <div class="form-group row">
                            <label for="name" class="col-md-4 col-form-label text-md-right">{{ __('Name') }}</label>

                            <div class="col-md-6">
                                <input id="name" type="text" class="form-control{{ $errors->has('name') ? ' is-invalid' : '' }}" name="name" value="{{ old('name') }}" required autofocus>

                                @if ($errors->has('name'))
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $errors->first('name') }}</strong>
                                    </span>
                                @endif
                            </div>
                        </div>

                        <div class="form-group row">
                            <label for="email" class="col-md-4 col-form-label text-md-right">{{ __('E-Mail Address') }}</label>

                            <div class="col-md-6">
                                <input id="email" type="email" class="form-control{{ $errors->has('email') ? ' is-invalid' : '' }}" name="email" value="{{ old('email') }}" required>

                                @if ($errors->has('email'))
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $errors->first('email') }}</strong>
                                    </span>
                                @endif
                            </div>
                        </div>

                        <div class="form-group row">
                            <label for="password" class="col-md-4 col-form-label text-md-right">{{ __('Password') }}</label>

                            <div class="col-md-6">
                                <input id="password" type="password" class="form-control{{ $errors->has('password') ? ' is-invalid' : '' }}" name="password" required>

                                @if ($errors->has('password'))
                                    <span class="invalid-feedback" role="alert">
                                        <strong>{{ $errors->first('password') }}</strong>
                                    </span>
                                @endif
                            </div>
                        </div>

                        <div class="form-group row">
                            <label for="password-confirm" class="col-md-4 col-form-label text-md-right">{{ __('Confirm Password') }}</label>

                            <div class="col-md-6">
                                <input id="password-confirm" type="password" class="form-control" name="password_confirmation" required>
                            </div>
                        </div>

                        <div class="form-group row mb-0">
                            <div class="col-md-6 offset-md-4">
                                <button type="submit" class="btn btn-primary">
                                    {{ __('Register') }}
                                </button>
                            </div>
                        </div>
                    </form>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection
After User Form View, Change app/Http/Controllers/Auth/registerController.php
<?php

namespace App\Http\Controllers\Auth;

use App\User;
use App\Rekvirent;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use Illuminate\Foundation\Auth\RegistersUsers;

class RegisterController extends Controller
{
    /*
    |--------------------------------------------------------------------------
    | Register Controller
    |--------------------------------------------------------------------------
    |
    | This controller handles the registration of new users as well as their
    | validation and creation. By default this controller uses a trait to
    | provide this functionality without requiring any additional code.
    |
    */

    use RegistersUsers;

    /**
     * Where to redirect users after registration.
     *
     * @var string
     */
    protected $redirectTo = '/home';

    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('guest');
    }

    /**
     * Get a validator for an incoming registration request.
     *
     * @param  array  $data
     * @return \Illuminate\Contracts\Validation\Validator
     */
    protected function validator(array $data)
    {
        return Validator::make($data, [
            'initialer' => ['required', 'string', 'max:16', 'unique:users'],
            'name' => ['required', 'string', 'max:40'],
            'email' => ['required', 'string', 'email', 'max:64', 'unique:users'],
            'password' => ['required', 'string', 'min:8', 'confirmed'],
        ]);
    }

    /**
     * Create a new user instance after a valid registration.
     *
     * @param  array  $data
     * @return \App\User
     */
    protected function create(array $data) {

        Rekvirent::create([
            'rekvirent' => $data['initialer'],
        ]);

        return User::create([
            'initialer' => $data['initialer'],
            'name' => $data['name'],
            'email' => $data['email'],
            'password' => Hash::make($data['password']),
        ]);
    }
}
Post Login Path
<?php

namespace App\Http\Controllers\Auth;

use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\AuthenticatesUsers;

class LoginController extends Controller
{
    /*
    |--------------------------------------------------------------------------
    | Login Controller
    |--------------------------------------------------------------------------
    |
    | This controller handles authenticating users for the application and
    | redirecting them to your home screen. The controller uses a trait
    | to conveniently provide its functionality to your applications.
    |
    */

    use AuthenticatesUsers;

    /**
     * Where to redirect users after login.
     *
     * @var string
     */
    protected $redirectTo = '/';

    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('guest')->except('logout');
    }
}

Views and Controllers, Example 1

Controllers are created with

php artisan make:controller KlasseController --resource
A Controller

edit to

<?php

namespace App\Http\Controllers;

use App\Klasse;
use App\Rekvirent;
use Illuminate\Http\Request;
use Redirect;

class KlasseController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        return view('klasser.list', Klasse::all());
    }
    
    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        return view('klasse.create');
    }
   
    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        $request->validate([
            'klassebetegnelse' => ['required', 'string', 'max:16', 'unique:klasse'],
        ]);

        Rekvirent::create([
            'rekvirent' => $request['klassebetegnelse'],
        ]);
   
        Klasse::create($request->all());
    
        return Redirect::to('klasse')
       ->with('success','Great! Klasse created successfully.');
    }
    
    /**
     * Display the specified resource.
     *
     * @param  \App\Product  $product
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {
    }
    
    /**
     * Show the form for editing the specified resource.
     *
     * @param  \App\Product  $product
     * @return \Illuminate\Http\Response
     */
    public function edit($id)
    {   
    }
   
    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \App\Product  $product
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, $id)
    {
    }
   
    /**
     * Remove the specified resource from storage.
     *
     * @param  \App\Product  $product
     * @return \Illuminate\Http\Response
     */
    public function destroy($id)
    {
    }
}
Its Corresponding View

edit to

@extends('layouts.nLayout')

@section('content')
    <div class='fl'>
        <h2>Eksisterende klasser</h2>
        <table>
            @foreach (App\Klasse::all() as $klasse)
                <tr><td>{{ $klasse->klassebetegnelse }}</td></tr>
            @endforeach
        </table>
    </div>
    <form method="post" action="{{ route('klasse.store') }}">
    <div class='fl'>
        @csrf
        <h2>Indtast ny klasse</h2>
        <table>
            <tr>
                <td>
                    <label for="klasse">{{ __('Klassebetegnelse') }}</label>
                </td>
                <td>
                    <input id="klasse" type="text" class="form-control{{ $errors->has('klasse') ? ' is-invalid' : '' }}" name="klassebetegnelse" value="{{ old('klasse') }}" required autofocus>

                    @if ($errors->has('klasse'))
                        <span class="invalid-feedback" role="alert">
                            <strong>{{ $errors->first('klasse') }}</strong>
                        </span>
                    @endif
                </td>
            </tr>
            <tr>
                <td></td>
                <td>
                    <button type="submit">{{ __('Registrer') }}</button>
                </td>
            </tr>
        </table>
    </div>
    </form>
    <div class='cl'></div>
@endsection

Views and Controllers, Example reserverer

This time the reserverer. Created with

php artisan make:controller ReservererController --resource
ReservererController

edit to

<?php

namespace App\Http\Controllers;

use App\Reserverer;
use Illuminate\Http\Request;
use Redirect;

class ReservererController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        return view('reserverer.create');
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        return view('reserverer.create');
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */
    public function store(Request $request)
    {
        $request->validate([
            'lokale' => ['required', 'int'],
            'datotid' => ['required', 'string'],
            'rekvirent' => ['required', 'string', 'max:16'],
            'reserverettil' => ['required', 'string', 'max:32'],
        ]);
   
        Reserverer::create($request->all());
    
        return Redirect::to('reserverer')
       ->with('success','Great! Reservation created successfully.');
    }

    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {
        //
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function edit($id)
    {
        //
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, $id)
    {
        //
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function destroy($id)
    {
        //
    }
}
Its Corresponding View

edit to

@extends('layouts.nLayout')

@section('content')
    <form method="post" name='reservation' action="{{ route('reserverer.store') }}">
    @csrf
    <div class='fl'>
        <h2>Vælg lokale</h2>
        <select name='lokale'>
            @foreach (App\Lokale::all() as $lokale)
                <option value='{{ $lokale->lokaleid }}'>{{ $lokale->lokaleid }}, {{ round(($lokale->lengthincms * $lokale->widthincms / 10000), 1) }} m<sup>2</sup></option>
            @endforeach
        </select>
    </div>
    <div class='fl'>
        <h2>Vælg rekvirent</h2>
        <select name='rekvirent'>
            @foreach (App\Rekvirent::all() as $rekv)
                <option>{{ $rekv->rekvirent }}</option>
            @endforeach
        </select>
    </div>
    <div class='fl'>
        <h2>Dato?</h2>
        <input type='date' id='dato' placeholder='dato'/>
    </div>
    <div class='fl'>
        <h2>Tid?</h2>
        <select id='tid'>
        @for ($i = 8; $i < 18; $i++)
            <option>{{ $i }}:00:00</option>
        @endfor
        </select>
        <input name='datotid' id='datotid' type='text' required readonly/>
    </div>
    <div class='fl'>
        <h2>Reserveret til</h2>
        <input type='text' name='reserverettil' placeholder='fagnavn eller møde'/>
    </div>
    <div class='fl'>
        <p>&nbsp;</p>
        <button type="submit" id='reserver'>{{ __('Reserver') }}</button>
    </div>
    </form>
    <div class='cl'></div>
@endsection