0xC0CAC0DA

Rants and code from PolCPP.

How to Install and Use Laravel Administrator Part 1

Trying to get FrozenNode’s laravel administrator bundle to work, i saw that there was no guide that set you up from zero to go with Laravel and administrator. This set of guides will cover the basic Laravel setup with administrator and later on setting up more advanced models.

First of all we install Laravel, get inside the directory and install frozennode administrator.

composer create-project laravel/laravel admin_project --prefer-dist
cd admin_project
composer require frozennode/administrator:dev-master

Make sure you add this line to the providers array in /app/config/app.php

'Frozennode\Administrator\AdministratorServiceProvider',

Once this is done you just have to publish the config and assets into the project with these two commands.

php artisan config:publish frozennode/administrator 
php artisan asset:publish frozennode/administrator

Now we setup the project to work locally on the database.

  1. Edit the start.php to add your computer name to the array.

     $env = $app->detectEnvironment(array(
         'local' => array('homestead','myComputer'),
     ));
    
  2. Edit app/config/local/database.php with working database settings. If the file doesn’t exist make a copy from app/config/database.php

And it’s installed! But we’re not done yet.

Creating a simple auth

Administrator is auth agnostic so you can use your own custom built auth, Sentry or any plugabble auth system compatible with Laravel, in our case we’ll build a simple auth system based on Laravel auth that will let us in.

If you have your own custom login procedure you can completely skip this step.

I’m going to use Jeffrey Way generators to make things faster so we install it too.

composer require --dev way/generators:dev-master

Like with administrator we add it to providers

'Way\Generators\GeneratorsServiceProvider'

Now with al the tools installed, let’s get to work and create the migration and seed.

php artisan generate:migration create_users_table --fields="username:string, email:string, password:string"
php artisan generate:seed user

We edit the UserTableSeeder.php that we generated in app/database/seeds and replace its contents with this.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php

class UserTableSeeder extends Seeder {

  public function run()
  {
      User::create([
          'username'   => 'admin',
          'email'      => 'admin@mysite.com',
          'password'   => Hash::make('thepass'),
          'created_at' => new DateTime(),
          'updated_at' => new DateTime()
      ]);
  }

}

To make it work we’ll need to uncomment the following line from DatabaseSeeder.php (same directory as UserTableSeeder).

$this->call('UserTableSeeder');

Now let’s migrate the database and seed it before building the login page and it’s controllers.

php artisan migrate
php artisan db:seed

And with this we have our database up and running, with a working user. Time to build the controller and templates to be able to log in.

php artisan generate:controller LoginController

Before starting to add the controllers we’ll add a route editing app/routes.php so Laravel shows us the login page when we go to myCoolSite.com/login

Route::controller('/login', 'LoginController');

Now we’ll edit our login controller and leave it like this.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<?php

class LoginController extends \BaseController {

 
  public function getIndex()
  {
      return View::make('login.index');
  }
 
  public function postIndex()
  {
      $username = Input::get('username');
      $password = Input::get('password');
 
      if (Auth::attempt(['username' => $username, 'password' => $password]))
      {
          return Redirect::intended('/admin');
      }
 
      return Redirect::back()
          ->withInput()
          ->withErrors('Username or Password are incorrect.');
  }
}

What we’re doing here is pretty simple. When the user navigates to /login we’ll display him a login form, and when sendsthat form we’ll auth him, in case it fails we’ll redirect them back with an error message.

Since we have the controller done let’s build the templates

First we’re going to build the structure. We’ll need a base template that we’ll store on app/views/layouts. and then our login.index view that we will store on views/login

So let’s start with the base template (app/views/layouts/master.blade.php)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!DOCTYPE html>
<html lang='en'>
  <head>
      <meta http-equiv="content-type" content="text/html; charset=UTF-8"> 
      <meta charset="utf-8">
      <meta name='viewport' content='width=device-width, initial-scale=1'>

      <title>@yield('title')</title> 
      <link rel='stylesheet' href='//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css'>
      <style>
          body {
              margin-top: 10px;
          }
      </style>
  </head>
  <body>
      <div class='container-fluid'>
          <div class='row'>
              @yield('content')
          </div>
      </div>
  </body>
</html>

Nothing really fancy here we setup some placeholders like the Title and we just get the latest bootstrap version (3.1.1) and build some basic html.

