Skip to content

Instantly share code, notes, and snippets.

@suwardany
Last active April 29, 2016 15:19
Show Gist options
  • Star 8 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save suwardany/e7b0d5d7da18cfe76908 to your computer and use it in GitHub Desktop.
Save suwardany/e7b0d5d7da18cfe76908 to your computer and use it in GitHub Desktop.
Setup a blog extension with Cartalyst Platform 2

Setup a blog extension with Cartalyst Platform 2

Download Platform

git clone https://github.com/cartalyst/platform.git blog

Install Dependencies

Navigate into the downloaded folder and run

composer install

Setup Platform

Platform can be installed either through the browser or terminal,

Browser

Navigate to your vhost, the installer will appear, follow instructions.

Terminal

run php artisan platform:install and follow instructions.

Create a new extension

Note If you want platform to install the extension for you, make sure you create a workbench directory that is writable by the webserver in your project root before proceeding with the next step.

Open the app in the browser, Sign in, go to Admin

Under Operations choose Workshop

Fill out the fields as follows

Author Name: Cartalyst Author Email: help@cartalyst.com Vendor: cartalyst Name: blog Version: 0.1.0 Description: A Platform 2 Blog Extension

Components: Admin components Frontend components

Install Method: Automatic

Click on Save

Configure Extension

We'll start by defining our routes on workbench/cartalyst/blog/extension.php

under routes around #186 we'll define our routes as follows

// Admin routes
Route::group(array('prefix' => admin_uri().'/blog', 'namespace' => 'Cartalyst\Blog\Controllers\Admin'), function()
{
	Route::get('/', 'BlogController@index');
	Route::get('grid', 'BlogController@grid');
	Route::get('create', 'BlogController@create');
	Route::post('create', 'BlogController@store');
	Route::get('{id}/edit', 'BlogController@edit');
	Route::post('{id}/edit', 'BlogController@update');
	Route::get('{id}/delete', 'BlogController@delete');
});

// Frontend routes
Route::group(array('prefix' => 'blog', 'namespace' => 'Cartalyst\Blog\Controllers\Frontend'), function()
{
	Route::get('/', 'BlogController@index');
	Route::get('{id}', 'BlogController@show');
});

Setup migrations


Now, let's create our blog migrations

Navigate to your project directory in the terminal,

run php artisan migrate:make create_posts_table --path="workbench/cartalyst/blog/database/migrations" --create posts

Now we need to add title and body fields to our migration, navigate to the newly created migration and add the missing fields to match the following

Schema::create('posts', function(Blueprint $table)
{
	$table->increments('id');

	$table->string('title');
	$table->text('body');

	$table->timestamps();
});

Setup our model


Let's create our Post model .. workbench/cartalyst/blog/src/Post.php

<?php namespace Cartalyst\Blog;

use Eloquent;
use Str;
use Carbon\Carbon;

class Post extends Eloquent {

	protected $appends = array('summary');

	protected $guarded = array(
		'id',
		'created_at',
		'updated_at',
	);

	public function getSummaryAttribute($item)
	{
		return Str::words(strip_tags($this->body), 60, '...');
	}

	public function getCreatedAtAttribute($item)
	{
		return Carbon::parse($item)->format('M d, Y');
	}

}

Setup our controllers


Admin Controller workbench/cartalyst/blog/src/Controllers/Admin/BlogController.php

<?php namespace Cartalyst\Blog\Controllers\Admin;

use Platform\Admin\Controllers\Admin\AdminController;
use View;
use Input;
use DataGrid;
use Redirect;
use Sentry;
use Platform\Users\Repositories\DbUserRepository as User;
use Cartalyst\Blog\Post;

class BlogController extends AdminController {

	/**
	 * Holds the post instance.
	 *
	 * @var \Cartalyst\Blog\Post
	 */
	protected $post;

	/**
	 * Constructor.
	 *
	 * @param  \Cartalyst\Blog\Post  $post
	 * @return void
	 */
	public function __construct(Post $post)
	{
		parent::__construct();

		$this->post = $post;
	}

