Creating Seussology App - Part 2
Download Starter Files
So all students are starting from the same point. Download the Seussology Files.
Unzip the file and copy the public, resources, and routes folders replace the existing folders in your laravel project.
Working with Controllers
Creating controller
1. Open Command Line application
Open Local by Flywheel and start the MTM6331 Laravel site. Right click on the MTM6331 Laravel site in the Local Sites menu and select "Open Site SSH".

Now, your default command line application should be open to the Local by Flywheel virtual machine. All command must be entered in this command line window.
2. Use Artisan
Type and execute the following command in Local by Flywheel virtual machine command line window.
cd app
php artisan make:controller BooksController
After executing this command, you should find that the file BooksController.php was created in the app/Http/Controllers directory.
Important
Leave the Command Line Window open. We will use it again.
Adding a method to a controller
1. Open BooksController.php in app/Http/Controllers
2. Add index method
Add new method (function) to the BooksController class. The method will have the name index and return the books view.
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class BooksController extends Controller
{
public function index ()
{
return view('books');
}
}
Updating Books Route
1. Open web.php in the routes/ directory
2. Update the route
Replace the books route with the following:
Route::get('/', 'BooksController@index');
Working with Models
Adding Seussology database
1. Download the seussology-laravel.sql file
2. Use Adminer to import the database to MTM6331 Laravel site
3. Open .env file at the Laravel site root
4. Update the Database Settings
Starting around line 9, we can find the database settings, which will look like this:
DB_CONNECTION=mysql
DB_HOST=192.168.95.100
DB_PORT=4035
DB_DATABASE=local
DB_USERNAME=root
DB_PASSWORD=root
From this list, DB_PORT and DB_DATABASE will need to be updated. DB_DATABASE should equal seussology and DB_PORT should equal the MySQL remote port number for your version of the MTM6331 Laravel site. That number can be found by going to Local by Flywheel, selecting the MTM6331 Laravel site, and clicking on the database tab.
Defining the Book Model
1. Go to Local by Flywheel virtual machine command line window
2. Enter the following command
php artisan make:model Book
After executing the command, we should find the file Book.php inside the app directory of our Laravel application.
Requesting the Books Data
1. Open app/Http/Controllers/BooksController.php
2. Import the Book Model
Add use App\Book after the namespace declaration.
namespace App\Http\Controllers;
use App\Book;
3. Request all the books from the database
To retrieve all the books, we will use the all() method from the Book Model. We will set the results of the query to the variable $books.
$books = BOOK::all();
The above line should be placed right before the return statement of the index() method
public function index ()
{
$books = BOOK::all();
return view('Books');
}
4. Send the books data to the view
Finally, we will send the data retrieved from the database to view. We do this by placing the $books variable inside an associative array, which itself is the second argument the view() method.
BookController.php
<?php
namespace App\Http\Controllers;
use App\Book;
use Illuminate\Http\Request;
class BooksController extends Controller
{
public function index ()
{
$books = Book::all();
return view('Books', ['books' => $books]);
}
}
Replacing Static Content
1. Open books.blade.php in the resources/views.
2. Create a loop
We will create a loop using the @foreach directive around the book div:
@section('main')
<main id="main" class="books">
@foreach ($books as $book)
<div class="book">
<a class="book-image" href="/book">
<img src="http://www.seussville.com/media/assets/all-book-covers/1.jpg" alt="And to Think That I Saw It on Mulberry Street">
</a>
</div>
@endforeach
</main>
@endsection
4. Replace static content with $book data
Use the mustache syntax to insert the $book data in the appropriate spots.
@section('main')
<main id="main" class="books">
@foreach ($books as $book)
<div class="book">
<a class="book-image" href="/book/{{ $book['id'] }}">
<img src="{{ $book['book_image'] }}" alt="{{ $book['book_title'] }}">
</a>
</div>
@endforeach
</main>
@endsection
Working with Route Parameters
Updating the Route
1. Open web.php in the routes directory
2. Add the book route with parameter
Add a new route for /book with a parameter of id. Parameters are surrounded by curly braces. The route will point to the show() method of the BookController class.
Route::get('/book/{id}', 'BooksController@show');
Creating the Show Method
1. Open BooksController.php in the app/Http/Controllers directory
2. Add the new method
Create a new method in the BookController class with the name of show and it should take the parameter $id.
<?php
class BooksController extends Controller
{
public function index ()
{
$books = Book::all();
return view('books', ['books' => $books]);
}
public function show($id)
{
}
}
3. Request the desired book from the database
Use the find() method from the Book Model, passing the $id as the parameter, to get the desired book. Set results of to the variable $book.
public function show($id)
{
$book = Book::find($id);
}
4. Return the book view with the book data
Return the book view, passing the $book variable inside of an associative array.
public function show($id)
{
$book = Book::find($id);
return view('book', ['book' => $book]);
}
Updating the Book View
1. Open book.blade.php in the resources/view directory
2. Replace the static content
Replace all the static content with the data receive from the database.
Note
Book quotes come from the quotes table, which we have not access yet.
@section('main')
<main id="main" class="details">
<div class="details-controls">
<a href="/edit/{{ $book['id'] }}" class="details-control"><i class="far fa-edit"></i></a>
<a href="/delete/{{ $book['id'] }}" class="details-control"><i class="far fa-trash-alt"></i></a>
</div>
<div class="details-image">
<img src="{{ $book['book_image'] }}" alt="{{ $book['book_title'] }}">
</div>
<div>
<h2 class="details-title">{{ $book['book_title'] }}</h2>
<p>{{ $book['book_description'] }}</p>
<p>Published: {{ $book['book_year'] }}<br>
Number of Pages: {{ $book['book_pages'] }}</p>
<blockquote class="details-quote">
<p>Stop telling such outlandish tales. Stop turning minnows into whales.</p>
</blockquote>
<blockquote class="details-quote">
<p>For I had a story that no one could beat! And to think that I saw it on Mulberry Street!</p>
</blockquote>
</div>
</main>
@endsection
Working with Relationships
Defining the Model
1. Go to Local by Flywheel virtual machine command line window
2. Enter the following command
php artisan make:model Quote
After executing the command, we should find the file Quote.php inside the app directory of our Laravel application.
Defining the Relationship
1. Open Book.php in the /app directory
2. Create a new method
Inside the Book class, create a new method with the name quotes.
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Book extends Model
{
public function quotes ()
{
}
}
3. Define the relationship
Inside the quotes() method, return hasMany() method passing the path to the Quote model ('App\Quote') as the parameter.
Note
Because the hasMany() method is also part of the Book class, we will use the $this variable to call the hasMany() method.
public function quotes ()
{
return $this->hasMany('App\Quote');
}
Querying with the Relationship
1. Open BooksController.php in the app/Http/Controllers directory
2. Request the quotes
Inside the show() method, request all of the quotes for the selected book by accessing the quotes method Book model. Save the results to the $quotes variable.
public function show ($id)
{
$book = Book::find($id);
$quotes = Book::find($id)->quotes;
return view('book', ['book' => $book]);
}
3. Send the quotes to the view
Add $quotes to the view by adding a new item the array.
public function show ($id)
{
$book = Book::find($id);
$quotes = Book::find($id)->quotes;
return view('book', ['book' => $book, 'quotes' => $quotes]);
}
Adding Quotes to View
1. Open book.blade.php in the resources/views directory
2. Replace the static quotes
Using the @foreach directive, replace the static quotes with the quotes data, stored in the $quotes variable.
@section('main')
<main id="main" class="details">
<div class="details-controls">
<a href="/edit/{{ $book['id'] }}" class="details-control"><i class="far fa-edit"></i></a>
<a href="/delete/{{ $book['id'] }}" class="details-control"><i class="far fa-trash-alt"></i></a>
</div>
<div class="details-image">
<img src="{{ $book['book_image'] }}" alt="{{ $book['book_title'] }}">
</div>
<div>
<h2 class="details-title">{{ $book['book_title'] }}</h2>
<p>{{ $book['book_description'] }}</p>
<p>Published: {{ $book['book_year'] }}<br>
Number of Pages: {{ $book['book_pages'] }}</p>
@foreach ($quotes as $quote)
<blockquote class="details-quote">
<p>{{ $quote['quote'] }}</p>
</blockquote>
@endforeach
</div>
</main>
@endsection
Working with New Data
Note
To keep things simple, the following example will NOT include any validation. However, in a real world form, you should ALWAYS include validation.
Using the Books Controller
Use the BooksController instead of the routes to handle the logic for New Book page.
1. Open web.php in the routes/ directory
2. Update the route for a new book
Replace the inline function with a call to the new() method in BooksController
Route::get('/new', 'BooksController@new');
3. Open BooksController.php in the app/Http/Controllers directory
4. Add the new method
Add a new method with the name new
<?php
namespace App\Http\Controllers;
use App\Book;
use Illuminate\Http\Request;
class BooksController extends Controller
{
public function index ()
{
$books = Book::all();
return view('books', ['books' => $books]);
}
public function show ($id)
{
$book = Book::find($id);
$quotes = Book::find($id)->quotes;
return view('book', ['book' => $book, 'quotes' => $quotes]);
}
public function new ()
{
}
}
5. Return the form view
Return the form view inside the new() method, pass an array containing key title and the value New Book.
public function new ()
{
return view('form', ['title' => 'Add Book']);
}
Creating categories dynamically
Replace the categories dropdown when a dynamic one by retrieving the categories from the database.
1. Go to Local by Flywheel virtual machine command line window
2. Enter the following command
php artisan make:model Category
3. Open BooksController.php in the app/Http/Controllers directory
4. Import the Category model
Add the following line belong the import the Category model
<?php
namespace App\Http\Controllers;
use App\Book;
use App\Category;
use Illuminate\Http\Request;
class BooksController extends Controller
{
public function index ()
{
$books = Book::all();
return view('books', ['books' => $books]);
}
public function show ($id)
{
$book = Book::find($id);
$quotes = Book::find($id)->quotes;
return view('book', ['book' => $book, 'quotes' => $quotes]);
}
public function new ()
{
return view('form', ['title' => 'Add Book']);
}
}
5. Retrieve categories from database
Inside the new() method, use the Category model and the all() method to retrieve all the categories.
public function new ()
{
$categories = Category::all();
return view('form', ['title' => 'Add Book']);
}
6. Send categories to view
Add another item to data array being sent to the view that will hold that categories.
public function new ()
{
$categories = Category::all();
return view('form', ['title' => 'Add Book', 'categories' => $categories]);
}
7. Open form.blade.php in the resources/views directory
8. Update the select menu
Use $categories data select menu.
<select class="form-input" name="category_id">
<option></option>
@foreach ($categories as $category)
<option value="{{ $category['id'] }}">{{ $category['category_name'] }}</option>
@endforeach
</select>
Creating a Submission Route
1. Open web.php in the routes/ directory
2. Create a route for a new book submission
Create a route using the post() method and /new URL. It will point to the store() method in the BooksController.
Route::post('/new', 'BooksController@store');
Creating the store Method
1. Open BooksController.php in the app/Http/Controllers directory
2. Add the store method
Add a new method with the name store and the parameter Request $request.
<?php
namespace App\Http\Controllers;
use App\Book;
use App\Category;
use Illuminate\Http\Request;
class BooksController extends Controller
{
public function index ()
{
$books = Book::all();
return view('books', ['books' => $books]);
}
public function show ($id)
{
$book = Book::find($id);
$quotes = Book::find($id)->quotes;
return view('book', ['book' => $book, 'quotes' => $quotes]);
}
public function new ()
{
$categories = Category::all();
return view('form', ['title' => 'Add Book', 'categories' => $categories]);
}
public function store (Request $request)
{
}
}
3. Insert the data into the database
Use the Book::create() method to insert the $request data into the database.
public function store (Request $request)
{
$book = Book::create($request->all());
}
4. Redirect to the edit page
Return the redirect() padding the "/edit/{$book['id']}" as a parameter.
public function store (Request $request)
{
$book = Book::create($request->all());
return redirect("/edit/{$book['id']}");
}
Note
Submitting the form will fail because of security features build into Laravel.
Allowing for New Data
1. Open Book.php in the app/ directory
2. Add fillable inputs
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Book extends Model
{
protected $fillable = [
'book_title',
'book_year',
'book_pages',
'book_image',
'book_description',
'category_id'
];
public $timestamps = false;
public function quotes()
{
return $this->hasMany('App\Quote');
}
}
Note
Submitting the form will result in page not found because we have not defined the edit route yet.
Updating Existing Data
Creating an Edit Route
1. Open web.php in the routes/ directory
2. Update the route
Create the edit route with id parameter to the URI and point the route the edit() method of the BooksController.
Route::get('/edit/{id}', 'BooksController@edit');
Creating an Edit Method
1. Open BooksController.php in the app/Http/Controllers directory
2. Add the edit method
Add an edit() method with parameter of $id.
<?php
namespace App\Http\Controllers;
use App\Book;
use App\Category;
use Illuminate\Http\Request;
class BooksController extends Controller
{
public function index ()
{
$books = Book::all();
return view('books', ['books' => $books]);
}
public function show ($id)
{
$book = Book::find($id);
$quotes = Book::find($id)->quotes;
return view('book', ['book' => $book, 'quotes' => $quotes]);
}
public function new ()
{
$categories = Category::all();
return view('form', ['title' => 'Add Book', 'categories' => $categories]);
}
public function store (Request $request)
{
$book = Book::create($request->all());
return redirect("/edit/{$book['id']}");
}
public function edit ($id)
{
}
}
3. Retrieve the book data
Use the Book::find() to get book data by $id.
public function edit ($id)
{
$book = Book::find($id);
}
4. Return the form view
Return the form view passing the book data.
public function edit ($id)
{
$book = Book::find($id);
return view('form', ['book' => $book]);
}
Updating the Form View
1. Open form.blade.php in the resources/views directory
2. Update the form to accept data
Use the @isset and @endisset directive to check if the book data is available, and if so, add the appropriate book data to each input value.
Note
Replace each input with the appropriate one below.
<input class="form-input" type="text" name="book_title"
value="@isset($book['book_title']){{ $book['book_title'] }}@endisset">
...
<input class="form-input" type="text" maxlength="4" name="book_year"
value="@isset($book['book_year']){{ $book['book_year'] }}@endisset">
...
<input class="form-input" type="number" name="book_pages"
value="@isset($book['book_pages']){{ $book['book_pages'] }}@endisset">
...
<input class="form-input" type="text" name="book_image"
value="@isset($book['book_image']){{ $book['book_image'] }}@endisset">
...
<textarea class="form-input" name="book_description">
@isset($book['book_description']){{ $book['book_description'] }}@endisset
</textarea>
Note
Category has not been updated because we do not have the category data.
Retrieving the Book's Category
1. Open Book.php in the app/ directory
2. Create a category method
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Book extends Model
{
protected $fillable = [
'book_title',
'book_year',
'book_pages',
'book_image',
'book_description',
'category_id'
];
public $timestamps = false;
public function quotes()
{
return $this->hasMany('App\Quote');
}
public function category()
{
}
}
3. Define the Relationship
Return the belongsTo() method passing the parameter 'App\Category'.
public function category()
{
return $this->belongsTo('App\Category');
}
4. Open BookController.php in the app/Http/Controllers directory
5. Update edit() method
Update the edit method to retrieve the selected book's category as well as all categories. This will allow use to dynamically create the categories select menu. Send the category and categories data to the form view.
public function edit ($id)
{
$book = Book::find($id);
$category = Book::find($id)->category;
$categories = Category::all();
return view('form', [
'title' => 'Edit Book',
'book' => $book,
'bookCategory' => $category,
'categories' => $categories
]);
}
6. Open form.blade.php in the resources/views directory
7. Update the select menu
Use $bookCategory preselect the correct option.
<select class="form-input" name="category_id">
<option></option>
@foreach ($categories as $category)
<option value="{{ $category['id'] }}"
@isset($bookCategory)
@if ($category['id'] === $bookCategory['id'])
selected="selected"
@endif
@endisset
>{{ $category['category_name'] }}</option>
@endforeach
</select>
Updating the Book
Now, that we are displaying all of the book's data in the form, we do set up our application to process any change that we make to the data.
1. Open web.php in the routes directory
2. Add a new route
Add a new route using the post() method. The URL should be /edit/{id} and it should point to store() method of the BooksController
Route::post('/edit/{id}', 'BooksController@update');
3. Open BooksController.php in the app/Http/Controllers/
4. Add the update method
Create an the update method with two parameters, the request data Request $request and the Book $book data.
<?php
namespace App\Http\Controllers;
use App\Book;
use App\Category;
use Illuminate\Http\Request;
class BooksController extends Controller
{
public function index ()
{
$books = Book::all();
return view('books', ['books' => $books]);
}
public function show ($id)
{
$book = Book::find($id);
$quotes = Book::find($id)->quotes;
return view('book', ['book' => $book, 'quotes' => $quotes]);
}
public function new ()
{
$categories = Category::all();
return view('form', ['title' => 'Add Book', 'categories' => $categories]);
}
public function store (Request $request)
{
$book = Book::create($request->all());
return redirect("/edit/{$book['id']}");
}
public function edit ($id)
{
$book = Book::find($id);
$category = Book::find($id)->category;
$categories = Category::all();
return view('form', [
'title' => 'Edit Book',
'book' => $book,
'bookCategory' => $category,
'categories' => $categories
]);
}
public function update (Request $request, $id)
{
}
}
5. Update the data
Find the book using the $id and update the data with the $request using the update() method.
public function update (Request $request, Book $book)
{
Book::find($id)->update($request->all());
}
6. Return the edit method
To display the edit book form again, return the edit() passing the $id. Use $this to access the method.
public function update (Request $request, Book $book)
{
Book::find($id)->update($request->all());
return $this->edit($id);
}
Deleting Existing Data
Deleting a Book
1. Open web.php from the routes directory
2. Add the delete route
Route::get('/delete/{id}', 'BooksController@delete');
3. Open BooksController.php from the app/Http/Controllers directory
4. Add the delete() method
Create the delete() method with the parameter $id
<?php
namespace App\Http\Controllers;
use App\Book;
use App\Category;
use Illuminate\Http\Request;
class BooksController extends Controller
{
public function index ()
{
$books = Book::all();
return view('books', ['books' => $books]);
}
public function show ($id)
{
$book = Book::find($id);
$quotes = Book::find($id)->quotes;
return view('book', ['book' => $book, 'quotes' => $quotes]);
}
public function new ()
{
$categories = Category::all();
return view('form', ['title' => 'Add Book', 'categories' => $categories]);
}
public function store (Request $request)
{
$book = Book::create($request->all());
return redirect("/edit/{$book['id']}");
}
public function edit ($id)
{
$book = Book::find($id);
$category = Book::find($id)->category;
$categories = Category::all();
return view('form', [
'title' => 'Edit Book',
'book' => $book,
'bookCategory' => $category,
'categories' => $categories
]);
}
public function update (Request $request, $id)
{
Book::find($id)->update($request->all());
return $this->edit($id);
}
public function delete ($id)
{
}
}
5. Find the book
Using Book::find find the selected book and save the data to the $book variable.
public function delete ($id)
{
$book = Book::find($id);
}
6. Delete the book
Delete the book using the delete() method of $book
public function delete ($id)
{
$book = Book::find($id);
$book->delete();
}
7. Return the delete view
Return the delete view, passing the book title to the view.
public function delete ($id)
{
$book = Book::find($id);
$book->delete();
return view('delete', ['title' => $book['book_title']]);
}