Job Function just keeps processing without being processed - laravel

I am trying to create multiple rows in the database table behind the scene in order to decrease page loading time so I am implementing laravel queue for that. But the actual job does not seem to be implementing without any errors
this is in my controller
public function store(SlotRequest $request)
{
$quota = 2;
$slotquota = request('slotamount') + $quota;
if ( auth()->user()->wallet->balance < $slotquota ) {
return Redirect::back()->with('low_balance', 'You do not have a sufficient wallet balance to reserve these SLOTS. Please Load Up Your Wallet');
} else {
// Getting SLOTS as objects of an array
$slotquantity = new SplFixedArray(request('slotamount'));
$slotquantity = $slotquantity->toArray();
$user = auth()->user();
SlotQueuer::dispatch($slotquantity, $user);
}
//Sorting Wallet Balance
$wallet = Wallet::where('user_id', auth()->user()->id)->first();
$wallet->balance = $wallet->balance - $slotquota;
$wallet->save();
//Returning View With Message
return Redirect::back()->with('reserved', 'Your SLOTS have been successfully reserved');
}
and for my job
namespace App\Jobs;
use App\Events\SlotCounter;
use App\Slot;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
class SlotQueuer implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
protected $slotquantity;
protected $user;
/**
* Create a new job instance.
*
* #return void
*/
public function __construct(array $slotquantity, $user)
{
$this->slotquantity = $slotquantity;
$this->user = $user;
}
/**
* Execute the job.
*
* #return void
*/
public function handle()
{
// Inserting Rows in SLOTS Table
foreach ($this->slotquantity as $slot) {
$slot = new Slot();
$slot->user_id = $this->user->id;
$slot->save();
//Slot Counting Event
event(new SlotCounter);
}
}
}
I am hoping to create database rows behind the scenes

Please change in your job class
protected $slotquantity;
protected $user;
public function __construct($slotquantity , $user)
{
$this->slotquantity = $slotquantity;
$this->user = $user;
}
In your handle() function
public function handle()
{
// Inserting Rows in SLOTS Table
foreach ($this->slotquantity as $slot) { //use this keyword to access slotquantity
$slot = new Slot();
$slot->user_id = $this->user->id;
$slot->save();
//Slot Counting Event
event(new SlotCounter);
}
}

Related

Laravel Nova 3 - Queued Actions - Can I skip model?

I'm using Laravel Nova 3 Queued Actions.
I have over 25K records in my table.
I want to Laravel Nova Action create new job only if model has attribute status == 1.
I tried to use continue in foreach loop but it does'nt work.
<?php
namespace App\Nova\Actions;
use App\Http\Services\UserService;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Support\Collection;
use Laravel\Nova\Actions\Action;
use Laravel\Nova\Fields\ActionFields;
class UserSynchronization extends Action implements ShouldQueue
{
use InteractsWithQueue, Queueable;
public $name = 'Synchronize User';
public static $chunkCount = 1;
public $withoutActionEvents = true;
public function __construct()
{
$this->connection = 'database';
//$this->queue = 'default';
}
/**
* Perform the action on the given models.
*
* #param \Laravel\Nova\Fields\ActionFields $fields
* #param \Illuminate\Support\Collection $models
* #return mixed
*/
public function handle(ActionFields $fields, Collection $models)
{
foreach ($models as $model) {
if (!$model->status !== 1) {
continue;
}
UserService::synchronize($model);
}
return Action::message('Users have been successfully synchronized');
}
/**
* Get the fields available on the action.
*
* #return array
*/
public function fields()
{
return [];
}
}
Create record in jobs table only if model->status === 1

How to passing variable from controller to view queued mail?

