Crafting a CMS package with Laravel 5 - Part 2

So it has been a while! Sorry for that! Lets dive right in! And don't waste more time! In part 1 we created our basic laravel application and saw how we just did the basic setup, now let us start on the coding!

Creating our folder structure for our CMS package!

Since the workbench has been removed from Laravel 5 we are going to use a basic Namespaced folder for our package since that is actually everything that we need.

Lets create a folder in the main project folder to start with.
With the terminal type:
mkdir Cms

Now we are also going to need more folders inside the Cms folder, lets see what we our going to need:

  • Application logic
  • Assets (images, css, js)
  • Configuration files
  • Migration for our database

And that will cover the basics, so lets create the following structure:

/Cms
↳  migrations
↳  config
↳ src
    ↳ Providers
    ↳ Http
        ↳ Controllers
↳  public

so now we are having a nice starter structure to place our files in.

But John where is the tests folder?

Well I don't want to make this more complicated than it already is, and stick with the basics.

Open the composer.json file and add our namespace to the autoload -> psr-4 what will look like the following:

"autoload": {
    "classmap": [
        "database"
    ],
    "psr-4": {
        "blimp\\": "app/",
        "Cms\\": "Cms/"
    }
},

Now when we will run composer dump-autoload the folder will be scanned and the files inside it will be autoloaded so we can use it anywhere in our Laravel application.

Our starting provider.

So now the first thing we are going to do is make a new Provider so our package can be loaded, and bind all the package logic to the right places.

Lets create our provider in Cms/src/Providers I will call it BlimpServiceProvider.html?php namespace Cms\Providers; use Illuminate\Support\ServiceProvider; class BlimpServiceProvider extends ServiceProvider { /** * Bootstrap the application services. * * @return void */ public function boot() { // } /** * Register the application services. * * @return void */ public function register() { // } }

Awesome now we can load that sucker into our application! Lets do it go to config/app.html'providers' => [ #.... 'Cms\Providers\CmsServiceProvider' ]

Lets run a quick composer dump-autoload in the root of our project to load the added psr-4 namespace. Run php artisan serv to start a server on https://localhost:8000 and we should see a beautifull:

BAM!

That was pretty easy wasn't it!

Loading our routes!

So now that everything is set up we can start defining some routes! let us create a new Provider called RouteServiceProvider to define our routes in the path Cms\Providers open up the file and lets paste in the following!

<?php namespace Cms\Providers;

use Illuminate\Routing\Router;  
use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider;

class RouteServiceProvider extends ServiceProvider {

    protected $namespace = 'Cms\Http\Controllers';

    public function map(Router $router)
    {
        $router->group(['namespace' => $this->namespace], function($router)
        {
            // Your routes here..
        });
    }

}

Notice the protected $namespace in there it prefixes the namespace for all the routes we are going to load through this provider.

Since we are going to want our admin to load from a specific url for example https://blimp.dev/admin we need to have a prefix for all our routes that needs prefixing (What is basicly all routes in our CMS). Add this to the existing map() function. We can use the prefix key here.

$router->group(['prefix' => 'admin', 'namespace' => $this->namespace], function($router)

So lets take a step back and think what probably would be the first thing we might expect when we browse to /admin. I think since we are not logged in we should be redirected to some kind of login form. so lets see how we might add this to the route. To start off simple lets do it as following:

$router->get('/', function () {
    if (app('auth')->guest()) {
      return redirect()->guest('admin/login');
    }

      return redirect()->to('admin/dashboard');
});

$router->controllers([
    '/' => 'AuthController',
]);

Be aware you see Auth\AuthController being referenced here however since it is being prefixed with $this->namespace the actual full namespace is Cms\Http\Controllers\AuthController.

Also we should extract the redirects to a middleware to take care of this for us however we will do this later. Let us just start making this basic auth work. And later we will refine everything.

Now the RouteServiceProvider is not beeing loaded yet. We need to register it into the application we can do this in the CmsServiceProvider in the register() method lets register the provider into our application like following:

public function register()  
{
    $this->app->register(RouteServiceProvider::class);
}

fyi. in this context RouteServiceProvider::class references the class RouteServiceProvider and returns the class with full namespace so in this case it will return Cms\Providers\RouteServiceProvider.

Offcourse the controller does not exist yet so lets create him right now Cms/Http/Controllers/AuthController.html?php namespace Cms\Http\Controllers; use Illuminate\Routing\Controller; use Illuminate\Contracts\Auth\Guard; use Illuminate\Contracts\Auth\Registrar; use Illuminate\Foundation\Auth\AuthenticatesAndRegistersUsers; class AuthController extends Controller { use AuthenticatesAndRegistersUsers; public function __construct(Guard $auth, Registrar $registrar) { $this->auth = $auth; $this->registrar = $registrar; $this->middleware('guest', ['except' => 'getLogout']); } }

As you can see at this point it's almost identical as the file Laravel is providing right out of the box app/Http/Controllers/Auth/AuthController.html"https://localhost:8000/admin">https://localhost:8000/admin And you should be redirected to /admin/login and see a nice bootstrap login Form. This is because we are using the trait AuthenticatesAndRegistersUsers and inside that trait there is a method called getLogin what is returning view('auth.login');. Offcourse nothing else is working just yet we still have alot more to be done! But have a play with this thing and just look at the existing laravel structure what would be nice to do next? I will wrap it up here

In the next part:

  • Using the Auth provider for our authentication.
  • Creating our migrations.
  • Loading the configuration.
  • Publishing the vendor assets / languages