	/**
	 * Datasource for the blogs Data Grid.
	 *
	 * @return \Cartalyst\DataGrid\DataGrid
	 */
	public function grid()
	{
		return DataGrid::make($this->post->all(), array(
			'id',
			'title',
			'created_at',
		));
	}

	/**
	 * Return the main administration screen.
	 *
	 * @return \Illuminate\View\View
	 */
	public function index()
	{
		return View::make('cartalyst/blog::index');
	}

	/**
	 * Return create form.
	 * @param  int $id
	 * @return \Illuminate\View\View
	 */
	public function create()
	{
		return $this->showForm('create');
	}

	/**
	 * Return edit form.
	 * @param  int $id
	 * @return \Illuminate\View\View
	 */
	public function edit($id)
	{
		return $this->showForm('edit', $id);
	}

	/**
	 * Update the specified post.
	 * @param  int $id
	 * @return \Illuminate\Http\RedirectResponse
	 */
	public function update($id)
	{
		$post = $this->post->find($id);
		$post->fill(Input::except('_token'));
		if ($post->save())
		{
			return Redirect::toAdmin("blog/{$post->id}/edit")->withSuccess('Post Successfully updated.');
		}
		else
		{
			return Redirect::toAdmin('blog')->withSuccess('There was an error updating your post.');
		}
	}

	/**
	 * Show create / edit form.
	 *
	 * @param  string $mode
	 * @param  int $id
	 * @return \Illuminate\View\View
	 */
	public function showForm($mode, $id = null)
	{
		$post = $id ? $this->post->find($id) : $this->post;

		return View::make('cartalyst/blog::form')->with(compact('post', 'mode'));
	}

	/**
	 * Save post.
	 *
	 * @return \Illuminate\Http\RedirectResponse
	 */
	public function store()
	{
		$input = Input::except('token');

		$post = Post::create($input);

		return Redirect::toAdmin("blog/{$post->id}/edit")->withSuccess('Post successfully created.');
	}

	/**
	 * Remove the specified post.
	 *
	 * @param  int  $id
	 * @return \Illuminate\Http\RedirectResponse
	 */
	public function delete($id)
	{
		// Delete the page
		if ($this->post->find($id)->delete())
		{
			return Redirect::toAdmin('blog')->withSuccess('Post successfully deleted.');
		}

		return Redirect::toAdmin('blog')->withErrors('An error occured, please try again later.');
	}

}

Frontend Controller workbench/cartalyst/blog/src/Controllers/Frontend/BlogController.php

<?php namespace Cartalyst\Blog\Controllers\Frontend;

use Platform\Foundation\Controllers\BaseController;
use View;
use Cartalyst\Blog\Post;

class BlogController extends BaseController {

	/**
	 * Return the main administration screen.
	 *
	 * @return Illuminate\View\View
	 */
	public function index()
	{
		$posts = Post::paginate(8);

		return View::make('cartalyst/blog::index')->with(compact('posts'));
	}

	/**
	 * Return the post view.
	 * @param  int $id
	 * @return \Illuminate\View\View
	 */
	public function show($id)
	{
		$post = Post::find($id);

		return View::make('cartalyst/blog::show')->with(compact('post'));
	}

}

Setup our views


Admin

Data Grid Templates

workbench/cartalyst/blog/themes/admin/default/packages/cartalyst/blog/views/datagrid.blade.php

<script type="text/template" data-grid="main" data-template="results">

	<% _.each(results, function(r) { %>

		<tr>
			<td><%= r.title %></td>
			<td><%= r.created_at %></td>
			<td>
				<a class="btn btn-primary tip" href="{{ URL::toAdmin('blog/<%= r.id %>/edit') }}" title="{{{ trans('button.edit') }}}"><i class="fa fa-edit"></i></a>

				<a class="btn btn-danger tip" data-toggle="modal" data-target="modal-confirm" href="{{ URL::toAdmin('blog/<%= r.id %>/delete') }}" title="{{{ trans('button.delete') }}}"><i class="fa fa-trash-o"></i></a>
			</td>
		</tr>

	<% }); %>