I'm trying to pass variable $array from controller to mail blade, but whenever I run queue:listen. It always say failed.
Bellow is my code
In controller I have a variable named $array, I've putting it in dispatch
Controller
$array["view"] = "layouts.mail.order";
$array["subject"] = "Order Created";
$array["from"] = env('MAIL_USERNAME');
$array["data"] = "aaaaaaaaa";
$array["email"] = Auth::user()->email;
OrderEmailJob::dispatch($array);
OrderEmailJob
<?php
namespace App\Jobs;
use App\Mail\OrderMail;
use Illuminate\Bus\Queueable;
use Illuminate\Support\Facades\Mail;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
class OrderEmailJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public $array;
/**
* Create a new job instance.
*
* #return void
*/
public function __construct($array)
{
$this->array = $array;
}
/**
* Execute the job.
*
* #return void
*/
public function handle()
{
$email = new OrderMail();
Mail::to($this->array['email'])->send($array);
}
}
and this is code for the mailable
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class OrderMail extends Mailable
{
use Queueable, SerializesModels;
public $array;
/**
* Create a new message instance.
*
* #return void
*/
public function __construct($array)
{
$this->array = $array;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->view($this->array['view'])
->from($this->array['from'], env('MAIL_FROM_NAME'))
->subject($this->array['subject'])
->with([
'data' => $this->array['data'],
]);
}
}
The result I want is I can use variable $array in view for my mail, because I've to printed out data from $array variable
Sorry about my english, thanks
try like this :
public $mailData;
public function __construct($mailData)
{
$this->mailData = $mailData;
}
public function build()
{
// Array for Blade
$input = array(
'action' => $this->mailData['action'],
'object' => $this->mailData['object'],
);
return $this->view('emails.notification')
->with([
'inputs' => $input,
]);
}
I'm not sure, the answer correct. But you can change the name variable $array to $data and check again. Maybe your variable name is a special case like array keyword

How to store files attached to MMS from Twilio phone number into laravel database?

I am working on developing a website using Laravel 7. I also have a Twilio phone number that receives multimedia messages with attached files, and I want to store these files within my website's database. and I want to know what is wrong in the process
My controller Code is
<?php
namespace App\Http\Controllers;
use App\Http\Controllers\Controller;
use App\MMSMedia;
use App\Services\MediaMessageService\IMediaMessageService;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Magyarjeti\MimeTypes\MimeTypeConverter;
use Twilio\Rest\Client;
use Twilio\Twiml;
class MessagingController extends Controller
{
/*
|--------------------------------------------------------------------------
| Messaging Controller
|--------------------------------------------------------------------------
|
| This controller receives messages from Twilio and makes the media available
| via the /images url.
*/
protected $twilio;
protected $accountSid;
protected $twilioNumber;
protected $twilioNumberSid;
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->accountSid = env('TWILIO_SID');
$this->twilioNumber = env('TWILIO_NUMBER');
$this->twilioNumberSid = env('TWILIO_NUMBER_SID');
$authToken = env('TWILIO_AUTH_TOKEN');
$this->twilio = new Client($this->accountSid, $authToken);
}
public function handleIncomingSMS(Request $request, IMediaMessageService $mediaService)
{
$converter = new MimeTypeConverter;
$NumMedia = (int)$request->input('NumMedia');
$FromNumber = $request->input('From');
$MessageSid = $request->input('MessageSid');
for ($i=0; $i < $NumMedia; $i++) {
$mediaUrl = $request->input("MediaUrl$i");
$MIMEType = $request->input("MediaContentType$i");
$fileExtension = $converter->toExtension($MIMEType);
$mediaSid = basename($mediaUrl);
$media = $mediaService->getMediaContent($mediaUrl);
$filename = "$mediaSid.$fileExtension";
$mediaData = compact('mediaSid', 'MessageSid', 'mediaUrl', 'media', 'filename', 'MIMEType');
$mmsMedia = new MMSMedia($mediaData);
$mmsMedia->save();
}
$response = new Twiml();
$messageBody = $NumMedia == 0 ? 'Send us an image!' : "Thanks for the $NumMedia images.";
$message = $response->message([
'from' => $request->input('To'),
'to' => $FromNumber
]);
$message->body($messageBody);
return (string)$response;
}
public function deleteMediaFromTwilio($mediaItem)
{
return $this->twilio->api->accounts($this->accountSid)
->messages($mediaItem['MessageSid'])
->media($mediaItem['mediaSid'])
->delete();
}
public function allMedia()
{
$mediaItems = MMSMedia::all();
return $mediaItems;
}
public function getMediaFile($filename, Response $response)
{
$media = MMSMedia::where('filename', $filename)->firstOrFail();
$fileContents = $media['media'];
$MessageSid = $media['MessageSid'];
$mediaSid = $media['mediaSid'];
$MIMEType = $media['MIMEType'];
$media->delete();
$this->deleteMediaFromTwilio(compact('mediaSid', 'MessageSid'));
return response($fileContents, 200)
->header('Content-Type', $MIMEType);
}
public function config()
{
return ['twilioNumber' => $this->twilioNumber];
}
}
and my table in database is
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateMMSMediaTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('m_m_s_media', function (Blueprint $table) {
$table->id();
$table->timestamps();
$table->string('mediaSid')->index();
$table->string('MessageSid')->index();
$table->string('mediaUrl')->index();
$table->binary('media');
$table->string('filename')->index();
$table->string('MIMEType');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('m_m_s_media');
}
}
I did what the process need but i do not know why it is not working

