I'm new in Laravel and i want to import a Csv file and store the data in DB with Maatwebsite\Excel. I'm trying to achieve that using jobs in laravel. When i run php artisan queue:work i don't see the job in the queue.
I've set my routes :
Route::get('/import', 'UserImportController#getImport')->name('import');
Route::post('/import_process', 'UserImportController#fileImport')->name('import_process');
I have my controller like this :
<?php
namespace App\Http\Controllers\Admin;
use App\Http\Controllers\Controller;
use App\Http\Requests\CsvImportRequest;
use Illuminate\Http\Request;
use Maatwebsite\Excel\Facades\Excel;
use App\Imports\UsersImport;
class UserImportController extends Controller
{
public function getImport()
{
return view('import');
}
public function fileImport(Request $request)
{
$request->validate([
'import_file' => 'required',
]);
Excel::import(new UsersImport, request()->file('import_file'));
return back()->withStatus('Import done!');
}
}
I've configured my .env like this:
BROADCAST_DRIVER=log
CACHE_DRIVER=file
QUEUE_CONNECTION=database
SESSION_DRIVER=file
SESSION_LIFETIME=120
I've created a Job:
<?php
namespace App\Jobs;
use App\Imports\UsersImport;
use Illuminate\Bus\Queueable;
use Illuminate\Bus\Batchable;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Maatwebsite\Excel\Facades\Excel;
class ImportJob implements ShouldQueue
{
use Batchable, Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public $uploadFile;
/**
* Create a new job instance.
*
* #return void
*/
public function __construct($uploadFile)
{
$this->uploadFile = $uploadFile;
}
/**
* Execute the job.
*
* #return void
*/
public function handle()
{
Excel::import(new UsersImport, $this->uploadFile);
}
}
I created a Livewire component and view:
<?php
namespace App\Http\Livewire;
use App\Jobs\ImportJob;
use Livewire\Component;
use Livewire\WithFileUploads;
use Illuminate\Support\Facades\Bus;
use Illuminate\Support\Facades\Storage;
class Import extends Component
{
use WithFileUploads;
public $batchId;
public $importFile;
public $importing = false;
public $importFilePath;
public $importFinished = false;
public function import()
{
$this->validate([
'importFile' => 'required',
]);
$this->importing = true;
$this->importFilePath = $this->importFile->store('imports');
$batch = Bus::batch([
new ImportJob($this->importFilePath),
])->dispatch();
$this->batchId = $batch->id;
}
public function getImportBatchProperty()
{
if (!$this->batchId) {
return null;
}
return Bus::findBatch($this->batchId);
}
public function updateImportProgress()
{
$this->importFinished = $this->importBatch->finished();
if ($this->importFinished) {
Storage::delete($this->importFilePath);
$this->importing = false;
}
}
public function render()
{
return view('livewire.import');
}
}
<div>
<form wire:submit.prevent="import" enctype="multipart/form-data">
#csrf
<input type="file" wire:model="importFile" class="#error('import_file') is-invalid #enderror">
<button class="btn btn-outline-secondary">Import</button>
#error('import_file')
<span class="invalid-feedback" role="alert">{{ $message }}</span>
#enderror
</form>
#if($importing && !$importFinished)
<div wire:poll="updateImportProgress">Importing...please wait.</div>
#endif
#if($importFinished)
Finished importing.
#endif
</div>
But when i click on import button nothing happens the import function isn't called and the job is not queued. I don't know what the issue ?
Related
Using Database Notification I have stored notification in the notification table.
But now I want to display the notification in the blade template.
I have faced an undefined error.
Controller
$data=Employee::create([
'first_name'=>$request->input('first_name'),
'last_name'=>$request->input('last_name'),
'username'=>$request->input('username'),
'email'=>$request->input('email'),
'password'=>$request->input('password'),
'confirm_password'=>$request->input('confirm_password'),
]);
$admin=Employee::find(1);
$admin->notify(new NotifyAdmin($data));
NotifyAdmin class
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Notifications\Notification;
use Illuminate\Notifications\Notifiable;
use App\Models\Employee;
class NotifyAdmin extends Notification implements ShouldQueue
{
use Queueable, Notifiable;
private $val;
public function __construct(Employee $employee)
{
$this->val=$employee;
}
public function via($notifiable)
{
return ['database'];
}
public function toArray($notifiable)
{
return [
'username'=> $this->val->username
];
}
}
After doing this, the notification is stored in the notification table.
Now I want to display this notification
<div class="media-body">
#foreach($employee->notifications as $row)
<p class="noti-details"><span class="noti-title">Admin</span> added new doctor <span class="noti-title">{{$row->data['username']}}</span></p>
<p class="noti-time"><span class="notification-time">4 mins ago</span></p>
#endforeach
</div>
this is my controller
<?php
namespace App\Http\Controllers;
use App\Models\Employee;
use Illuminate\Http\Request;
use App\helpers\helper;
use App\Notifications\NotifyAdmin;
class EmployeeController extends Controller
{
public function InsertEmployees(Request $request)
{
$data=Employee::create([
'first_name'=>$request->input('first_name'),
'last_name'=>$request->input('last_name'),
'username'=>$request->input('username'),
'email'=>$request->input('email'),
'password'=>$request->input('password'),
'confirm_password'=>$request->input('confirm_password'),
'phone'=>$request->input('phone'),
'nid_number'=>$request->input('nid_number'),
'status'=>$request->input('status'),
'roles'=>$request->input('roles'),
'join_date'=>$request->input('join_date'),
]);
$admin=Employee::find(1);
$admin->notify(new NotifyAdmin($data));
I have several methods that require email submissions. An example is, after making a purchase.
My class Mailable
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use App\Models\Order;
class AfterOrder extends Mailable
{
use Queueable, SerializesModels;
public $order;
public function __construct(Order $order)
{
$this->Order = $order;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->subject('Thanks for your purchase')->view('mail.after-order');
}
}
My mail view
<div class="container">
<h1>Nombre: {{\Auth::user()->email}}</h1>
<h1>Order: {{$order->reference}}</h1>
</div>
My Controller
public function sendMail(Order $order) {
$order = $order->newQuery();
$order->whereHas('user', function($query){
$query->where('email', '=', \Auth::user()->email);
});
$order = $order->orderBy('id', 'desc')->first();
$user = User::where('email', '=', \Auth::user()->email)->first();
Mail::to($user->email)->send(new AfterOrder($order));
//return redirect()->route('home')->with(['message' => 'Thank you for shopping at Sneakers!']);
}
What am I doing wrong? If I, for example, in my controller make a $ order-> reference I get the order reference but when passing the variable to the view it treats me as null or empty
You should use the with method
public function build()
{
return $this->view('mail.after-order')
->with([
'orderName' => $this->order->name,
'orderPrice' => $this->order->price,
]);
}
in your mailable class AfterOrder. With that you have access to the name and the price of the order in your mail view.
You can then access these with {{ $orderPrice }} and {{ $orderName }} in your view.
Was a typo. just change $this->Order = $order; to $this->order = $order;
I am developing a live chat app with Laravel 7 and Pusher as broadcast driver.
And i am facing a weird problem because its broadcasting an empty object,
but in my console I am receiving the right object/comment.
indexComponent.vue:
<template>
<div>
<h1>All Comments</h1>
<div style="margin-bottom:20px;">
<textarea class="form-control" rows="3" name="body" placeholder="write a comment" v-model="commentBox" ></textarea>
<button class="btn btn-success" style="margin-top:10px" v-on:click="createComment()" >Save Comment</button>
</div>
<div v-for='comment in this.listOfComments' v-bind:key="comment.id" class='card card-body mb-2'>
<p>{{comment.body}}</p>
</div>
</div>
</template>
<script>
export default {
props: ['comments'],
data() {
return {
commentBox: '',
listOfComments: this.comments,
}
},
created: function() {
this.listen();
},
methods: {
createComment: function() {
axios.post('/api/comment', {
body: this.commentBox,
title: 'from axios',
user_id: '1'
})
.then(response => {
this.listOfComments.unshift(response.data)
this.commentBox = '';
})
.catch(error => {
console.log(error.response);
});
},
listen: function() {
Echo.channel('commentsChannel')
.listen('NewComment', (cmn) => {
console.log(cmn);
this.listOfComments.unshift(cmn);
console.log(this.comments[0]);
})
}
},
}
</script>
NewComment.php (event)
<?php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
use Illuminate\Contracts\Broadcasting\ShouldBroadcastNow; //for no queueing
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
use App\Comment;
class NewComment implements ShouldBroadcastNow
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $comment;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct(Comment $comment)
{
$this->comment = $comment;
}
/**
* Get the channels the event should broadcast on.
*
* #return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new Channel('commentsChannel');
}
}
CommentController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Comment;
use Auth;
use App\Events\NewComment;
class CommentsController extends Controller {
public function index() {
$comments = Comment::orderBy('created_at','desc')->get();
return view('comments/index')->with('comments',$comments);
}
public function store(Request $request) {
$comment = new Comment;
$comment->body = $request->body;
$comment->title = $request->title;
$comment->user_id = $request->user_id;
if($comment->save()){
// event(new NewComment($comment));
broadcast(new NewComment($comment))->toOthers();
return $comment->toJson();
}
}
}
Please note that wen i submit a new comment the event is happening, a new division have been created, but its empty.
Anyone can help with this problem ?! Thank you in advance
Problem: how can I display data with update function?
the notification is sent but witout data that I specified in this function :
public function toDatabase($notifiable)
{
return [
'data'=>$this->booking->num_ch
];
}
it works with store function but it dosn't with update function
my notification class:
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
use App\Booking;
class NewMessage extends Notification
{
use Queueable;
public $booking;
public function __construct(Booking $booking)
{
//
$this->booking = $booking;
}
public function via($notifiable)
{
return ['database'];
}
public function toDatabase($notifiable)
{
return [
'data'=>$this->booking->num_ch
];
}
my update function :
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Booking;
use App\User;
use Notification;
use App\Notifications\NewMessage;
class DispoController extends Controller
{
public function update(Request $request,$id,Booking $booking)
{
//
Booking::findOrFail($id)->update([
'num_ch'=>$request->num_ch,
'type'=>$request->type,
'statut'=>$request->statut,
'enfants'=>$request->enfants,
'adultes'=>$request->adultes,
]);
auth()->user()->notify(new NewMessage($booking)); // notification
return redirect()->route('booking.index')->with(['success'=>'succés']);
}
it shows just "new booking"
#foreach(Auth::user()->unreadNotifications as $not)
<li>
<a class="dropdown-item" >new booking {{$not->data['data']}}</a>
</li>
#endforeach
public function update(Request $request,$id,Booking $booking)
{
//
Booking::findOrFail($id)->update([
'num_ch'=>$request->num_ch,
'type'=>$request->type,
'statut'=>$request->statut,
'enfants'=>$request->enfants,
'adultes'=>$request->adultes,
]);
auth()->user()->notify(new NewMessage(Booking::findOrFail($id)));
// notification
return redirect()->route('info_client.index')->with(['success'=>'succés']);
}
The issue is your not capturing the saved booking, should be like so
public function update(Request $request,$id,Booking $booking)
{
//
$booking = Booking::findOrFail($id)->update([
'num_ch'=>$request->num_ch,
'type'=>$request->type,
'statut'=>$request->statut,
'enfants'=>$request->enfants,
'adultes'=>$request->adultes,
]);
auth()->user()->notify(new NewMessage($booking)); // notification
return redirect()->route('booking.index')->with(['success'=>'succés']);
}
So your passing in an empty booking from the function call and passing that to the notification and not the updated record.
But you can simplify the whole thing by doing this
public function update(Request $request, Booking $booking)
{
//
$booking->update([
'num_ch'=>$request->num_ch,
'type'=>$request->type,
'statut'=>$request->statut,
'enfants'=>$request->enfants,
'adultes'=>$request->adultes,
]);
auth()->user()->notify(new NewMessage($booking)); // notification
return redirect()->route('booking.index')->with(['success'=>'succés']);
}
So instead of passing both id and booking just pass in the booking which should automatically be found from the Route and container.
I use laravel 5.3
I make routes/channels.php like this :
<?php
Broadcast::channel('messages', function() {
return true;
});
If I input the data cart and click submit, it will run this :
this.$http.post(window.BaseUrl + '/guest/add-notification', {cart_data: JSON.stringify(data)});
It will call function on the controller
The function like this :
public function addNotification(Request $request){
$input = $request->only('cart_data');
$data = json_decode($input['cart_data'], true);
event(new CartNotificationEvent($data));
}
Then it will call event
The event like this :
<?php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
class CartNotificationEvent
{
use InteractsWithSockets, SerializesModels;
public $data;
public function __construct($data)
{
$this->data = $data;
}
public function broadcastWith()
{
return [
'message' => $this->data,
];
}
public function broadcastAs()
{
return 'newMessage';
}
public function broadcastOn()
{
return new Channel('messages');
}
}
On the client, I do like this :
Echo.channel('messages')
.listen('.newMessage', (message) => {
console.log('test')
console.log(message);
});
When all the code is executed, I check on the console, the console.log not display
Why is it not working?
If I see the whole code that I make, it seems the process is correct
class CartNotificationEvent implements ShouldBroadcast is missing.