One place for hosting & domains

      Controllers

      Cleaner Laravel Controllers with Route Model Binding


      Introduction

      Laravel as a framework either for building websites or a container to build APIs (lumen) has evolved as a developer’s framework of choice. Laravel comes with a lot of growing features – take for example Laravel’s events. Events in Laravel used to be a simple pub-sub library, but now Laravel events can broadcast all the way to the client and allows us to create real-time apps.

      But that’s beside the point, today’s celebrity is Laravel’s route model binding.

      What is Route Model Binding

      Route model binding in Laravel provides a mechanism to inject a model instance into your routes. Still not clear on the meaning, here is an example. Say we want to get a post from the database, we could do something like this:

      ...
      // the route parameter is the id of the post
      // for example http://example.com/posts/53
      Route::get('posts/{id}', function ($id) {
      
        // we have to find the post using the $id
        $post = Post::find($id);
      
        // if there is no post, 404
        if (!$post) return abort(404);
      
        // return the view and the post
        return view('post.show', compact('post'));
      });
      ...
      

      We could further go on to simplify this method into

      ...
      // the route parameter is the id of the post
      // for example http://awesome.dev/posts/53
      Route::get('posts/{id}', function ($id) {
      
        // find the post or 404 if not found
        $post = Post::findOrFail($id);
      
        // return the view and the post
        return view('post.show', compact('post'));
      });
      ...
      

      But route model binding helps us get rid of extra keystrokes by simplifying both instances above into

      ...
      // by using $post, we can inject the Post object
      Route::get('posts/{post}', function ($post) {
      
        // we now have access to the $post object! no code necessary
      
        // return the view and the post
        return view('post.show', compact('post'));
      });
      ...
      

      This is made possible by telling Laravel to inject a Post model into any route controller that has a {post} parameter attached to it.

      Laravel currently supports two types of route model bindings. We have:

      • Implicit model binding
      • explicit model binding

      Note: The example of route model binding listed above is explicit.

      Implicit Model Binding

      While we’ve seen explicit model binding, here’s an example of implicit model binding now:

      Route::get('posts/{post}', function (AppPost $post) {
        // be awesome. enjoy having the $post object
      });
      

      Laravel is smart enough to know that since a Post model is being injected into the controller closure, it should get the id parameter from the route and get the details for the user.

      Accessing a post will still be done using http://awesome.example.com/posts/24.

      Changing the Model’s Route Key

      If you would like the implicit model binding to use a database column other than id when retrieving models, you may override the getRouteKeyName method on your Eloquent model.

      For instance, if we wanted to use the slug instead of the id, we could do the following:

      class Post extends Model {
        public function getRouteKeyName() {
          return 'slug';
        }
      }
      

      Then we could access our route using http://awesome.example.com/posts/my-post-slug instead of http://awesome.example.com/posts/24.

      Explicit Model Binding

      Just like the name implies, you have to explicitly tell Laravel you want it to bind a url parameter to a particular model. There are two ways to do this, we could bind a parameter to a model using the provided Route facade or carry out this binding in app/Providers/RouteServiceProvider.php (I prefer this method).

      Using the Route Facade

      Using the Route facade to bind a parameter to a model, we can do something like this:

      Route::bind('post', 'AppPost');
      

      We could also give our binding more meaning, for example, what if we want a post only if is a draft? For that, we could change the second parameter of the Route::bind to a closure which takes the route parameter as its value.

      Route::bind('post', function ($value) {
        return AppPost::find($value)->where('status', '=', 'published')->first();
      });
      

      Using the RouteServiceProvider

      The only difference between using the Route facade and RouteServiceProvider class is that – registering your bindings is done in the boot method of the RouteServiceProvider class (location is app/Providers directory) and the bind method is called on the $router object injected into the method. Quick example

      public function boot(Router $router)
      {
        parent::boot($router);
      
        $router->bind('post', function ($value) {
          return AppPost::find($value)->where('status', '=', 'published')->first();
        });
      }
      

      Custom Exceptions for Route Model Binding

      I build a lot of APIs, so custom exceptions for route model bindings are actually more useful for people like me. Laravel provides an easy way for us to do this. Still in the boot method of the RouteServiceProvider class, call the model method on the $router object.

      The model method takes three arguments, the arguments are similar to that of the bind method, with a new addition the third argument which is a closure that throws the new exception.

      $router->model($routeParameter, $modelToBind, function () {
        throw new NotFoundHTTPException;
      });
      

      Conclusion

      You can read more about route model binding in the documentation.

      Hopefully this small, but neat feature can save you a few lines of code in your projects and make your controllers that much cleaner.



      Source link

      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

      A Beginner's Guide to Kubernetes, Part 4: Controllers


      Updated by Linode

      Contributed by

      Linode

      A Beginner's Guide to Kubernetes

      Note

      A Controller is a control loop that continuously watches the Kubernetes API and tries to manage the desired state of certain aspects of the cluster. There are a number of controllers. Below is a short reference of the most popular controllers you might interact with.

      In this guide you will learn about ReplicaSets, Deployments, and Jobs.

      ReplicaSets

      As has been mentioned, Kubernetes allows an application to scale horizontally. A ReplicaSet is one of the controllers responsible for keeping a given number of replica Pods running. If one Pod goes down in a ReplicaSet, another will be created to replace it. In this way, Kubernetes is self-healing. However, for most use cases it is recommended to use a Deployment instead of a ReplicaSet.

      Below is an example of a ReplicaSet:

      my-apache-replicaset.yaml
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      
      apiVersion: apps/v1
      kind: ReplicaSet
      metadata:
        name: apache-replicaset
        labels:
          app: web
      spec:
        replicas: 5
        selector:
          matchLabels:
            app: web
        template:
          metadata:
            labels:
              app: web
          spec:
            containers:
            - name: apache-container
              image: httpd

      There are three main things to note in this ReplicaSet. The first is the apiVersion, which is apps/v1. This differs from the previous examples, which were all apiVersion: v1, because ReplicaSets do not exist in the v1 core. They instead reside in the apps group of v1. The second and third things to note are the replicas field and the selector field. The replicas field defines how many replica Pods you want to be running at any given time. The selector field defines which Pods, matched by their label, will be controlled by the ReplicaSet.

      To view your ReplicaSets, issue the get replicasets command:

      kubectl get replicasets
      

      You should see output like the following:

      NAME                DESIRED   CURRENT   READY   AGE
      apache-replicaset   5         5         0       5s
      

      This output shows that of the five desired replicas, there are 5 currently active, but zero of those replicas are available. This is because the Pods are still booting up. If you issue the command again, you will see that all five have become ready:

      NAME                DESIRED   CURRENT   READY   AGE
      apache-replicaset   5         5         5       86s
      

      You can view the Pods the ReplicaSet created by issuing the get pods command:

      kubectl get pods
      

      You should see output like the following:

      NAME                      READY   STATUS    RESTARTS   AGE
      apache-replicaset-5rsx2   1/1     Running   0          31s
      apache-replicaset-8n52c   1/1     Running   0          31s
      apache-replicaset-jcgn8   1/1     Running   0          31s
      apache-replicaset-sj422   1/1     Running   0          31s
      apache-replicaset-z8g76   1/1     Running   0          31s
      

      To delete a ReplicaSet, issue the delete replicaset command:

      kubectl delete replicaset apache-replicaset
      

      If you issue the get pods command, you will see that the Pods the ReplicaSet created are in the process of terminating:

      NAME                      READY   STATUS        RESTARTS   AGE
      

      apache-replicaset-bm2pn 0/1 Terminating 0 3m54s

      In the above example, four of the Pods have already terminated, and one is in the process of terminating.

      For more information on ReplicaSets, view the Kubernetes ReplicaSets API documentation.

      Deployments

      A Deployment can manage a ReplicaSet, so it shares the ability to keep a defined number of replica Pods up and running. A Deployment can also update those Pods to resemble the desired state by means of rolling updates. For example, if you wanted to update a container image to a newer version, you would create a Deployment, and the controller would update the container images one by one until the desired state is achieved. This ensures that there is no downtime when updating or altering your Pods.

      Below is an example of a Deployment:

      my-apache-deployment.yaml
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      
      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: apache-deployment
        labels:
          app: web
      spec:
        replicas: 5
        selector:
          matchLabels:
            app: web
        template:
          metadata:
            labels:
              app: web
          spec:
            containers:
            - name: apache-container
              image: httpd:2.4.35

      The only noticeable difference between this Deployment and the example given in the ReplicaSet section is the kind. In this example we have chosen to initially install Apache 2.4.35. If you wanted to update that image to Apache 2.4.38, you would issue the following command:

      kubectl --record deployment.apps/apache-deployment set image deployment.v1.apps/apache-deployment apache-container=httpd:2.4.38
      

      You’ll see a confirmation that the images have been updated:

      deployment.apps/apache-deployment image updated
      

      To see for yourself that the images have updated, you can grab the Pod name from the get pods list:

      kubectl get pods
      
      NAME                                 READY   STATUS    RESTARTS   AGE
      apache-deployment-574c8c4874-8zwgl   1/1     Running   0          8m36s
      apache-deployment-574c8c4874-9pr5j   1/1     Running   0          8m36s
      apache-deployment-574c8c4874-fbs46   1/1     Running   0          8m34s
      apache-deployment-574c8c4874-nn7dl   1/1     Running   0          8m36s
      apache-deployment-574c8c4874-pndgp   1/1     Running   0          8m33s
      

      Issue the describe command to view all of the available details of the Pod:

      kubectl describe pod apache-deployment-574c8c4874-pndgp
      

      You’ll see a long list of details, of which the container image is included:

      ....
      
      Containers:
        apache-container:
          Container ID:   docker://d7a65e7993ab5bae284f07f59c3ed422222100833b2769ff8ee14f9f384b7b94
          Image:          httpd:2.4.38
      
      ....
      

      For more information on Deployments, visit the Kubernetes Deployments API documentation

      Jobs

      A Job is a controller that manages a Pod that is created for a single, or set, of tasks. This is handy if you need to create a Pod that performs a single function, or calculates a value. The deletion of the Job will delete the Pod.

      Below is an example of a Job that simply prints “Hello World!” and ends:

      my-job.yaml
       1
       2
       3
       4
       5
       6
       7
       8
       9
      10
      11
      12
      13
      14
      15
      16
      17
      
      apiVersion: batch/v1
      kind: Job
      metadata:
        name: hello-world
      spec:
        template:
          metadata:
            name: hello-world
          spec:
            containers:
            - name: output
              image: debian
              command:
               - "bin/bash"
               - "-c"
               - "echo 'Hello World!'"
            restartPolicy: Never

      To create the Job, issue the create command:

      kubectl create -f my-job.yaml
      

      To see if the job has run, or is running, issue the get jobs command:

      kubectl get jobs
      

      You should see output like the following:

      NAME          COMPLETIONS   DURATION   AGE
      hello-world   1/1           9s         8m23s
      

      To get the Pod of the Job, issue the get pods command:

      kubectl get pods
      

      You should see an output like the following:

      NAME                               READY   STATUS             RESTARTS   AGE
      hello-world-4jzdm                  0/1     Completed          0          9m44s
      

      You can use the name of the Pod to inspect its output by consulting the log file for the Pod:

      kubectl get logs hello-world-4jzdm
      

      To delete the Job, and its Pod, issue the delete command:

      kubectl delete job hello-world
      

      Next Steps

      There are other controllers not listed in this guide that you may find useful. Visit the official Kubernetes documentation for more information.

      To continue in the Beginner’s Guide to Kubernetes series, visit part 5:

      More Information

      You may wish to consult the following resources for additional information on this topic. While these are provided in the hope that they will be useful, please note that we cannot vouch for the accuracy or timeliness of externally hosted materials.

      Find answers, ask questions, and help others.

      This guide is published under a CC BY-ND 4.0 license.



      Source link