</script>

<script type="text/template" data-grid="main" data-template="filters">

	<% _.each(filters, function(f) { %>

		<span>

			<button type="button" class="btn btn-info tip" title="{{{ trans('general.remove_filter') }}}">

				<% if (f.column === 'all') { %>

					<%= f.value %>

				<% } else { %>

					<%= f.value %> {{{ trans('general.in') }}} <em><%= f.column %></em>

				<% } %>

				<i class="fa fa-times"></i>

			</button>

		</span>

	<% }); %>

</script>

<script type="text/template" data-grid="main" data-template="no_results">
	<tr>
		<td colspan="5">No results.</td>
	</tr>
</script>

<script type="text/template" data-grid="main" data-template="pagination">

	<% _.each(pagination, function(p) { %>

		<div>

			<div class="pull-right">

				<ul class="pagination pagination-sm">

					<% if (p.previous_page !== null) { %>

						<li><a data-grid="main" data-page="<%= p.previous_page %>"><i class="fa fa-chevron-left"></i></a></li>

					<% } else { %>

						<li class="disabled"><span><i class="fa fa-chevron-left"></i></span></li>

					<% } %>

					<% if (p.next_page !== null) { %>

						<li><a data-grid="main" data-page="<%= p.next_page %>"><i class="fa fa-chevron-right"></i></a></li>

					<% } else { %>

						<li class="disabled"><span><i class="fa fa-chevron-right"></i></span></li>

					<% } %>

				</ul>

			</div>

			Showing <%= p.page_start %> to <%= p.page_limit %> of <span class="total"><%= p.filtered %></span>

		</div>

	<% }); %>

</script>

Admin index

workbench/cartalyst/blog/themes/admin/default/packages/cartalyst/blog/views/index.blade.php

@extends('layouts/default')

{{-- Page title --}}
@section('title')
Blog ::
@parent
@stop

{{-- Queue Assets --}}
{{ Asset::queue('underscore', 'underscore/js/underscore.js', 'jquery') }}
{{ Asset::queue('data-grid', 'cartalyst/js/data-grid.js', 'underscore') }}

{{-- Inline scripts --}}
@section('scripts')
@parent
<script>
$(function() {

	var dg = $.datagrid('main', '.data-grid', '.pagination', '.filters', {
		loader: '.loading',
		scroll: '.data-grid',
		callback: function()
		{
			$('#checkAll').prop('checked', false);

			$('#actions').prop('disabled', true);
		}
	});

});
</script>
@stop

{{-- Page content --}}
@section('content')

<div class="col-md-12">

	{{-- Page header --}}
	<div class="page-header">

		<span class="pull-right">

			<a class="btn btn-warning" href="{{ URL::toAdmin('blog/create') }}"><i class="fa fa-plus"></i> Create</a>

		</span>

		<h1>Blog</h1>

	</div>

	{{-- Data Grid : Search --}}
	<div class="row">

		<div class="col-lg-12 text-right">

			<form method="post" action="" accept-charset="utf-8" data-search data-grid="main" class="form-inline" role="form">

				<div class="form-group">

					<div class="loading"></div>

				</div>

				<div class="form-group">
					<select class="form-control" name="column">
						<option value="all">All</option>
						<option value="title">Title</option>
					</select>
				</div>

				<div class="form-group">
					<input name="filter" type="text" placeholder="Search" class="form-control">
				</div>

				<button class="btn btn-default"><i class="fa fa-search"></i></button>

			</form>

		</div>

	</div>

	<br />

	{{-- Data Grid : Content --}}
	<table data-source="{{ URL::toAdmin('blog/grid') }}" data-grid="main" class="data-grid table table-striped table-bordered table-hover">
		<thead>
			<tr>
				<th data-sort="title" data-grid="main" class="col-md-3 sortable">Title</th>
				<th data-sort="created_at" data-grid="main" class="col-md-3 sortable">Created at</th>
				<th class="col-md-2"></th>
			</tr>
		</thead>
		<tbody></tbody>
	</table>

	{{-- Data Grid : Pagination --}}
	<div class="pagination" data-grid="main"></div>