Laravel 5.7 - Access Auth::User() inside a service provider

I need to access to the current user in a service provider of a module. The Auth::user() returns null. I know the middleware is called after the service provider and that is why this is null. Is there any solution to this problem? it is my code
namespace Modules\User\Providers;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\ServiceProvider;
use Nwidart\Modules\Facades\Module;
class ViewComposerProvider extends ServiceProvider
{
/**
* Indicates if loading of the provider is deferred.
*
* #var bool
*/
protected $defer = false;
/**
* Register the service provider.
*
* #return void
*/
public function boot()
{
$this->buildMenu();
$this->buildAvatar();
}
public function register()
{
dd(Auth::user());//null
}
private function buildAvatar(){
$f = Auth::user();
dd($f); // null
}
public function buildMenu()
{
view()->composer('layouts.subnavbar', function ($view) {
$t = \Nwidart\Modules\Facades\Module::getByStatus(1);
$modules = [];
foreach ($t as $item)
$modules[] = $item->name;
$view->with('modules', $modules);
});
}
/**
* Get the services provided by the provider.
*
* #return array
*/
public function provides()
{
return [];
}
}
Instead of calling the user in the provider you could make 2 view composers, 1 for the menu and 1 for the avatar
AvatarComposer.php
class AvatarComposer
{
public function compose(View $view)
{
$avatar = Auth::user()->avatar//AVATAR HERE
$view->with('avatar', $avatar);
}
}
ModuleComposer.php
class ModuleComposer
{
public function compose(View $view)
{
$t = \Nwidart\Modules\Facades\Module::getByStatus(1);
$modules = [];
foreach ($t as $item)
$modules[] = $item->name;
$view->with('modules', $modules);
}
}
and then in the boot of your provider:
//make it public for all routes
View::composer('*', AvatarComposer::class);
View::composer('layouts.subnavbar', ModuleComposer::class);

Laravel authentication without global scope

