Category Archives: Laravel

Grouped by date

This is the most elegant way to do this would be to pass a closure into 
the groupBy() collection method.

$posts_by_date = Post::all()->groupBy(function($date) {
return Carbon::parse($date->created_at)->format('Y-m');
});
Then you can loop through it in your blade template similar to this:

@foreach ($posts_by_date as $date => $posts)
<h2>{{ $date }}</h2>
@foreach ($posts as $post)
<h3>{{ $post->title }}</h3>
{{ $post->content }}
@endforeach
@endforeach
shareimprove this answer
answered Mar 18 '14 at 17:06


Very elegant ! One problem by default, the sort is asc ! Start to 2013, 
2014 etc... How to to sort it in desc ? – kesm0 May 20 at 10:01

I find the solution : News::orderBy('created_at', 
'desc')->get()->groupBy(function($date) – kesm0 May 20 at 10:08

Generating archive list for a blog in Laravel

$posts_by_date = Post::all()->groupBy(function($date) {
    return Carbon::parse($date->created_at)->format('Y-m');
});

Then you can loop through it in your blade template similar to this:

@foreach ($posts_by_date as $date => $posts)
    <h2>{{ $date }}</h2>
    @foreach ($posts as $post)
        <h3>{{ $post->title }}</h3>
        {{ $post->content }}
    @endforeach
@endforeach
I find the solution : News::orderBy(‘created_at’, ‘desc’)->get()->groupBy(function($date)

Sortable index view tables with Laravel 4

In this article I would like to share how to make a sortable index view with Laravel 4.

Let’s assume you have an index view with a table. Like this example for a table that contains posts.

@extends('layouts.scaffold')

@section('main')

<h1>All Posts</h1>

<div class="search">
{{ Form::model(null, array('route' => array('posts.search'))) }}
{{ Form::text('query', null, array( 'placeholder' => 'Search query...' )) }}
{{ Form::submit('Search') }}
{{ Form::close() }}
</div>

<p>{{ link_to_route('posts.create', 'Add new post') }}</p>

@if ($posts->count())
<table class="table table-striped table-bordered">
<thead>
<tr>
<th>Title</th>
<th>Body</th>
</tr>
</thead>

<tbody>
@foreach ($posts as $post)
<tr>
<td>{{{ $post->title }}}</td>
<td>{{ $post->body }}</td>
<td>{{ link_to_route('posts.edit', 'Edit', array($post->id), array('class' => 'btn btn-info')) }}</td>
<td>
{{ Form::open(array('method' => 'DELETE', 'route' => array('posts.destroy', $post->id))) }}
{{ Form::submit('Delete', array('class' => 'btn btn-danger')) }}
{{ Form::close() }}
</td>
</tr>
@endforeach
</tbody>
</table>
@else
There are no posts
@endif

@stop

And your index action looks like this:

public function index()
{
$posts = $this->post->all();

return View::make('posts.index', compact('posts'));
}

Now if we want to make our index view sortable by clicking on the column header, we should modify our controller to look like this

public function index()
{
    $sortby = Input::get('sortby');
    $order = Input::get('order');

    if ($sortby && $order) {
        $posts = $this->post->orderBy($sortby, $order)->get();
    } else {
        $posts = $this->post->get();
    }

    return View::make('posts.index', compact('posts', 'sortby', 'order'));
}

This will retrieve two GET variables: sortby and order.
The sortby variable will contain which field to sort by. The order variable will dontain the direction (ASC or DESC)

Next, we need to modify our view:

@extends('layouts.scaffold')

@section('main')

All Posts

  {{ link_to_route('posts.create', 'Add new post') }} @if ($posts->count()) Body @foreach ($posts as $post) {{ $post->body }}{{ link_to_route('posts.edit', 'Edit', array($post->id), array('class' => 'btn btn-info')) }} {{ Form::open(array('method' => 'DELETE', 'route' => array('posts.destroy', $post->id))) }} {{ Form::submit('Delete', array('class' => 'btn btn-danger')) }} {{ Form::close() }}   @endforeach  
@if ($sortby == 'title' && $order == 'asc') {{ link_to_action( 'PostsController@index', 'Title', array( 'sortby' => 'title', 'order' => 'desc' ) ) }} @else {{ link_to_action( 'PostsController@index', 'Title', array( 'sortby' => 'title', 'order' => 'asc' ) ) }} @endif
{{{ $post->title }}}
@else There are no posts @endif @stop

We added an if-statement to check if any sorting has been done to generate a clickable table header link. In this example we made the title sortable. You can add the same code to make the other headers sortable too.

Clicking once on the header will sort the posts by title with direction ASC, clicking again will sort by DESC order. (Ascending and Descending)

Laravel flash message with modal

Step 1

Lets say we’ve got a web application which has various pages users can access, one of these pages “archive” requires users to be logged in to access it.  I won’t go into the details of how to do that authorization here, since it’s package/project dependent.  However for this example, we’ll be using a custom filter called require_login, which we will create.

Lets go ahead and open our routes.php file in laravel/app/, and add the following example route for our archive page:

1
Route::get('archive', array('before' => 'require_login', 'uses' => 'HomeController@archive'));

A very simple route; if the user goes to access http://mysite.com/archive, then they’ll first be passed to the require_login filter where any arguments within there will be run. The arguments for this filter will be checking whether they are logged in or not. Lets go ahead and create our filter

Step 2

So open up your filters.php file in laravel/app/. We’ll add our own custom filter using the Route class and it’s filter methods. So go ahead and add the following into that file (doesn’t really matter where, just keep it tidy for yourself):

1
Route::filter('require_login', function(){});

Now, every time we access the archive page we’ll be passed through this filter. As promised, this will do our authorization checks. However since I’m not really covering that here, I’ll just use pseudo code. If you want to know more about user authentication & authorization, check out Security in the Laravel Docs, or you could use a 3rd party package like Sentry. So add the following:

1
2
3
4
5
6
Route::filter('require_login', function(){
   // If: User is not logged in:
       return Redirect::to('/')
          ->with("modal_message_error", "You must be logged in to view this page.");
   // End If
});

Lets assume you’ve added your code to check whether the user is logged in, and we’re in the argument where the user has tried to access our archive page and they are not logged in. What we can do here is redirect the user back to the homepage (or wherever you want) using the Redirect class and it’s to method (again, you can use whatever you want). However with this, we will pass a Flash Data session with our with method (which is specifically designed to pass flash data).

Our key for this session will be modal_message_error and the value of the session being: You must be logged in to view this page..

Right, so our user has just been redirected to the home page and they have a flash session stored, now lets use it.

Step 3

For simplicity sake, lets assume the root of your site points towards hello.php view in laravel/app/views/, as is default in the installation. First we need to rename this file to hello.blade.php, so we can use the features of Blade.  So now when we try to access http://mysite.com/archive, we get passed through our filter, and redirected back to the root since we are not logged in, and the route for our sites root loads the hello view.

I’ll go over this part quickly since I’m assuming you have Twitter Bootstrap already loaded in your project:

  • Make sure jQuery is loaded (since Twitter Bootstrap requires it).
  • Make sure your Bootstrap files (JavaScript, CSS and the images are loaded within your CSS file) are being loaded after jQuery.  Just drop them into laravel/public/assets/.

Now lets get started… Within your elements of the hello view (preferably at the end) add in the following:

1
2
3
4
5
6
7
@if( Session::has('modal_message_error'))
   <script type="text/javascript">
      $(document).ready(function() {
        $('#popupmodal').modal();
      });
   </script>
@endif

This means every time our hello view loads we’ll check whether a Session called ‘modal_message’ is set. If it isn’t then do nothing, but if it is, execute the following JavaScript/Jquery. Since we have Bootstrap loaded, the modal() function will be recognized and called, using the #popupmodal divs elements. Check out here if you have no idea what I’m on about.

So we can also add our #popupmodal div inside this if argument, as follows:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
@if( Session::has('modal_message_error'))
    <script type="text/javascript">
        $(document).ready(function() {
            $('#popupmodal').modal();
        });
    </script>
    <div id="popupmodal" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
        <div class="modal-header">
            <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
            <h3>Notification: Please read</h3>
        </div>
        <div class="modal-body">
            <p>
                {{ Session::get('modal_message_error') }}
            </p>
        </div>
        <div class="modal-footer">
            <button class="btn" data-dismiss="modal" aria-hidden="true">Close</button>
        </div>
    </div>
@endif

This way the extra HTML isn’t getting loaded if we don’t need it.

You’ll notice that I’m using {{ Session::get('modal_message_error') }} to get the sessions value, meaning we have our own text in our modal popup.

So if we now try to access http://mysite.com/archive, this view will be loaded with a Flash Data session. The if argument detects that the session is active an d loads the script with the div element. This will cause the Twitter Bootstrap Modal to load and it’s content will be our sessions value! Something like:

modal_message

However since this is a Flash Data session, when we refresh the page it wont be active and thus no popup!  Quite a handy trick to deal with all sorts of messages.  Also since the argument is using nothing distinctly, we can generate different popup messages without duplicating the code… for example another redirect could be:

1
2
return Redirect::to('error-page')
   ->with("modal_message_error", "This is another popup, with some different content!");

Step 4 – Use with popovers

Modal messages by nature are quite intrusive and interrupt the users experience so they have to read it.  This is good, but if the notification isn’t really that important it can be pretty annoying – for example you wouldn’t want it for every new notification you get on Facebook.

Popovers in Twitter Bootstrap can also be used in exactly the same way as Modals.

Simply rename your session, with some different text and you’re good to go.  However since you need to specify which element will have the popover appearing from it, you do have to do something slightly different.  For example in one of my projects, I do the following:

1
2
3
4
5
6
7
8
...
@if (Session::has('user_logged_in'))
   <li id="popOverLogin" rel="popover" data-placement="bottom" data-original-title="Notification!"
      @if (Session::has('popoverlogin'))
         data-content="{{ Session::get('popoverlogin') }}"
      @endif
   >
...

So if the user logs in, I set a permanent session which loads the list item above (on every page load), however if the user has just logged in I set a flash session (popoverlogin) with the value “Thanks for logging in $name!”. Then at the bottom of my main file (just like the modal), I’d have the following:

01
02
03
04
05
06
07
08
09
10
@if (Session::has('popoverlogin'))
    <script type="text/javascript">
        $(document).ready(function() {
            $('#popOverLogin').popover('show');
            setTimeout(function() {
                $('#popOverLogin').popover('hide');
            }, 6000);
        });
    </script>
@endif

If the popoverlogin session is active, load the following script which creates a popup and then hides it after 6 seconds. This looks slick and effective. Here’s an example from a project I’m working on:

logged_in_popover

Conclusion

There we have it… It’s pretty long winded but I didn’t want to skip parts out that lead up to getting the final result.  This stuff really is simple, and with a bit of thought you can use any of Twitter Bootstraps (and other front-end frameworks) components and create awesome effects.

laravel sort tables

VIEW

<table class=”table table-striped table-bordered”>

<thead>
<tr>
<td>ID</td>
<td>name</td>
<td>email</td>
<!–<td>{{ link_to_route(‘reviews.index’, ‘rating’, [‘sort’ => ‘rating’,’direction’=>$direction]) }}</td>–>
<td>{{sortableColumn(‘reviews.index’, ‘rating’, ‘rating’, $direction)}}</td>
<td>{{sortableColumn(‘reviews.index’, ‘section’, ‘section’, $direction)}}</td>
<td>comments</td>
<td></td>
<td>actions</td>
</tr>
</thead>

———————————————————————–

CONTROLLER

public function index() {

$sort = null !==(Input::get(‘sort’))? Input::get(‘sort’) : ‘id’ ;

$direction = null !==(Input::get(‘direction’))? Input::get(‘direction’) : ‘DESC’ ;

$reviews = Review::orderBy($sort, $direction)->paginate(10);

$direction = $direction==’DESC’? ‘ASC’: ‘DESC’ ;

return View::make(‘reviews.index’, compact(‘reviews’,’direction’));
}

Laravel export to excel specific fields

FIRST INSTALL

https://github.com/Maatwebsite/Laravel-Excel

 

Controller

public function getCsv() {

Excel::create(‘Filename’, function($excel) {
$excel->sheet(‘Sheetname’, function($sheet) {
$data = Post::get(array(‘title’,’content’));

$sheet->fromModel($data);

});

//FOR EXCEL 2007 or export(‘xls’) for latest versions

})->export(‘xlsx’);

ROUTE

Route::get(‘csv’, array(‘as’ => ‘csv’, ‘uses’ => ‘PostController@getCsv’));

VIEW

{{HTML::link(‘csv’,’EXPORT TO CSV’)}}

Laravel image upload

MORE INFOS:: http://clivern.com/how-to-create-file-upload-with-laravel/

MODEL

 

<?php

 

class Myform extends \Eloquent {

 

// Add your validation rules here

public static $rules = [

// ‘title’ => ‘required’

];

 

public $timestamps = false;

 

// Don’t forget to fill this array

protected $fillable = [];

 

 

 

}

——————————————-

 

Controller

 

<?php

 

class MyformController extends \BaseController {

 

/**

* Display a listing of offers

*

* @return Response

*/

public function index() {

//$offers = Offer::all();

 

 

return View::make(‘myform’);

}

 

public function FormSubmit() {

 

$data = Input::all();

//Form::create(Input::all());   // which does work, miraculously

// var_dump($data);

$file            = Input::file(‘file1’);

$destinationPath = ‘/storage/’;

$filename        = $file->getClientOriginalName();

$uploadSuccess   = $file->move($destinationPath, $filename);

 

 

$form = new Myform;

$form->name = Input::get(‘name’);

$form->email = Input::get(’email’);

$form->image =  $destinationPath . $filename;

//  return Input::file(‘file’)->move(__DIR__.’/storage/’,Input::file(‘file’)->getClientOriginalName());

 

$form->save();

}

 

 

}

 

——————————————–

 

 

VIEW

 

@extends(‘master’)

 

@section(‘content’)

 

<h2>This is the FORM</h2>

 

{{ Form::open(array(‘url’=>’form-submit’,’files’=>true)) }}

 

{{ Form:: label (‘name’, ‘Name’ )}}

{{ Form:: text (‘name’, ” )}}

 

 

{{ Form:: label (’email’, ‘E-mail Address*’) }}

{{ Form:: email (’email’, ”, array(‘placeholder’ => ‘me@example.com’)) }}

 

 

{{ Form::label(‘file’,’File’,array(‘id’=>”,’class’=>”)) }}

{{ Form::file(‘file1’,”,array(‘id’=>”,’class’=>”)) }}

<br/>

<!– submit buttons –>

{{ Form::submit(‘Save’) }}

 

<!– reset buttons –>

{{ Form::reset(‘Reset’) }}

 

{{ Form::close() }}

 

@stop

 

——————————————–

 

MYSQL TABLE

 

CREATE TABLE IF NOT EXISTS `myforms` (

`id` int(11) NOT NULL AUTO_INCREMENT,

`name` varchar(200) COLLATE utf8_unicode_ci NOT NULL,

`email` varchar(200) COLLATE utf8_unicode_ci NOT NULL,

`image` varchar(200) COLLATE utf8_unicode_ci NOT NULL,

PRIMARY KEY (`id`)

) ENGINE=InnoDB  DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=3 ;

 

— GRGR `myforms`

 

INSERT INTO `myforms` (`id`, `name`, `email`, `image`) VALUES

 

(1, ‘fsdgsdfg’, ‘info@ariser2.com’, ‘C:\\wamp\\www\\lara_users\\app\\controllers/storage\\ticket.jpg’);

Laravel export table to csv with columns names

Controller function

public function getCsv() {

$table = Post::all();
$filename = “posts.csv”;
$handle = fopen($filename, ‘w+’);

// titloi stilwn
fputcsv($handle, array(‘id’, ‘title’, ‘content’));

//pedia

foreach($table as $row) {
fputcsv($handle, array($row[‘id’], $row[‘title’], $row[‘content’]));
}

fclose($handle);

$headers = array(

‘Content-Encoding: UTF-8’

‘Content-Type’ => ‘text/csv’,
);

return Response::download($filename, ‘posts.csv’, $headers);

}

ROUTE

Route::get(‘csv’, array(‘as’ => ‘csv’, ‘uses’ => ‘PostController@getCsv’));

VIEW

{{HTML::link(‘csv’,’EXPORT TO CSV’)}}

Populate dropdown list from database with Laravel

First, create a model named “Country.php” (you can use artisan, excellent  Laravel 4 generators or create it manually. Keep in mind that the model name is singular (Country) and the database table is plural (Countries).

In your controller add:

1
$country_options = Country::lists('short_name', 'id');

Simple isn’t it? This will return an array of values like “[1] => Afghanistan [2] => Aland Islands”… (We are assuming that database field name containing country names is “short_name”).

Note: Personally I like Eloquent but in case you do not want to use Eloquent or/and do not want to have an empty Country.php model lying there just so you can populate drop-down then you can use Laravel’s Fluent Database Query Builder:

1
$country_options = DB::table('countries')->orderBy('short_name', 'asc')->lists('short_name','id');

Ok, now let’s send this to view with ->with :

1
return View::make('admin/customers/create')->with('country_options',$country_options);

In above case I am sending $country_options to admin view that is used to create customers.

In the view you display it like this:

1
{{ Form::select('country', $country_options , Input::old('country')) }}

That is all it takes to have a functioning drop-down select box. As you can see we are using Laravel Blade template engine and Form class. With Input::old('country')) we re-populate it with old values (for example after the form is submitted and there are some errors)

How to combine more fields with concat

In another case (for “customers”) I needed to combine two table fields into one and then populate the drop down with it: customers “first_name” + “last_name” should be “first_name last_name”. You can do this by combining Fluent Query Builder with Eloquent:

1
$customer_options = Customer::select(DB::raw('concat (first_name," ",last_name) as full_name,id'))->lists('full_name', 'id');

As you can see we are mixing Eloquent and DB:raw method.

Note: If you only want to use Laravel’s Database Query Builder then you can do this:

1
$customer_options = DB::table('customers')->select(DB::raw('concat (first_name," ",last_name) as full_name,id'))->lists('full_name', 'id');

How to add default option to dropdown list

Sometimes we want to have some default value that gives us some instructions what to do (“Please select a country,…”) with the dropdown or maybe even some default “non-value” (in case user doesn’t want to select anything). The easiest way to do this is to add array('' => 'Select One') + so our code looks like this (few examples with the code in this post):

1
2
3
4
$country_options = array('' => 'Please Select Your Country') + Country::lists('short_name', 'id');
//or
$customer_options = array('' => 'Select Customer') + Customer::select(DB::raw('concat (first_name," ",last_name) as full_name,id'))->lists('full_name', 'id');
//and so on..

Keep in mind that you will have to add some validation (jQuery, Laravel’s own validation etc) in case user leaves the default option (in example above we leave the value as empty but you can set it to anything you want).