Yajra DataTables service implementation upgrade from Laravel 5 to Laravel 6 - laravel

We have been using Yajra DataTables with Laravel 5 for a few years and have built up a library of over 50 of them, basically for the index page of a BREAD UI. It's finally time to upgrade, and We're using the service implementation, which looks like this.
The current code is working against
"yajra/laravel-datatables-oracle": "^6.0",
Here is the Controller:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Validator;
use App\DataTables\WidgetDataTable;
use App\Models\Widget;
use Illuminate\Support\Facades\Auth;
use App\Models\Widgetaccount;
use App\Events\Widgetcrud;
use App\DataTables\WidgetHistoryDataTable;
use Illuminate\Support\Facades\DB;
class WidgetController extends Controller
{
/**
* Create a new controller instance
*
* #return void
*/
public function __construct()
{
$this->middleware('permission:widget_view', ['only' => ['index', 'history']]);
$this->middleware('permission:widget_create', ['only' => ['create','store']]);
$this->middleware('permission:widget_edit', ['only' => ['edit','update']]);
$this->middleware('permission:widget_delete', ['only' => ['destroy']]);
}
/**
* Display a listing of the resource.
*
* #param object $dataTable
* #return \Illuminate\Http\Response
*/
public function index(WidgetDataTable $dataTable)
{
return $dataTable->render('widget.index', [
'title' => 'Manage Widgets',
]);
}
// other methods here
}
Here is the DataTables class:
<?php
namespace App\DataTables;
use Illuminate\Support\Facades\DB;
use Yajra\DataTables\Services\DataTable;
use Illuminate\Support\Facades\Auth;
class widgetDataTable extends DataTable
{
/**
* Display ajax rwidgetonse.
*
* #return \Illuminate\Http\JsonResponse
*/
public function ajax()
{
return $this->datatables
->queryBuilder($this->query())
->editColumn(
'edit accounts',
function ($widget) {
return '<a href="' . route('widgetaccounts.index', 'widgetid=' . $widget->id)
. '" class="btn btn-xs btn-primary"><i class="glyphicon glyphicon-edit"></i> </a>';
}
)
->editColumn(
'documentation',
function ($widget) {
if ($widget->documentation != null) {
return '<a href="javascript:void(0)" data-value="' . $widget->documentation .
'" class="btn btn-xs btn-primary opendocument">View</a>';
} else {
return '';
}
}
)
->addColumn(
'action',
function ($widget) {
return '<a href="' . route('widgets.edit', $widget->id) .
'" class="btn btn-xs btn-primary" dusk="widget-edit-button-'.$widget->id .'"><i class="glyphicon glyphicon-edit"></i> Edit</a>
<a href="javascript:void(0)" data-remote="' . route('widgets.destroy', $widget->id) .
'" class="btn btn-xs btn-danger btn-delete" dusk="widget-delete-button-'.$widget->id .'"><i class="glyphicon glyphicon-trash"></i>Delete</a>';
}
)
->make(true);
}
/**
* Get the query object to be processed by dataTables.
*
* #return \Illuminate\Database\Eloquent\Builder|
*/
public function query()
{
$widget_id = null;
if ($this->request()->has("widgetid")) {
$widget_id = $this->request()->get("widgetid");
}
$query = DB::connection('dashboard')
->table('widgets')
->join('users', 'users.id', '=', 'widgets.user_id')
->whereNull('widgets.deleted_at')
->when($widget_id,
function ($queryvar, $widget_id) {
return $queryvar->where('widgets.id', $widget_id);
})
->select(
'widgets.id',
'widgets.name',
'widgets.active',
'users.name as username',
'widgets.documentation',
'widgets.created_at',
'widgets.updated_at',
'widgets.deleted_at'
);
return $this->applyScopes($query);
}
/**
* Optional method if you want to use html builder.
*
* #return \Yajra\Datatables\Html\Builder
*/
public function html()
{
if (Auth::user()->can('distribution_manage_widget_lists_edit')) {
return $this->builder()
->columns($this->getColumns())
->ajax('')
->addAction(['width' => '80px'])
->parameters([
'dom' => 'lBfrtip',
'buttons' => ['csv', 'excel'],
'pageLength' => 50
]);
}else{
return $this->builder()
->columns($this->getColumns())
->ajax('')
->parameters([
'dom' => 'lBfrtip',
'buttons' => ['csv', 'excel'],
'pageLength' => 50
]);
}
}
/**
* Get columns.
*
* #return array
*/
protected function getColumns()
{
return [
'id',
'name',
'active',
'documentation' => ['searchable' => false, 'orderable' => false],
'edit accounts' => ['searchable' => false, 'orderable' => false],
'last edited by' => ['name' => 'users.name', 'data' => 'username'],
'created_at',
'updated_at',
];
}
/**
* Get filename for export.
*
* #return string
*/
protected function filename()
{
return 'widgetdatatables_'.time();
}
}
Here is the view:
#extends('layouts.main')
#section('content')
#include('partials.panel-open', [ 'title' => "Manage widgets" ])
<form action="{{route('widgetsearch')}}" method="POST">
{{ csrf_field() }}
<div class="search_button_group">
<div class="row">
<div class="col-sm-4 col-sm-offset-2">
<label>Search for widget-related Settings: </label>
</div>
<div class="col-sm-6">
<div class="input-group">
<input type="text" class="form-control" placeholder="" name="search" aria-describedby="basic-addon1" required="required">
<button class="input-group-addon btn btn-primary" id="basic-addon1" type="submit">Go</button>
</div>
</div>
</div>
</div>
</form>
<div class="row form-group">
<div class="col-sm-6">
#permission(('widget_create'))
Add New widget
#endpermission
</div>
<div class="col-sm-6">
<div class="text-right">
widget History
</div>
</div>
</div>
{!! $dataTable->table(['class' => 'table table-bordered','id' =>'widget-table']) !!}
#permission(('widget_create'))
Add New widget
#endpermission
#include('partials.panel-close')
<div id="myModal" class="modal fade" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Documentation</h4>
</div>
<div class="modal-body">
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
#endsection
#push('scripts')
<script src="/vendor/datatables/buttons.server-side.js"></script>
{!! $dataTable->scripts() !!}
<script type="text/javascript">
$('#widget-table').on('click', '.btn-delete[data-remote]', function (e) {
e.preventDefault();
if (confirm("Are you sure you want to delete"))
{
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
var url = $(this).data('remote');
$.ajax({
url: url,
type: 'DELETE',
dataType: 'json',
data: {method: '_DELETE', submit: true}
})
.always(function (data) {
var count = data.count;
if (count == 0) {
$('#widget-table').DataTable().draw(false);
} else {
alert("widget can't be deleted as there are associated widget Account/s (#" + count + ") under the same. Kindly remove the widget Account/s first.");
}
});
}
});
$(document).on("click",".opendocument",function(){
$(".modal-body").html($(this).data('value'));
$('#myModal').modal('show');
});
</script>
#endpush
Now I've updated composer and am trying to use:
"yajra/laravel-datatables-oracle": "^9.0",
"yajra/laravel-datatables-buttons": "^4.0",
And when I view the widget index, I get the ajax error dialog
DataTables warning: table id=widget-table -
Ajax error. For more information about this error,
please see http://datatables.net/tn/7
When I look in the Laravel.log:
[2020-07-24 10:30:55] local.ERROR: Call to a member function queryBuilder() on null
{"userId":19,"exception":"[object]
(Symfony\\Component\\Debug\\Exception\\FatalThrowableError(code: 0): Call to a member function queryBuilder() on null at /Projects/my-app/app/DataTables/WidgetDataTable.php:20)
[stacktrace]
#0 [internal function]: App\\DataTables\\WidgetDataTable->ajax()
So, it seems that on this line:
return $this->datatables
->queryBuilder(...
the datatables property is not set. So, I am stuck as to how to proceed, and have broken my entire application. Looking for advice on what to try or a guide on how to upgrade the Yajra service implementation without having to modify hundreds of files.

It's been a while, but as I myself was stuck at this point in the process of upgrading, I thought I would share the solution as the documentation lacks a bit of detail.
I only got to understand what to change after finding and comparing this example sheet in the documentation:
https://yajrabox.com/docs/laravel-datatables/master/quick-starter
Further changes are then introduced in yajra's upgrade guide:
https://yajrabox.com/docs/laravel-datatables/8.0/upgrade
Changes to the DataTables class:
1.
/**
* Display ajax rwidgetonse.
*
* #return \Illuminate\Http\JsonResponse
*/
public function ajax()
{
return $this->datatables
->queryBuilder($this->query())
becomes:
use Yajra\DataTables\DataTables;
public function dataTable(DataTables $dataTables, $query) {
return $dataTables->eloquent($query)
If you're ajax / datatables function contains the ->editColumn() api, remove the ->render(); at the end. Otherwise html will be parsed as string.
3.
private function getColumns()
{
...
}
becomes protected:
protected function getColumns()
{
...
}
Return Object of the html function is now CamelCased too:
* #return \Yajra\Datatables\Html\Builder
to
* #return \Yajra\DataTables\Html\Builder
the getColumns() function now returns Columns as Array of Columns:
return [
[
'name' => 'users.firstname',
'data' => 'firstname',
'title' => 'Vorname',
],
];
becomes:
return [
Column::computed('firstname')
->name('users.firstname')
->title('Vorname'),
];
For which you need to import:
use Yajra\DataTables\Html\Column;
Even though that's the new way, your way of returning columns should still work as well.
Actually that's all
Many things are possible with sublime's find and replace so it shouldn't be that costly.
I hope that helps someone else who is struggling with the update.
Cheers
Dominik

Related

How to add Recaptcha v2 to Laravel and Vue js?

I'm following this article on how to add Recaptcha v2 to a Laravel and Vue js project.
https://www.itechempires.com/2018/05/how-to-implement-google-recapcha-with-vuejs-and-laravel-5-6/
I'm trying to implement it in my project but I'm getting this error on the page:
The recaptcha verification failed. Try again.
And in the network tab this error:
{recaptcha: ["The recaptcha verification failed. Try again."]}
And in the console:
POST http://highrjobsadminlte.test/submit 422 (Unprocessable Entity)
I'm trying to implement this on a Contact Form on my Contact.vue page.
Contact.vue:
<form #submit.prevent="submit">
<div class="form-group">
<label for="name">Name</label>
<input type="text" class="form-control" name="name" id="name" v-model="fields.name" />
<div v-if="errors && errors.name" class="text-danger" style="font-size: 13px;">{{ errors.name[0] }}</div>
</div>
<div class="form-group">
<label for="email">E-mail</label>
<input type="email" class="form-control" name="email" id="email" v-model="fields.email" />
<div v-if="errors && errors.email" class="text-danger" style="font-size: 13px;">{{ errors.email[0] }}</div>
</div>
<div class="form-group">
<label for="message">Message</label>
<textarea class="form-control" id="message" name="message" rows="5" v-model="fields.message"></textarea>
<div v-if="errors && errors.message" class="text-danger" style="font-size: 13px;">{{ errors.message[0] }}</div>
</div>
<div class="form-group">
<vue-recaptcha
v-model="fields.recaptcha"
ref="recaptcha"
#verify="onVerify"
sitekey="6LcAHcoZAAAAAFDOejn9e2LrogSpF41RMlXtrpDa">
</vue-recaptcha>
</div>
<div v-if="errors && errors.recaptcha" class="text-danger" style="font-size: 13px;">{{ errors.recaptcha[0] }}</div>
<button type="submit" class="btn btn-primary mt-3">Send message</button>
</form>
export default {
name: "Contact",
data() {
return {
fields: {},
errors: {},
}
},
methods: {
onVerify(response) {
this.fields.recaptcha = response;
},
submit() {
this.errors = {};
axios.post('/submit', this.fields, {
headers:{
'Content-Type':'application/json',
'Accept':'application/json'
}
}).then(({data: {fields}}) => {
this.$toast.success('Message sent successfully!');
this.$refs.recaptcha.reset();
}).catch(error => {
if (error) {
this.errors = error.response.data.errors || {};
}
});
},
},
}
Recaptcha.php (This is a rule):
<?php
namespace App\Rules;
use Illuminate\Contracts\Validation\Rule;
use Zttp\Zttp;
class Recaptcha implements Rule
{
const URL = 'https://www.google.com/recaptcha/api/siteverify';
/**
* Determine if the validation rule passes.
*
* #param string $attribute
* #param mixed $value
* #return bool
*/
public function passes($attribute, $value)
{
return Zttp::asFormParams()->post(static::URL, [
'secret' => config('services.recaptcha.secret'),
'response' => $value,
'remoteip' => request()->ip()
])->json()['success'];
}
/**
* Get the validation error message.
*
* #return string
*/
public function message()
{
return 'The recaptcha verification failed. Try again.';
}
/**
* Determine if Recaptcha's keys are set to test mode.
*
* #return bool
*/
public static function isInTestMode()
{
return Zttp::asFormParams()->post(static::URL, [
'secret' => config('services.recaptcha.secret'),
'response' => 'test',
'remoteip' => request()->ip()
])->json()['success'];
}
}
ContactFormController.php:
<?php
namespace App\Http\Controllers;
use App\Mail\ContactEmail;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Mail;
use App\Rules\Recaptcha;
class ContactFormController extends Controller
{
public function submit(Request $request, Recaptcha $recaptcha) {
$this->validate($request, [
'name' => 'required|string',
'email' => 'required|email',
'message' => 'required',
'recaptcha' => ['required', $recaptcha],
]);
$contact = [];
$contact['name'] = $request->get('name');
$contact['email'] = $request->get('email');
$contact['subject'] = $request->get('subject');
$contact['message'] = $request->get('message');
// Mail Delivery logic goes here
Mail::to(config('mail.from.address'))->send(new ContactEmail($contact));
return response(['contact' => $contact], 200);
}
}
web.php:
Route::post('/submit', 'ContactFormController#submit');
And I have set recaptcha key and secret in config/services.php to point to my .env variables which are set in my .env file.

Filter with date range while using HTML Builder - yajra Datatables

I used the Yajra Laravel Datatables and HTML Builder plugin for displaying my data, now I want to add two date input fields which are start date and end date that can be used to get the data within a range of time, so I can download the data according to date range. Please how can I go about this?
/**
* Show the application.
* More info DataTables : https://yajrabox.com/docs/laravel-datatables/master
*
* #param Datatables $datatables
* #return \Illuminate\Http\Response
* #throws \Exception
*/
public function index(Datatables $datatables)
{
$columns = [
'name',
'id_card',
'date',
];
if ($datatables->getRequest()->ajax()) {
return $datatables->of(Attendance::all())
->addColumn('name', function(Attendance $user) {
return User::where('id', $user->user_id)->first()->name;
})
->toJson();
}
$html = $datatables->getHtmlBuilder()
->columns($columns)
->parameters([
'responsive' => true,
'autoWidth' => false,
'dom' => 'Bfrtip',
'buttons' => ['csv', 'excel', 'pdf', 'print'],
]);
return view('backend.attendances.index', compact('html'));
}
Blade
<div class="card-body">
<p id="date_filter" class="form-inline">
<span id="date-label-from" class="date-label"><b>From:</b> </span><input class="date_range_filter date form-control input-sm" type="text" id="min" />
<span id="date-label-to" class="date-label"><b>To:</b></span> <input class="date_range_filter date form-control input-sm" type="text" id="max" />
</p>
<div class="table-responsive">
{!! $html->table(['class' => 'table table-hover']) !!}
</div>
</div>
........
........
{!! $html->scripts() !!}
I use
PHP Version : 7.2
Laravel Version: 6
Laravel-DataTables Version: 9.0
You can pass extra parameters in yajra datatable as service from frontend.
window.LaravelDataTables["dataTableBuilder"] = $("#dataTableBuilder").on('preXhr.dt', function (e, settings, data) {
data.startDate= 2020-10-27 0:00:00;
data.endDate = 2020-10-30 23:59:59;
}).DataTable({
"serverSide": true,
"processing": true,
"ajax": {
url: "{{route('route.index')}}",
type: "GET"
}
});
LaravelDataTables.dataTableBuilder.ajax.reload()
I hope It will be helpful for who use yajra datatable as service :)
If you view page source of your page this {!! $html->scripts() !!} generate this code
window.LaravelDataTables["dataTableBuilder"] = $("#dataTableBuilder").DataTable
so DataTables instance store as global variable. This means any JS code will have access to this variable. in order to send a request with parameter you can do like this.
<script>
(function () {
const doSubmit = () => {
LaravelDataTables.dataTableBuilder.ajax.url({
type: 'POST',
data: function (d) {
d.start = document.getElementById('start').value
d.end = document.getElementById('end').value
}
})
LaravelDataTables.dataTableBuilder.ajax.reload()
}
const send = document.getElementById('send')
send.addEventListener('click', doSubmit)
})()
</script>

laravel event generate an error in real chat app

I am working on a demo for instant chat and I was able to display the number of logged in users and show their names in the "Online Users" list, but the problem is that I created a laravel event to show messages in real time, and here I get the following error message in my console: Error: Syntax error, unrecognized expression: #user=1 .
demo app details :
laravel : 5.8.*
php : ^7.1.3
redis & laravel echo & laravel echo serveur
view :
<div class="container">
<div class="row">
<div class="col-md-4">
<h2>Online Users</h2>
<hr>
<h5 id="no-online-users">No Online Users</h5>
<ul class="liste-group" id="online-users">
</ul>
</div>
</div>
<div class="row">
<div class="col-md-9 d-flex flex-column" style="height: 80vh">
<div class="h-100 bg-white mb-4 p-5" id="chat" style="overflow-y: scroll;">
#foreach($messages as $message)
#if(\Auth::user()->id == $message->user_id)
<div class="mt-4 w-50 text-white p-3 rounded float-right bg-primary">
#else
<div class="mt-4 w-50 text-black p-3 rounded float-left bg-warning">
#endif
<p>{{ $message->body }}</p>
</div>
<div class="clearfix"></div>
#endforeach
</div>
<form action="" class="d-flex">
<input type="text" id="chat-text" name="" data-url="{{ route('messages.store') }}" style="margin-right: 10px" class="col-md-9 d-flex flex-column">
<button class="btn btn-primary col-md-3">Send</button>
</form>
</div>
</div>
</div>
MessageController :
namespace App\Http\Controllers;
use App\Message;
use Illuminate\Http\Request;
class MessageController extends Controller
{
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('auth');
}
//index
public function index()
{
$messages = Message::all();
return view('messages.index',compact('messages'));
}
// store
public function store(Request $request)
{
//$message = auth()->user()->messages()->create($request->all());
//return $request->body;
$message = new Message();
$message->user_id = \Auth::user()->id;
$message->body = $request->body;
$message->save();
broadcast(new MessageDelivered($message))->toOthers();
}
}
the event MessageDelivered:
namespace App\Events;
use App\Message;
use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
class MessageDelivered implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $message;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct(Message $message)
{
$this->message = $message;
}
/**
* Get the channels the event should broadcast on.
*
* #return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new Channel('chat-group');
}
}
app.js
require('./bootstrap');
import Echo from "laravel-echo"
window.io = require('socket.io-client');
window.Echo = new Echo({
broadcaster: 'socket.io',
host: window.location.hostname + ':6001'
});
// online users :
let onlineUsersLength = 0;
window.Echo.join('online')
.here((users) => {
onlineUsersLength = users.length;
console.log(onlineUsersLength);
let userId = $('meta[name=user-id]').attr('content');
//console.log(userId);
users.forEach(function(user){
if (user.id == userId) { return; }
$('#no-online-users').css('display','none');
$('#online-users').append('<li id="user='+user.id+'" class="liste-group-item">'+user.name+'</li>');
})
//console.log(users);
})
.joining((user) => {
$('#no-online-users').css('display','none');
$('#online-users').append('<li id="user='+user.id+'" class="liste-group-item">'+user.name+'</li>');
})
.leaving((user) => {
$('#user='+user.id).css('display','none');
$('#no-online-users').css('display','yes');
});
// submit chat text :
$('#chat-text').keypress(function(e){
//console.log(e.which);
if(e.which == 13){
e.preventDefault();
let body = $(this).val();
let url = $(this).data('url');
let data = {
'_token': $('meta[name=csrf-token]').attr('content'),
body
}
//console.log(body);
$.ajax({
url: url,
method: 'post',
data: data,
});
}
});
window.Echo.channel('chat-group')
.listen('MessageDelivered', (e) => {
console.log('message');
});
problem :
in first user console (user id 1 in database)
in second user console (user id 2 in database)
When I refresh the page for a specific user, the error appears for the second user
I guess you have a typo here $('#user='+user.id).css('display','none')
^^^
and here $('#online-users').append('li id="user='+user.id+'" class="liste-group-item">'+user.name+'</li>'); ^^^
You may fix it
//...
users.forEach(function(user){
if (user.id == userId) { return; }
$('#no-online-users').css('display','none');
$('#online-users').append('<li id="user-'+user.id+'" class="liste-group-item">'+user.name+'</li>');
})
//...
.joining((user) => {
$('#no-online-users').css('display','none');
$('#online-users').append('<li id="user='+user.id+'" class="liste-group-item">'+user.name+'</li>');
})
.leaving((user) => {
$('#user-'+user.id).css('display','none');
$('#no-online-users').css('display','yes');
});
//...

Export .xslx data using Laravel Excel with parameter

I want to export data from the database to .xlsx using Laravel-Excel.
I want to pass three parameters to query the data and download into excel file.
I already search and read a few examples but still failed to make the excel file to download.
This is my blade file.
#section('content')
<div class="container">
<div class="row justify-content-center">
<div class="col-md-3"></div>
<div class="col-md-6">
<div class="card">
<div class="card-header">Download Report</div>
<div class="card-body">
<div class="col-md-12" style="margin-bottom:15px">
<select class="form-control" name="plant" id="plant">
<option selected value="All">Please Select Plant</option>
#foreach($plants as $plant)
<option value="{{ $plant->id }}">{{ $plant->name }}</option>
#endforeach
</select>
</div>
<div class="col-md-12" style="">
<div class="input-group input-daterange" align="center">
<input type="text" name="from_date" id="from_date" readonly class="form-control" value="<?php echo date("Y-m-d");?>" />
<div class="input-group-addon" >To</div>
<input type="text" name="to_date" id="to_date" readonly class="form-control" value="<?php echo date("Y-m-d");?>"/>
</div>
</div>
<br>
<div class="col-md-12" align="center">
<button type="button" name="search" id="search" class="btn btn-info btn-block">Download</button>
</div>
</div>
</div>
</div>
<div class="col-md-3"></div>
</div>
</div>
<script type="text/javascript">
$(function() {
var date = new Date();
$('.input-daterange').datepicker({
todayBtn: 'linked',
format: 'yyyy-mm-dd',
autoclose: true
});
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
$('#search').click(function(e){
e.preventDefault();
var from_date = $('#from_date').val();
var to_date = $('#to_date').val();
var plant = $('#plant').val();
if(plant != 'All')
{
$.ajax({
url:"{{ route('export') }}",
data:{from_date:from_date, to_date:to_date, plant:plant},
dataType:"json",
})
}
else
{
alert('Please Select Plant');
}
});
});
</script>
#endsection
This is my function at the controller
public function export(Request $request)
{
return (new DetailReportDownload($request->plant,$request->from_date,$request->to_date))->download('Report Details.xlsx');
}
and This is my Export file
class DetailReportDownload implements FromQuery, WithHeadings
{
use Exportable;
protected $plant,$from,$to;
public function __construct(String $from,String $to,String $plant)
{
$this->plant = $plant;
$this->from = $from;
$this->to = $to;
}
public function headings(): array
{
return [
'plandate',
'workcentre',
'partno',
'prodduration',
'totaldowntime',
'planout',
'cumout',
];
}
public function query()
{
return DB::table('plannings')
->select(DB::raw('plandate, workcentre, partno, prodduration, coalesce(sum(downduration),0) as totaldowntime, planout, cumout'))
->join('prodstatuses', 'plannings.id', '=', 'prodstatuses.id')
->leftJoin('downtimes', 'plannings.id', '=', 'downtimes.plan_id')
->whereBetween('plandate', array($this->from, $this->to))
->where('plant_id',$this->plant)
->where('status','Finished')
->groupBy('plannings.id')
->orderBy('plannings.id');
}
}
I wanted to download excel file from parameter given in blade file.
Thanks in advance for any help
create a provider to add below code & register to app.php file
Sheet::macro('styleCells', function (Sheet $sheet, string $cellRange, array $style) {
$sheet->getDelegate()->getStyle($cellRange)->applyFromArray($style);
});
And create class to download data using parameters,
<?php
namespace App\Modules\User\Http\Exports;
use Illuminate\Contracts\View\View;
use Illuminate\Support\Collection;
use Maatwebsite\Excel\Concerns\FromView;
use Maatwebsite\Excel\Concerns\ShouldAutoSize;
use Maatwebsite\Excel\Concerns\WithEvents;
use Maatwebsite\Excel\Events\AfterSheet;
/**
* Class ExportUsers
* #package App\Exports
*/
class ExportUsers implements FromView, ShouldAutoSize, WithEvents
{
protected $plannings;
/**
* ExportUsers constructor.
* #param Collection $plannings
*/
public function __construct(Collection $plannings) {
$this->plannings = $plannings;
}
/**
* #return View
*/
public function view() : View {
return view('plannings_list', [
'plannings' => $this->plannings,
]);
}
/**
* #return array
*/
public function registerEvents() : array {
return [
AfterSheet::class => function (AfterSheet $event) {
$this->createStyle($event, 'A1:N1', 9);
$event->sheet->styleCells(
'A1:N1',
[
'font' => [
'bold' => true,
]
]
);
},
];
}
/**
* #param $event
* #param $cell
* #param $size
* #throws \PhpOffice\PhpSpreadsheet\Exception
*/
private function createStyle($event, $cell, $size) {
/** #var AfterSheet $event */
$event->sheet->getDelegate()->getStyle($cell)->getFont()->setSize($size);
}
}
add this code to controller
private function downloadCsv($exportCsvList) {
return Excel::download(new ExportUsers($exportCsvList),
'students.xlsx');
}

Laravel 5.2.45 - empty $errors variable in views

Problem:
The $errors variable is empty in the views. There's talk that this has been fixed in 5.2 so hopefully the problem is on my end.
Environment:
Mac OS X
Laravel 5.2.45
The Codez:
Routes.php
Route::get('/', 'AlleleController#index');
Route::get('/register', function () {
return view('auth.register');
});
Route::auth();
Route::get('/home', 'HomeController#index');
Route::get('/alleles', 'AlleleController#index');
Route::post('/allele', 'AlleleController#store');
Route::delete('/allele/{allele}', 'AlleleController#destroy');
AlleleController.php:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Allele;
class AlleleController extends Controller {
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct() {
// All methods require authentication except index.
$this->middleware('auth', ['except' => ['index']]);
}
/**
* Root page.
*
* #return Response
*/
public function index() {
return view('welcome');
}
/**
* Create a new allele.
*
* #param Request $request
* #return Response
*/
public function store(Request $request) {
$allele = new Allele();
// Get all input as an array.
$input = $request->all();
// Validate input.
if ($allele->validate($input)) {
// Valid input. Write to database.
// The inserted model instance is returned.
$result = $allele::create($input);
if ($result) {
// Insert successful.
$message = array('message' => 'Data added!');
return view('home', $message);
} else {
// Insert failed. Send errors to view.
$errors = array('errors' => 'Error saving data.');
return view('home', $errors);
}
} else {
// Invalid input. Get errors.
$errors = $allele->errors();
// Send errors to view.
return view('home', $errors);
}
}
}
?>
HomeController.php:
<?php
namespace App\Http\Controllers;
use App\Http\Requests;
use Illuminate\Http\Request;
class HomeController extends Controller {
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct() {
$this->middleware('auth');
}
/**
* Show the application dashboard.
*
* #return \Illuminate\Http\Response
*/
public function index() {
return view('home');
}
}
Model: Allele.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Allele extends Validation {
/**
* The attributes that are mass assignable.
*/
protected $fillable = ['allele'];
/**
* Validation rules.
*/
protected $rules = array (
'allele' => 'required|max:20',
);
}
Model: Validation.php
<?php
namespace App;
use Validator;
use Illuminate\Database\Eloquent\Model;
class Validation extends Model {
protected $rules = array();
protected $errors;
public function validate($input) {
// Make a new validator object.
$v = Validator::make($input, $this->rules);
// Check for failure.
if ($v->fails()) {
// Set errors and return false.
$this->errors = $v->errors();
return false;
}
// Validation passed.
return true;
}
// Retrieves the errors object.
public function errors() {
return $this->errors;
}
}
View: views/common/errors.blade.php
#if (count($errors) > 0)
<!-- Form Error List -->
<div class="alert alert-danger">
<strong>Whoops! Something went wrong!</strong>
<br><br>
<ul>
#foreach ($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
</div>
#endif
View: views/home.blade.php
#extends('layouts.app')
#section('content')
<div class="container">
<div class="row">
<div class="col-md-10 col-md-offset-1">
<div class="panel panel-default">
<div class="panel-heading">Dashboard</div>
<div class="panel-body">
You are logged in!
</div>
</div>
</div>
</div>
</div>
<!-- Create New Allele -->
<div class="panel-body">
<!-- Display Validation Errors -->
#include('common.errors')
<!-- New Allele Form -->
<form action="{{ url('allele') }}" method="POST" class="form-horizontal">
{{ csrf_field() }}
<!-- Allele Name -->
<div class="form-group">
<label for="allele-name" class="col-sm-3 control-label">Allele</label>
<div class="col-sm-6">
<input type="text" name="allele" id="allele-name" class="form-control">
</div>
</div>
<!-- Add Allele Button -->
<div class="form-group">
<div class="col-sm-offset-3 col-sm-6">
<button type="submit" class="btn btn-default">
<i class="fa fa-plus"></i> Add Allele
</button>
</div>
</div>
</form>
</div>
#endsection
All validation methods should be placed inside web middleware . I do not see any other error. Replace your route.php like this.
Route::group(['middleware' => ['web']], function ()
{
Route::get('/', 'AlleleController#index');
Route::get('/register', function () {
return view('auth.register');
});
Route::auth();
Route::get('/home', 'HomeController#index');
Route::get('/alleles', 'AlleleController#index');
Route::post('/allele', 'AlleleController#store');
Route::delete('/allele/{allele}', 'AlleleController#destroy');
});

Resources