In my Laravel app users can disable (not delete) their account to disappear from the website. However, if they try to login again their account should be activated automatically and they should log in successfully.
This is done with "active" column in the users table and a global scope in User model:
protected static function boot() {
parent::boot();
static::addGlobalScope('active', function(Builder $builder) {
$builder->where('active', 1);
});
}
The problem now is that those inactive accounts can't log in again, since AuthController does not find them (out of scope).
What I need to achieve:
Make AuthController ignore global scope "active".
If username and password are correct then change the "active" column value to "1".
The idea I have now is to locate the user using withoutGlobalScope, validate the password manually, change column "active" to 1, and then proceed the regular login.
In my AuthController in postLogin method:
$user = User::withoutGlobalScope('active')
->where('username', $request->username)
->first();
if($user != null) {
if (Hash::check($request->username, $user->password))
{
// Set active column to 1
}
}
return $this->login($request);
So the question is how to make AuthController ignore global scope without altering Laravel main code, so it will remain with update?
Thanks.
Create a class GlobalUserProvider that extends EloquentUserProvider like below
class GlobalUserProvider extends EloquentUserProvider {
public function createModel() {
$model = parent::createModel();
return $model->withoutGlobalScope('active');
}
}
Register your new user provider in AuthServiceProvider:
Auth::provider('globalUserProvider', function ($app, array $config) {
return new GlobalUserProvider($this->app->make('hash'), $config['model']);
});
Finally you should change your user provider driver to globalUserProvider in auth.php config file.
'providers' => [
'users' => [
'driver' => 'globalUserProvider',
'model' => App\Models\User::class
]
]
protected static function boot()
{
parent::boot();
if (\Auth::check()) {
static::addGlobalScope('active', function(Builder $builder) {
$builder->where('active', 1);
});
}
}
Please try this for login issue, You can activate after login using withoutGlobalScopes().
#Sasan's answer is working great in Laravel 5.3, but not working in 5.4 - createModel() is expecting a Model but gets a Builder object, so when EloquentUserProvider calls $model->getAuthIdentifierName() an exception is thrown:
BadMethodCallException: Call to undefined method Illuminate\Database\Query\Builder::getAuthIdentifierName() in /var/www/vendor/laravel/framework/src/Illuminate/Database/Query/Builder.php:2445
Instead, follow the same approach but override more functions so that the right object is returned from createModel().
getQuery() returns the builder without the global scope, which is used by the other two functions.
class GlobalUserProvider extends EloquentUserProvider
{
/**
* Get query builder for the model
*
* #return \Illuminate\Database\Eloquent\Builder
*/
private function getQuery()
{
$model = $this->createModel();
return $model->withoutGlobalScope('active');
}
/**
* Retrieve a user by their unique identifier.
*
* #param mixed $identifier
* #return \Illuminate\Contracts\Auth\Authenticatable|null
*/
public function retrieveById($identifier)
{
$model = $this->createModel();
return $this->getQuery()
->where($model->getAuthIdentifierName(), $identifier)
->first();
}
/**
* Retrieve a user by their unique identifier and "remember me" token.
*
* #param mixed $identifier
* #param string $token
* #return \Illuminate\Contracts\Auth\Authenticatable|null
*/
public function retrieveByToken($identifier, $token)
{
$model = $this->createModel();
return $this->getQuery()
->where($model->getAuthIdentifierName(), $identifier)
->where($model->getRememberTokenName(), $token)
->first();
}
}
Sasan Farrokh has a right answer. The only thing not to rewrite createModel but newModelQuery and this will work
protected function newModelQuery($model = null)
{
$modelQuery = parent::newModelQuery();
return $modelQuery->withoutGlobalScope('active');
}
Extend the AuthController with the code you used in your OP. That should work.
public function postLogin(Request $request)
{
$user = User::withoutGlobalScope('active')
->where('username', $request->username)
->first();
if($user != null){
if (Hash::check($request->password, $user->password)){
$user->active = 1;
$user->save();
}
}
return $this->login($request);
}
I resolved it by creating the new package.
mpyw/scoped-auth: Apply specific scope for user authentication.
Run composer require mpyw/scoped-auth and modify your User model like this:
<?php
namespace App;
use Illuminate\Auth\Authenticatable;
use Illuminate\Contracts\Auth\Authenticatable as UserContract;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Mpyw\ScopedAuth\AuthScopable;
class User extends Model implements UserContract, AuthScopable
{
use Authenticatable;
public function scopeForAuthentication(Builder $query): Builder
{
return $query->withoutGlobalScope('active');
}
}
You can also easily pick Illuminate\Auth\Events\Login to activate User on your Listener.
<?php
namespace App\Providers;
use Illuminate\Support\Facades\Event;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
class EventServiceProvider extends ServiceProvider
{
/**
* The event listener mappings for the application.
*
* #var array
*/
protected $listen = [
\Illuminate\Auth\Events\Login::class => [
\App\Listeners\ActivateUser::class,
],
];
/**
* Register any events for your application.
*
* #return void
*/
public function boot()
{
parent::boot();
//
}
}
 
<?php
namespace App\Listeners;
use Illuminate\Auth\Events\Login;
class ActivateUser
{
/**
* Handle the event.
*
* #param Illuminate\Auth\Events\Login $event
* #return void
*/
public function handle(Login $event)
{
$event->user->fill('active', 1)->save();
}
}
 
I had to use
->withoutGlobalScopes() instead
in order for it to work

Resources