One place for hosting & domains

      Laravel

      Simple Laravel CRUD with Resource Controllers


      Creating, reading, updating, and deleting resources is used in pretty much every application. Laravel helps make the process easy using resource controllers. Resource Controllers can make life much easier and takes advantage of some cool Laravel routing techniques. Today, we’ll go through the steps necessary to get a fully functioning CRUD application using resource controllers.

      For this tutorial, we will go through the process of having an admin panel to create, read, update, and delete (CRUD) a resource. Let’s use sharks as our example. We will also make use of Eloquent ORM.

      This tutorial will walk us through:

      • Setting up the database and models
      • Creating the resource controller and its routes
      • Creating the necessary views
      • Explaining each method in a resource controller

      To get started, we will need the controller, the routes, and the view files.

      You can view and clone a repo of all the code covered in this tutorial on GitHub

      Getting our Database Ready

      Shark Migration

      We need to set up a quick database so we can do all of our CRUD functionality. In the command line in the root directory of our Laravel application, let’s create a migration.

      • php artisan migrate:make create_sharks_table --table=sharks --create

      This will create our shark migration in app/database/migrations. Open up that file and let’s add name, email, and shark_level fields.

      app/database/migrations/####_##_##_######_create_sharks_table.php

      <?php
      
      use IlluminateDatabaseSchemaBlueprint;
      use IlluminateDatabaseMigrationsMigration;
      
      class CreatesharksTable extends Migration {
      
          /**
              * Run the migrations.
              *
              * @return void
              */
          public function up()
          {
              Schema::create('sharks', function(Blueprint $table)
              {
                  $table->increments('id');
      
                  $table->string('name', 255);
                  $table->string('email', 255);
                  $table->integer('shark_level');
      
                  $table->timestamps();
              });
          }
      
          /**
              * Reverse the migrations.
              *
              * @return void
              */
          public function down()
          {
              Schema::drop('sharks');
          }
      
      }
      

      Now from the command line again, let’s run this migration. Make sure your database settings are good in app/config/database.php and then run:

      php artisan migrate Our database now has a sharks table to house all of the sharks we CRUD (create, read, update, and delete). Read more about migrations at the Laravel docs.

      Eloquent Model for the sharks

      Now that we have our database, let’s create a simple Eloquent model so that we can access the sharks in our database easily. You can read about Eloquent ORM and see how you can use it in your own applications.

      In the app/models folder, let’s create a shark.php model.

      app/models/shark.php

      
      <?php
      
          class shark extends Eloquent
          {
      
          }
      

      That’s it! Eloquent can handle the rest. By default, this model will link to our sharks table and and we can access it later in our controllers.

      Creating the Controller

      From the official Laravel docs, on resource controllers, you can generate a resource controller using the artisan tool.

      Let’s go ahead and do that. This is the easy part. From the command line in the root directory of your Laravel project, type:

      php artisan controller:make sharkController This will create our resource controller with all the methods we need.

      app/controllers/sharkController.php

      <?php
      
      class sharkController extends BaseController {
      
          /**
              * Display a listing of the resource.
              *
              * @return Response
              */
          public function index()
          {
              //
          }
      
          /**
              * Show the form for creating a new resource.
              *
              * @return Response
              */
          public function create()
          {
              //
          }
      
          /**
              * Store a newly created resource in storage.
              *
              * @return Response
              */
          public function store()
          {
              //
          }
      
          /**
              * Display the specified resource.
              *
              * @param  int  $id
              * @return Response
              */
          public function show($id)
          {
              //
          }
      
          /**
              * Show the form for editing the specified resource.
              *
              * @param  int  $id
              * @return Response
              */
          public function edit($id)
          {
              //
          }
      
          /**
              * Update the specified resource in storage.
              *
              * @param  int  $id
              * @return Response
              */
          public function update($id)
          {
              //
          }
      
          /**
              * Remove the specified resource from storage.
              *
              * @param  int  $id
              * @return Response
              */
          public function destroy($id)
          {
              //
          }
      
      }
      

      Setting Up the Routes

      Now that we have generated our controller, let’s make sure our application has the routes necessary to use it. This is the other easy part (they actually might all be easy parts). In your routes.php file, add this line:

      app/routes.php

      <?php
      
          Route::resource('sharks', 'sharkController');
      

      This will automatically assign many actions to that resource controller. Now if you, go to your browser and view your application at example.com/sharks, it will correspond to the proper method in your sharkController.

      Actions Handled By the Controller

      HTTP VerbPath (URL)Action (Method)Route Name
      GET/sharksindexsharks.index
      GET/sharks/createcreatesharks.create
      POST/sharksstoresharks.store
      GET/sharks/{id}showsharks.show
      GET/sharks/{id}/editeditsharks.edit
      PUT/PATCH/sharks/{id}updatesharks.update
      DELETE/sharks/{id}destroysharks.destroy

      Tip: From the command line, you can run php artisan routes to see all the routes associated with your application.

      The Views

      Since only four of our routes are GET routes, we only need four views. In our app/views folder, let’s make those views now.

      app
      └───views
          └───sharks
              │    index.blade.php
              │    create.blade.php
              │    show.blade.php
              │    edit.blade.php
      

      Making It All Work Together

      Now we have our migrations, database, and models, our controller and routes, and our views. Let’s make all these things work together to build our application. We are going to go through the methods created in the resource controller one by one and make it all work.

      Showing All Resources sharks.index

      DescriptionURLController FunctionView File
      Default page for showing all the sharks.GET example.com/sharksindex()app/views/sharks/index.blade.php

      Controller Function index()

      In this function, we will get all the sharks and pass them to the view.

      app/controllers/sharkController.php

      
      <?php
      
      ...
      
          /**
              * Display a listing of the resource.
              *
              * @return Response
              */
          public function index()
          {
              // get all the sharks
              $sharks = shark::all();
      
              // load the view and pass the sharks
              return View::make('sharks.index')
                  ->with('sharks', $sharks);
          }
      ...
      

      The View app/views/sharks/index.blade.php

      Now let’s create our view to loop over the sharks and display them in a table. We like using Twitter Bootstrap for our sites, so the table will use those classes.

      app/views/sharks/index.blade.php

      
      <!DOCTYPE html>
      <html>
      <head>
          <title>Shark App</title>
          <link rel="stylesheet" href="https://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css">
      </head>
      <body>
      <div class="container">
      
      <nav class="navbar navbar-inverse">
          <div class="navbar-header">
              <a class="navbar-brand" href="https://www.digitalocean.com/community/tutorials/{{ URL::to("sharks') }}">shark Alert</a>
          </div>
          <ul class="nav navbar-nav">
              <li><a href="https://www.digitalocean.com/community/tutorials/{{ URL::to("sharks') }}">View All sharks</a></li>
              <li><a href="https://www.digitalocean.com/community/tutorials/{{ URL::to("sharks/create') }}">Create a shark</a>
          </ul>
      </nav>
      
      <h1>All the sharks</h1>
      
      <!-- will be used to show any messages -->
      @if (Session::has('message'))
          <div class="alert alert-info">{{ Session::get('message') }}</div>
      @endif
      
      <table class="table table-striped table-bordered">
          <thead>
              <tr>
                  <td>ID</td>
                  <td>Name</td>
                  <td>Email</td>
                  <td>shark Level</td>
                  <td>Actions</td>
              </tr>
          </thead>
          <tbody>
          @foreach($sharks as $key => $value)
              <tr>
                  <td>{{ $value->id }}</td>
                  <td>{{ $value->name }}</td>
                  <td>{{ $value->email }}</td>
                  <td>{{ $value->shark_level }}</td>
      
                  <!-- we will also add show, edit, and delete buttons -->
                  <td>
      
                      <!-- delete the shark (uses the destroy method DESTROY /sharks/{id} -->
                      <!-- we will add this later since its a little more complicated than the other two buttons -->
      
                      <!-- show the shark (uses the show method found at GET /sharks/{id} -->
                      <a class="btn btn-small btn-success" href="https://www.digitalocean.com/community/tutorials/{{ URL::to("sharks/' . $value->id) }}">Show this shark</a>
      
                      <!-- edit this shark (uses the edit method found at GET /sharks/{id}/edit -->
                      <a class="btn btn-small btn-info" href="https://www.digitalocean.com/community/tutorials/{{ URL::to("sharks/' . $value->id . '/edit') }}">Edit this shark</a>
      
                  </td>
              </tr>
          @endforeach
          </tbody>
      </table>
      
      </div>
      </body>
      </html>
      

      We can now show all of our sharks on a page. There won’t be any that show up currently since we haven’t created any or seeded our database with sharks. Let’s move on to the form to create a shark.

      index-blade

      Creating a New Resource sharks.create

      DescriptionURLController FunctionView File
      Show the form to create a new shark.GET example.com/sharks/createcreate()app/views/sharks/create.blade.php

      Controller Function create()

      In this function, we will show the form for creating a new shark. This form will be processed by the store() method.

      app/controllers/sharkController.php

      <?php
      ...
          /**
              * Show the form for creating a new resource.
              *
              * @return Response
              */
          public function create()
          {
              // load the create form (app/views/sharks/create.blade.php)
              return View::make('sharks.create');
          }
      ...
      

      The View app/views/sharks/create.blade.php

      app/views/sharks/create.blade.php

      
      <!DOCTYPE html>
      <html>
      <head>
          <title>Shark App</title>
          <link rel="stylesheet" href="https://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css">
      </head>
      <body>
      <div class="container">
      
      <nav class="navbar navbar-inverse">
          <div class="navbar-header">
              <a class="navbar-brand" href="https://www.digitalocean.com/community/tutorials/{{ URL::to("sharks') }}">shark Alert</a>
          </div>
          <ul class="nav navbar-nav">
              <li><a href="https://www.digitalocean.com/community/tutorials/{{ URL::to("sharks') }}">View All sharks</a></li>
              <li><a href="https://www.digitalocean.com/community/tutorials/{{ URL::to("sharks/create') }}">Create a shark</a>
          </ul>
      </nav>
      
      <h1>Create a shark</h1>
      
      <!-- if there are creation errors, they will show here -->
      {{ HTML::ul($errors->all()) }}
      
      {{ Form::open(array('url' => 'sharks')) }}
      
          <div class="form-group">
              {{ Form::label('name', 'Name') }}
              {{ Form::text('name', Input::old('name'), array('class' => 'form-control')) }}
          </div>
      
          <div class="form-group">
              {{ Form::label('email', 'Email') }}
              {{ Form::email('email', Input::old('email'), array('class' => 'form-control')) }}
          </div>
      
          <div class="form-group">
              {{ Form::label('shark_level', 'shark Level') }}
              {{ Form::select('shark_level', array('0' => 'Select a Level', '1' => 'Sees Sunlight', '2' => 'Foosball Fanatic', '3' => 'Basement Dweller'), Input::old('shark_level'), array('class' => 'form-control')) }}
          </div>
      
          {{ Form::submit('Create the shark!', array('class' => 'btn btn-primary')) }}
      
      {{ Form::close() }}
      
      </div>
      </body>
      </html>
      

      We will add the errors section above to show validation errors when we try to store() the resource.
      Tip: When using {{ Form::open() }}, Laravel will automatically create a hidden input field with a token to protect from cross-site request forgeries. Read more at the Laravel docs.

      We now have the form, but we need to have it do something when it the submit button gets pressed. We set this form’s action to be a POST to example.com/sharks. The resource controller will handle this and automatically route the request to the store() method. Let’s handle that now.

      Storing a Resource store()

      DescriptionURLController FunctionView File
      Process the create form submit and save the shark to the database.POST example.com/sharksstore()NONE

      As you can see from the form action and the URL, you don’t have to pass anything extra into the URL to store a shark. Since this form is sent using the POST method, the form inputs will be the data used to store the resource.

      To process the form, we’ll want to validate the inputs, send back error messages if they exist, authenticate against the database, and store the resource if all is good. Let’s dive in.

      Controller Function store()

      app/controllers/sharkController.php

      <?php
      ...
          /**
              * Store a newly created resource in storage.
              *
              * @return Response
              */
          public function store()
          {
              // validate
              // read more on validation at http://laravel.com/docs/validation
              $rules = array(
                  'name'       => 'required',
                  'email'      => 'required|email',
                  'shark_level' => 'required|numeric'
              );
              $validator = Validator::make(Input::all(), $rules);
      
              // process the login
              if ($validator->fails()) {
                  return Redirect::to('sharks/create')
                      ->withErrors($validator)
                      ->withInput(Input::except('password'));
              } else {
                  // store
                  $shark = new shark;
                  $shark->name       = Input::get('name');
                  $shark->email      = Input::get('email');
                  $shark->shark_level = Input::get('shark_level');
                  $shark->save();
      
                  // redirect
                  Session::flash('message', 'Successfully created shark!');
                  return Redirect::to('sharks');
              }
          }
      ...
      

      If there are errors processing the form, we will redirect them back to the create form with those errors. We will add them in so the user can understand what went wrong. They will show up in the errors section we setup earlier.

      Now you should be able to create a shark and have them show up on the main page! Navigate to example.com/sharks and there they are. All that’s left is showing a single shark, updating, and deleting.

      created

      Showing a Resource show()

      DescriptionURLController FunctionView File
      Show one of the sharks.GET example.com/sharks/{id}show()app/views/sharks/show.blade.php

      Controller Function show()

      app/controllers/sharkController.php

      <?php
      
      ...
      
          /**
              * Display the specified resource.
              *
              * @param  int  $id
              * @return Response
              */
          public function show($id)
          {
              // get the shark
              $shark = shark::find($id);
      
              // show the view and pass the shark to it
              return View::make('sharks.show')
                  ->with('shark', $shark);
          }
      
      ...
      

      The View app/views/sharks/show.blade.php

      app/views/sharks/show.blade.php

      
      <!DOCTYPE html>
      <html>
      <head>
          <title>Shark App</title>
          <link rel="stylesheet" href="https://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css">
      </head>
      <body>
      <div class="container">
      
      <nav class="navbar navbar-inverse">
          <div class="navbar-header">
              <a class="navbar-brand" href="https://www.digitalocean.com/community/tutorials/{{ URL::to("sharks') }}">shark Alert</a>
          </div>
          <ul class="nav navbar-nav">
              <li><a href="https://www.digitalocean.com/community/tutorials/{{ URL::to("sharks') }}">View All sharks</a></li>
              <li><a href="https://www.digitalocean.com/community/tutorials/{{ URL::to("sharks/create') }}">Create a shark</a>
          </ul>
      </nav>
      
      <h1>Showing {{ $shark->name }}</h1>
      
          <div class="jumbotron text-center">
              <h2>{{ $shark->name }}</h2>
              <p>
                  <strong>Email:</strong> {{ $shark->email }}<br>
                  <strong>Level:</strong> {{ $shark->shark_level }}
              </p>
          </div>
      
      </div>
      </body>
      </html>
      

      show

      Editing a Resource edit()

      DescriptionURLController FunctionView File
      Pull a shark from the database and allow editing.GET example.com/sharks/{id}/editedit()app/views/sharks/edit.blade.php

      To edit a shark, we need to pull them from the database, show the creation form, but populate it with the selected shark’s info. To make life easier, we will use form model binding. This allows us to pull info from a model and bind it to the input fields in a form. Just makes it easier to populate our edit form and you can imagine that when these forms start getting rather large this will make life much easier.

      Controller Function edit()

      app/controllers/sharkController.php

      
      <?php
      
      ...
      
          /**
              * Show the form for editing the specified resource.
              *
              * @param  int  $id
              * @return Response
              */
          public function edit($id)
          {
              // get the shark
              $shark = shark::find($id);
      
              // show the edit form and pass the shark
              return View::make('sharks.edit')
                  ->with('shark', $shark);
          }
      ...
      

      The View app/views/sharks/edit.blade.php

      app/views/sharks/edit.blade.php

      <!DOCTYPE html>
      <html>
      <head>
          <title>Shark App</title>
          <link rel="stylesheet" href="https://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css">
      </head>
      <body>
      <div class="container">
      
      <nav class="navbar navbar-inverse">
          <div class="navbar-header">
              <a class="navbar-brand" href="https://www.digitalocean.com/community/tutorials/{{ URL::to("sharks') }}">shark Alert</a>
          </div>
          <ul class="nav navbar-nav">
              <li><a href="https://www.digitalocean.com/community/tutorials/{{ URL::to("sharks') }}">View All sharks</a></li>
              <li><a href="https://www.digitalocean.com/community/tutorials/{{ URL::to("sharks/create') }}">Create a shark</a>
          </ul>
      </nav>
      
      <h1>Edit {{ $shark->name }}</h1>
      
      <!-- if there are creation errors, they will show here -->
      {{ HTML::ul($errors->all()) }}
      
      {{ Form::model($shark, array('route' => array('sharks.update', $shark->id), 'method' => 'PUT')) }}
      
          <div class="form-group">
              {{ Form::label('name', 'Name') }}
              {{ Form::text('name', null, array('class' => 'form-control')) }}
          </div>
      
          <div class="form-group">
              {{ Form::label('email', 'Email') }}
              {{ Form::email('email', null, array('class' => 'form-control')) }}
          </div>
      
          <div class="form-group">
              {{ Form::label('shark_level', 'shark Level') }}
              {{ Form::select('shark_level', array('0' => 'Select a Level', '1' => 'Sees Sunlight', '2' => 'Foosball Fanatic', '3' => 'Basement Dweller'), null, array('class' => 'form-control')) }}
          </div>
      
          {{ Form::submit('Edit the shark!', array('class' => 'btn btn-primary')) }}
      
      {{ Form::close() }}
      
      </div>
      </body>
      </html>
      

      Note that we have to pass a method of PUT so that Laravel knows how to route to the controller correctly.

      Updating a Resource update()

      DescriptionURLController FunctionView File
      Process the create form submit and save the shark to the database.PUT example.com/sharksupdate()NONE

      This controller method will process the edit form. It is very similar to store(). We will validate, update, and redirect.

      Controller Function update()

      app/controllers/sharkController.php

      
      <?php
      
      ...
      
          /**
              * Update the specified resource in storage.
              *
              * @param  int  $id
              * @return Response
              */
          public function update($id)
          {
              // validate
              // read more on validation at http://laravel.com/docs/validation
              $rules = array(
                  'name'       => 'required',
                  'email'      => 'required|email',
                  'shark_level' => 'required|numeric'
              );
              $validator = Validator::make(Input::all(), $rules);
      
              // process the login
              if ($validator->fails()) {
                  return Redirect::to('sharks/' . $id . '/edit')
                      ->withErrors($validator)
                      ->withInput(Input::except('password'));
              } else {
                  // store
                  $shark = shark::find($id);
                  $shark->name       = Input::get('name');
                  $shark->email      = Input::get('email');
                  $shark->shark_level = Input::get('shark_level');
                  $shark->save();
      
                  // redirect
                  Session::flash('message', 'Successfully updated shark!');
                  return Redirect::to('sharks');
              }
          }
      ...
      

      Deleting a Resource destroy()

      DescriptionURLController FunctionView File
      Process the create form submit and save the shark to the database.DELETE example.com/sharks/{id}destroy()NONE

      The workflow for this is that a user would go to view all the sharks, see a delete button, click it to delete. Since we never created a delete button in our app/views/sharks/index.blade.php, we will create that now. We will also add a notification section to show a success message.

      We have to send the request to our application using the DELETE HTTP verb, so we will create a form to do that since a button won’t do.

      Alert: The DELETE HTTP verb is used when accessing the sharks.destroy route. Since you can’t just create a button or form with the method DELETE, we will have to spoof it by creating a hidden input field in our delete form.

      The View app/views/sharks/index.blade.php

      app/views/sharks/index.blade.php

      
      ...
      
          @foreach($sharks as $key => $value)
              <tr>
                  <td>{{ $value->id }}</td>
                  <td>{{ $value->name }}</td>
                  <td>{{ $value->email }}</td>
                  <td>{{ $value->shark_level }}</td>
      
                  <!-- we will also add show, edit, and delete buttons -->
                  <td>
      
                      <!-- delete the shark (uses the destroy method DESTROY /sharks/{id} -->
                      <!-- we will add this later since its a little more complicated than the other two buttons -->
                      {{ Form::open(array('url' => 'sharks/' . $value->id, 'class' => 'pull-right')) }}
                          {{ Form::hidden('_method', 'DELETE') }}
                          {{ Form::submit('Delete this shark', array('class' => 'btn btn-warning')) }}
                      {{ Form::close() }}
      
                      <!-- show the shark (uses the show method found at GET /sharks/{id} -->
                      <a class="btn btn-small btn-success" href="https://www.digitalocean.com/community/tutorials/{{ URL::to("sharks/' . $value->id) }}">Show this shark</a>
      
                      <!-- edit this shark (uses the edit method found at GET /sharks/{id}/edit -->
                      <a class="btn btn-small btn-info" href="https://www.digitalocean.com/community/tutorials/{{ URL::to("sharks/' . $value->id . '/edit') }}">Edit this shark</a>
      
                  </td>
              </tr>
          @endforeach
          ...
      

      Now when we click that form submit button, Laravel will use the sharks.destroy route and we can process that in our controller.

      Controller Function destroy()

      app/controllers/sharkController.php

      <?php
      
      ...
      
          /**
              * Remove the specified resource from storage.
              *
              * @param  int  $id
              * @return Response
              */
          public function destroy($id)
          {
              // delete
              $shark = shark::find($id);
              $shark->delete();
      
              // redirect
              Session::flash('message', 'Successfully deleted the shark!');
              return Redirect::to('sharks');
          }
      ...
      

      Conclusion

      That’s everything! Hopefully we covered enough so that you can understand how resource controllers can be used in all sorts of scenarios. Just create the controller, create the single line in the routes file, and you have the foundation for doing CRUD.

      As always, let us know if you have any questions or comments. We’ll be expanding more on Laravel in the coming articles so if there’s anything specific, throw it in the comments or email us.

      Further Reading: For more Laravel, check out our Simple Laravel Series.



      Source link

      Get Laravel Route Parameters in Middleware


      Today we’ll be talking about how to use route parameters in middleware, a task that may come up in your workflow.

      What is Middleware?

      A middleware simply wraps an application’s request. Think of it this way, when a request is made to your application, there’s code that handles the request, but if you want something to occur before or after the code that handles the request is run, you would put in a middleware.

      Laravel comes with a few inbuilt middlewares for maintenance, authentication and CSRF protection, which are all found in the app/Http/Middleware directory inside a laravel project folder.

      Laravel Route Parameters

      Laravel routes are located in the app/Http/routes.php file. A route usually has the URL path, and a handler function callback, which is usually a function written in a certain controller.

      // Inline function to handle the route
      Route::get('/', function () {
          return view('welcome');
      });
      
      // Controller function to handle the route
      Route::get('/profile', 'ProfileController@index');
      

      A parameter provided in the route is usually annotated with curly braces. For instance, to pass in a name parameter to a route, it would look like this.

      Route::get('/params/{name}', function ($name) {
          return $name
      });
      

      By convention, the Controller function accepts parameters based on the parameters provided.

      Accessing Route Parameters

      Accessing parameters in a middleware however is not that direct. First let’s create a middleware called DumpMiddleware that dumps the parameters provided in the route.

      php artisan make:middleware DumpMiddleware
      

      The file app/Http/Middlware/DumpMiddleware.php is created.

      Method 1: $request->route('parameter_name')

      We can access route parameters in two ways. One way is by using $request->route('parameter_name')., where parameter_name refers to what we called the parameter in the route. In the handle method within the DumpMiddleware class created in the app/Http/Middleware/DumpMiddleware.php file.

      public function handle($request, Closure $next)
      {   
          dd($request->route('parameter_name'));
          return $next($request);
      }
      

      To see the middleware in action, let’s add it to the route. Quickly create the route we showed above and add the middleware in the app/Http/routes.php file.

      Route::get('/params/{name}', [
          'middleware' => 'AppHttpMiddlewareDumpMiddleware',
           function () {
              return view('welcome');
      }]);
      

      We need the full namespace of the middleware, because we have not made Laravel aware of our new middleware. To do this we add it in the AppHttpKernel.php file, as part of the $routeMiddleware class property.

      protected $routeMiddleware = [
          // Middlewares commented out for brevity
          'DumpMiddleware' => AppHttpMiddlewareDumpMiddleware::class,
      ];
      

      You can then update the middleware in the route to be 'middleware' => 'DumpMiddleware',.

      Run php artisan serve on your terminal and open http://localhost:8000/params/scotch. You should see scotch dumped in the browser.

      Method 2: $request->route()->paremeters()

      The other way to access the Route parameters in the middlware involves gettting all the parameters. Imagine you had a route like this /params/{id}/{category}/{name}. All the route params are usually saved in an array, which in a middleware is accessible through $request->route()->parameters(). If we update our route to the above route,

      Route::get('/params/{id}/{category}/{name}', [
          'middleware' => DumpMiddleware',
           function () {
              return view('welcome');
      }]);
      

      And update the middleware’s handle method to,

      public function handle($request, Closure $next)
      {   
          dd($request->route()->parameters());
          return $next($request);
      }
      

      Going to http://localhost:8000/params/23/scotch/school should dump the parametes in your browser as an array, with the parameter names as the keys, and what was passed as values.

      Why Access Route Parameters in Middleware?

      A sample usage for accessing route parameters in middleware is when a given route performs different actions. Say for instance you have a route that returns user’s profiles, /{username}. To go to Scotch’s profile for instance, one would go to http://localhost:8000/scotch.

      This app, however, may have some routes that do not necessarily belong to profiles. Like faq, or support, or help. In such a scenario, it is usually recommended to have these routes defined before the route that looks for a profile.

      app/http/routes.php

      Route::get('/faq', function() {
          return view('faq');
      });
      Route::get('/help', function() {
          return view('help');
      });
      Route::get('/support', function() {
          return view('support');
      });
      
      // Route that handles profile comes last
      Route::get('/{username}', function() {
          return view('profile');
      });
      

      With middleware however, all we need to do is check if a value is in a defined array and redirect.

      app/Http/routes.php

      Route::get('/{username}',  [
           'middleware' => 'ProfileMiddleware',
           function () {
              return view('welcome');
      }]);
      

      Then in the profile middleware, we add this in the handle function.

      <?php
      
      namespace AppHttpMiddleware;
      
      use Closure;
      
      // Add Response namespace
      use IlluminateHttpResponse;
      
      class ProfileMiddleware
      {
          public function handle($request, Closure $next)
          {   
              $routes = ["faq", "support", "help"];
              $route = $request->route('username');
      
          // Redirect to custom page if it doesn't relate to a profile
              if (in_array($route, $routes)) {
                  return new Response(view($route));
              }
      
              return $next($request);
          }
      }
      

      We simply check if the parameter is in a given array, and return a view based on that. In case we have any other keywords that are not neccesarrily profiles, all we need to do is add them to this array. Cleaner, right?



      Source link

      How To Create a Laravel Contact Form and Send Emails with SendGrid


      The author selected the Open Source Initiative to receive a donation as part of the Write for DOnations program.

      Introduction

      Laravel is a free, open source PHP framework, based on Symfony and used for creating web applications. SendGrid is a cloud-based SMTP provider that allows you to send email without having to maintain email servers.

      Having a contact form on your website makes it easier for your visitors to contact you directly. For your contact form to work correctly and send out emails, you need an SMTP server. This tutorial will use SendGrid and their free SMTP service to deliver the emails sent out from the website contact form to an email inbox.

      In this tutorial, you’ll add a contact form to an existing Laravel application and configure it to send emails via SMTP using SendGrid.

      Prerequisites

      If you don’t already have a Laravel application set up, you will need the following:

      After you have set up your Laravel application, you’ll also need the following:

      • A SendGrid account. You can visit the SendGrid registration page to sign up for a free SendGrid account.
      • A fully registered domain name pointed to your server. This tutorial will use your_domain throughout. You can purchase a domain name on Namecheap, get one for free on Freenom, or use the domain registrar of your choice. For DigitalOcean, you can follow this introduction to DigitalOcean DNS for details on how to add them.

      Step 1 — Creating the Sender Identity

      SendGrid requires you to verify the ownership of your domain name before allowing you to start sending emails. In order to verify your domain name, go to your SendGrid account, then go to the Dashboard and click on Authenticate your Domain.

      This will take you to a page where you will need to specify your DNS host and choose if you would like to brand the links for your domain. Email link branding allows you to set all of the links used for click-tracking in your emails to your domain instead of from sendgrid.net.

      SendGrid choose DNS host

      Then click Next and on the next page, specify your domain name.

      SendGrid specify your domain name

      Finally, you will need to add the DNS records provided by SendGrid to complete their verification process. For more information on how to manage your DNS records, you can read this tutorial on How to Create, Edit, and Delete DNS Records.

      SendGrid verify DNS records

      Once you have added the DNS records to your DNS zone, go back to SendGrid and hit the Verify button.

      With your SendGrid Identity verified, you need to generate an API key, which you will use in your Laravel .env file.

      From the menu on the left, click on API Keys and then click on the Create API Key button. For security, set the API Key Permissions to Restricted Access.

      SendGrid Create API Key

      After that, scroll down and add the Mail Send permissions.

      SendGrid send mail permissions

      Finally, click on the Create & View button to get your API key. The API key will only be visible once, so be sure to take note of it in a secure place.

      Now that you’ve configured your domain with SendGrid and generated your API key, you’ll configure the SMTP details for your Laravel application.

      Step 2 — Configuring the SMTP Details

      The .env file in Laravel is used to store various configuration options for your application environment. Since there is usually some sensitive information in the .env file, like your database connection details, you should not commit the .env file to source control.

      If you completed the prerequisite tutorial, you’ll need to be in the /var/www/travellist directory to access your .env file:

      After that, use your favorite text editor open the .env file:

      There are many configuration variables in the .env file—in this tutorial you’ll only change the MAIL variables.

      To do so, find the MAIL_ settings and configure the variables as following, adding in your copied API key to sendgrid_api_key and updating the other highlighted fields as necessary:

      .env

      . . .
      MAIL_MAILER=smtp
      MAIL_HOST=smtp.sendgrid.net
      MAIL_PORT=587
      MAIL_USERNAME=apikey
      MAIL_PASSWORD=sendgrid_api_key
      MAIL_ENCRYPTION=tls
      . . .
      

      The following list contains an overview of the variables that have to be updated in order for your Laravel application to start using the SendGrid SMTP server:

      • MAIL_HOST: The SendGrid SMTP hostname, which will be used for sending out emails.
      • MAIL_PORT: The SendGrid secure TLS SMTP port.
      • MAIL_USERNAME: Your SendGrid username. By default, it is apikey for all accounts.
      • MAIL_PASSWORD: Your SendGrid API Key.
      • MAIL_ENCRYPTION: The mail encryption protocol. In this case you will use TLS as it secures the email content during the transfer between the servers.

      Save and exit the file.

      With your SMTP settings in place, you are ready to proceed and configure your contact controller.

      Step 3 — Creating the Controller

      Next you’ll create a controller that will handle your POST and GET requests for your contact form page.

      You’ll use the GET route to return the HTML page containing your contact form, and the POST route will handle the contact form submissions.

      In order to create a controller called ContactController in Laravel, use the following artisan command:

      • php artisan make:controller ContactController

      After running the command, you will get the following output:

      Output

      Controller created successfully.

      This command will create a new controller at app/Http/Controllers/ContactController.php.

      Run the following to edit the ContactController.php file:

      • nano app/Http/Controllers/ContactController.php

      First, you’ll include the Laravel Mail facade so that you can use the mail functionality in your new controller. A facade in Laravel is a class that provides access to different Laravel features. For more information about Laravel facades, take a look at the official Laravel Facades documentation.

      To include the Laravel Mail facade add the following:

      app/Http/Controllers/ContactController.php

      <?php
      
      namespace AppHttpControllers;
      
      use IlluminateHttpRequest;
      use Mail;
      . . .
      

      Then add the method that will handle your GET requests and return the contact page view:

      app/Http/Controllers/ContactController.php

      . . .
      class ContactController extends Controller
      {
              public function contact(){
                      return view('contact');
              }
      }
      

      Finally, let’s add a method that will handle the POST requests and send out the emails:

      app/Http/Controllers/ContactController.php

      ...
      class ContactController extends Controller
      {
              public function contact(){
                      return view('contact');
              }
      
          public function contactPost(Request $request){
              $this->validate($request, [
                              'name' => 'required',
                              'email' => 'required|email',
                              'comment' => 'required'
                      ]);
      
              Mail::send('email', [
                      'name' => $request->get('name'),
                      'email' => $request->get('email'),
                      'comment' => $request->get('comment') ],
                      function ($message) {
                              $message->from('youremail@your_domain');
                              $message->to('youremail@your_domain', 'Your Name')
                              ->subject('Your Website Contact Form');
              });
      
              return back()->with('success', 'Thanks for contacting me, I will get back to you soon!');
      
          }
      }
      

      Within the highlighted lines, you’ll need to change some of the variables, like so:

      • $message->from('youremail@your_domain');: Change the youremail@your_domain with your actual email address.

      • $message->to('youremail@your_domain', 'Your Name'): The $message->to and the $message->from do not necessarily need to match. You can also change the $message->to value with another email address to which you would like to receive all of your contact form inquiries.

      • subject('Your Website Contact Form');: You can also change the email subject by editing the message inside the subject method.

      Note: the $message->from('youremail@your_domain'); address needs to match the domain name that you used with SendGrid.

      Once you’ve finished these edits, the following will be your full ContactController.php file:

      app/Http/Controllers/ContactController.php

      <?php
      
      namespace AppHttpControllers;
      
      use IlluminateHttpRequest;
      use Mail;
      
      class ContactController extends Controller
      {
          public function contact(){
              return view('contact');
          }
      
          public function contactPost(Request $request){
              $this->validate($request, [
                              'name' => 'required',
                              'email' => 'required|email',
                              'comment' => 'required'
                      ]);
      
              Mail::send('email', [
                      'name' => $request->get('name'),
                      'email' => $request->get('email'),
                      'comment' => $request->get('comment') ],
                      function ($message) {
                              $message->from('youremail@your_domain');
                              $message->to('youremail@your_domain', 'Your Name')
                                      ->subject('Your Website Contact Form');
              });
      
              return back()->with('success', 'Thanks for contacting me, I will get back to you soon!');
      
          }
      }
      

      Save and exit your file once you’ve finished your edits.

      Your Contact Controller has two methods:

      • contact(): This method returns your contact Blade view template, which will hold your HTML page that has the HTML layout for your contact form. Blade is the templating engine that comes with Laravel. In your Blade template views, you can add your HTML structure along with PHP code and Blade syntax.
      • contactPost(): This method handles all of the contact form submissions—where you handle the input validation and send out the emails.

      You handle the validation inside the contactPost() method with the $this->validate() method. Inside the validation method, you specify that the name, email, and comment are required. That way, your users will not be able to submit empty or incomplete contact form inquiries. For more information on how the Laravel validation works, take a look at the official Laravel Validation documentation.

      When validation is successful, the Mail::send() method constructs your email body and subject and then sends out the email.

      Finally, if the email was sent successfully, you return a success message that displays to your users.

      You’ve set up your contact controller and can now move on to GET and POST routes.

      Step 4 — Creating the Routes

      Laravel routes allow you to create SEO-friendly URLs for your application. By using Laravel routes, you can route your application requests to specific controllers, where you handle your application logic.

      You’ll create two routes in your routes/web.php file to use the methods you set up in the previous step.

      You will first create a GET route that maps to your contact method in your ContactController. This method only returns your contact Blade view. Open routes/web.php with the following command:

      Add the GET route at the bottom of the file:

      Note: If you followed the prerequisites, you’ll have different content in you routes/web.php file. You can add your routes to the end of this file as per the instructions in this tutorial.

      routes/web.php

      <?php
      use IlluminateSupportFacadesRoute;
      
      /*
      |--------------------------------------------------------------------------
      | Web Routes
      |--------------------------------------------------------------------------
      |
      | Here is where you can register web routes for your application. These
      | routes are loaded by the RouteServiceProvider within a group which
      | contains the "web" middleware group. Now create something great!
      |
      */
      
      Route::get('/contact', 'ContactController@contact')->name('contact');
      

      You’ll now add a POST route and map it to your contactPost method, which will handle your user contact form submissions:

      routes/web.php

      <?php
      use IlluminateSupportFacadesRoute;
      
      /*
      |--------------------------------------------------------------------------
      | Web Routes
      |--------------------------------------------------------------------------
      |
      | Here is where you can register web routes for your application. These
      | routes are loaded by the RouteServiceProvider within a group which
      | contains the "web" middleware group. Now create something great!
      |
      */
      Route::get('/contact', 'ContactController@contact')->name('contact');
      Route::post('/contact', 'ContactController@contactPost')->name('contactPost');
      

      Once you have your Controller and Route ready, you can save and exit your file then proceed to the next step where you will prepare your Blade views.

      Step 5 — Creating the Blade Views

      In this step you will start by creating a view in the application that will hold your HTML contact form. It will have three input fields:

      • Input field with type text for the email address of the user
      • Input field with type text for the name of the user
      • Text area for the comment

      Create a file called resources/views/contact.blade.php:

      • nano resources/views/contact.blade.php

      Then add the following content:

      resources/views/contact.blade.php

      <!DOCTYPE html>
      <html lang="en">
      
      <head>
          <meta charset="UTF-8">
          <meta name="viewport" content="width=device-width, initial-scale=1.0">
          <title>Contact Form with Laravel and SendGrid</title>
          <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css"
              integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
      </head>
      
      <body>
      
          <div class="container">
              @if(session('success'))
              <div class="alert alert-success">
                {{ session('success') }}
              </div>
              @endif
      
              <form method="POST" action="/contact">
                  @csrf
                  <div class="form-group {{ $errors->has('name') ? 'has-error' : '' }}">
                      <label for="email">Email address</label>
                      <input name="email" type="email" class="form-control" id="email" aria-describedby="emailHelp"
                          placeholder="Enter your email">
                      <span class="text-danger">{{ $errors->first('email') }}</span>
                  </div>
                  <div class="form-group {{ $errors->has('name') ? 'has-error' : '' }}">
                      <label for="name">Name</label>
                      <input name="name" type="text" class="form-control" id="name" aria-describedby="name" placeholder="Your name">
                      <span class="text-danger">{{ $errors->first('name') }}</span>
      
                  </div>
                  <div class="form-group {{ $errors->has('name') ? 'has-error' : '' }}">
                      <label for="exampleInputPassword1">Comment</label>
                      <textarea name="comment" class="form-control" id="exampleFormControlTextarea1" rows="3"></textarea>
                      <span class="text-danger">{{ $errors->first('comment') }}</span>
                  </div>
                  <button type="submit" class="btn btn-primary">Submit</button>
              </form>
          </div>
      
      </body>
      
      </html>
      

      This is an HTML form with a POST method to the /contact route. When someone fills out the contact form, it’ll be handled by your contactPost method.

      The <link> tag inside the <head> tag is used to include Bootstrap. You’re using some styling for the HTML form. You can change the style of the form so that it matches the design of your website. For more information on how to style your website, you can take a look at our CSS resources page.

      The form is wrapped up in different <div> tags with classes from Bootstrap. You’re using the <div> tags to create the structure of the contact form. For more information on how the <div> tags work, check out the How To Use a <div>, the HTML Content Division Element tutorial.

      Save and exit this file.

      The next view that you’ll create is your email view.

      Open the resources/views/email.blade.php file:

      • nano resources/views/email.blade.php

      Then add the following content:

      resources/views/email.blade.php

      Inquiry from: {{ $name }}
      <p> Email: {{ $email }} </p>
      <p> Message: {{ $comment }} </p>
      

      This contains the email content that will be sent to users that complete your contact form. Save and exit the file.

      With the styling and views complete, you’re ready to go ahead and test the contact form.

      To test the contact form, visit http://your_domain/contact via your browser.

      You’ll see the Bootstrap HTML form that you created in the previous step.

      Complete all of the required fields and hit the Submit button. You will receive a green notification that the message was sent successfully.

      Laravel contact form message

      You can test the form by submitting it without filling any of the fields. The validation that you added in your controller will catch that and it’ll inform you that the fields must not be empty.

      Laravel contact form validation

      Finally, you can check your email account and make sure that you’ve received the test email and you can see it in your inbox.

      Conclusion

      You have now successfully added a contact form to your existing Laravel website.

      You can also find more information in the official Laravel documentation.

      To make sure that your contact form is secure, you can install an SSL certificate for your website by following our guide on How To Secure Nginx with Let’s Encrypt.

      To learn more about Laravel, check out our collection of Laravel resources.



      Source link