Now let’s get to the login template which i’m basing on this. So create app/views/login/index.blade.php and add these contents:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
@extends('layouts.master')

@section('title') Login @stop

@section('content')
<div class="col-md-4 col-md-offset-4">
        <div class="panel panel-default">
                <div class="panel-heading">
                        <h3 class="panel-title">Please sign in</h3>
                </div>
                <div class="panel-body">
                        @if ($errors->has())
                                @foreach ($errors->all() as $error)
                                        <div class='alert-danger alert'>{{ $error }}</div>
                                @endforeach
                        @endif

                        {{ Form::open(['role' => 'form']) }}
                        <fieldset>
                                <div class="form-group">
                                        {{ Form::text('username', null, ['placeholder' => 'Username', 'class' => 'form-control']) }}
                                </div>
                                <div class="form-group">
                                        {{ Form::password('password', ['placeholder' => 'Password', 'class' => 'form-control']) }}
                                </div>
                                        {{ Form::submit('Login', ['class' => 'btn btn-primary']) }}
                        </fieldset>
                        {{ Form::close() }}
                </div>
        </div>
</div>
@stop

And that it. If we run it using php artisan serve navigate to localhost:8000/login and try to login with incorrect credentials will fail, and if we set the correct ones we’ll get redirected to /admin which will give us an administrator error, because we haven’t configured it yet!

Configuring administrator and our first “model-admin”

First of all we’ll need to create a few directories as per our config.

Open app/config/packages/frozennode/administrator/administrator.php (if you don’t have it make sure you ran php artisan config:publish frozennode/administrator on the first step.)

Administrator needs a few directories and files to work that are setup on the following variables

'model_config_path' => app('path') . '/config/administrator',
'settings_config_path' => app('path') . '/config/administrator/settings',

You can change those values to existant directories or just create the path, in our case we’ll create app/config/administrator and app/config/administrator/settings.

Next we’ll need to add a menu option so administrator shows someting on it (it’s required). So we’ll edit the menu array and add ‘users’. It’s important that the menu names are the same than the ones from the model config options, including case.

'menu' => array('users'),

We’ll also edit the home_page so it displays us the users editor when we go to /admin.

'home_page' => 'users',  

Finally since our login page is /login we need to change the login_path variable to login

'login_path' => 'login',

And that’s all for now. If you try to load we’ll still get an error, that’s because we haven’t configured the user model editor, so time to create our users.php in app/config/administrator.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
 <?php

  /**
   * Users model config
   */

  return array(

      'title' => 'Users',
      'single' => 'user',
      'model' => 'User',

      'columns' => array(
          'email' => array(
              'title' => 'Email',
          ),
          'username' => array(
              'title' => 'First Name',
          ),
      ),

      'edit_fields' => array(
          'email' => array(
              'title' => 'Email',
              'type' => 'text',
          ),
          'username' => array(
              'title' => 'Username',
              'type' => 'text',
          ),
          'password' => array(
              'title' => 'Password',
              'type' => 'password',
          ),
      ),
  );

That seems a lot of code but it’s pretty simple.

  1. Title. Refers to the page/menu titles.

  2. Single. The singular name of the model. It’s used to fill the administrator texts like the “Create User” button.

  3. Model. The model name.

  4. Columns. The columns you want to display on the list viewer of the model.

  5. Edit_fields. The fields you want to be able to edit/create. If you want to know more details on the fields, check the following site

There are a lot of configurable settings so check http://administrator.frozennode.com/docs/model-configuration to see all that you can build with administrator.

And that’s it. There are a few details that you should have in mind though. First is that if we leave it like this the passwords that we save will be stored in plain text and won’t work for authorization. But you can fix that easily adding this mutator to the User model.

public function setPasswordAttribute($value)
{
    $this->attributes['password']  = $value;
}

And we’re done, kinda, try to add an user and leave it blank. Even if we have nulls on our database it saves blank characters, and we shouldn’t allow that. Don’t worry, validation to the rescue. Add this to the model and we will have validation.

public static $rules = array(
        'username' => 'required',
        'email' => 'required|email|unique:users',
        'password' => 'required|min:8',        
);

I recommend you to put those validation rules on the model instead of using the administrator rules option. The reaons is that on fields like password that has mutators it would give false positives since hashing an empty value would create a hash that would pass the validation.

And that’s all for Part 1. On part 2 we’ll create a real case of a view/admin and add it to this project.

You can clone/view the repo of this project here