</div>
@stop

{{-- Data Grid : Templates --}}
@include('cartalyst/blog::datagrid')

Form View

workbench/cartalyst/blog/themes/admin/default/packages/cartalyst/blog/views/form.blade.php

@extends('layouts/default')

{{-- Page title --}}
@section('title')
{{$mode}} Blog Post ::
@parent
@stop

{{-- Page content --}}
@section('content')

<div class="col-md-12">

	<div class="page-header">

		<h1>{{ucfirst($mode)}} <small>Blog Post</small></h1>

	</div>

	{{ Form::open() }}

		<div class="form-group">
			{{ Form::label('title') }}
			{{ Form::text('title', Input::old('title', $post->exists ? $post->title : null), array('class' => 'form-control')) }}
		</div>

		<div class="form-group">
			{{ Form::label('body') }}
			{{ Form::textarea('body', Input::old('body', $post->exists ? $post->body : null), array('class' => 'form-control')) }}
		</div>

		<div class="form-group">
			{{ Form::submit('Save', array('class' => 'btn btn-success')) }}
		</div>

	{{ Form::close() }}

</div>

@stop

Frontend

Index view

workbench/cartalyst/blog/themes/frontend/default/packages/cartalyst/blog/views/index.blade.php

@extends('layouts/default')

{{-- Page title --}}
@section('title')
Blog
@parent
@stop

{{-- Meta description --}}
@section('meta-description')
Cartalyst Blog
@stop

{{-- Page content --}}
@section('content')

<div class="container">

		<div class="col-md-12">
			<h2 class="text-center">Blog</h2>

			@foreach($posts as $post)

				<article>

					<h3><a href='{{ URL::to("blog/{$post->id}") }}'>{{ $post->title }}</a> <small>{{ $post->created_at }}</small></h3>
					<p>{{ $post->summary }}</p>

				</article>

			@endforeach

			<div class="text-center">
				{{ $posts->links() }}
			</div>
		</div>

</div>

@stop

Single post view

workbench/cartalyst/blog/themes/frontend/default/packages/cartalyst/blog/views/show.blade.php

@extends('layouts/default')

{{-- Page title --}}
@section('title')
Cartalyst Blog
@parent
@stop

{{-- Meta description --}}
@section('meta-description')
Cartalyst Blog
@stop

{{-- Page content --}}
@section('content')

<div class="container">

	<div class="col-md-12">

		<h2 class="text-center">Blog</h2>

		<article>

			<h2>{{ $post->title }}</h2>
			<p>{{ $post->body }}</p>

		</article>

	</div>

</div>

@stop

Publish Theme

run php artisan theme:publish --extension=cartalyst/blog

Install Extension

Now that we've prepared our files, we can continue and install the extension.

Navigate to your admin dashboard, under Operations choose Extensions,

Click on the edit button next to your extension

Click Install, this will install and run your extensions migrations.

Click Enable.

Done

At this point, you should find a new Blog menu item on the admin dashboard, navigate to it and start creating posts!

On the frontend, you will find a blog menu item as well, navigate to it to find your blog listings.

Autoloading Note

This package's autoloading happens automatically after generating the migration,

php artisan dump-autoload is invoked right after the migration is created.

If you do not create any migrations, or you're installing your package from scratch, you have to manually dump-autoload.

You can dump-autoload your workbench package using one of the following methods

From your project root

run php artisan dump-autoload

This will also run for all of your workbenches.

From your package directory

run composer dump-autoload

This will dump the required files for auto loading.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment