I currently have a live app that i am making huge changes too so i am working locally using Homestead. I previously used One Queue but with changes and all that i had to run multiple queues. The previous default queues was meant to make rows in a database table and one of the recent ones was to send emails. then i needed another one that I need to make rows in another table as well...issue is sometimes it works and other times it fails and sometimes it only creates one row before failing. the most annoying thing is that it is supposed to fire an event per row created in the database but that does not even occur at all. I had done it effectively before and it never failed me even the default queue still works fine.
here is the controller:
<?php
namespace App\Http\Controllers;
use Redirect;
use App\Short;
use App\Wallet;
use \SplFixedArray;
use App\Jobs\ShortQueuer;
use Illuminate\Http\Request;
use App\Http\Requests\SlotRequest;
class ShortController extends Controller
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index()
{
return view('short_term_goals');
}
/**
* Show the form for creating a new resource.
*
* #return \Illuminate\Http\Response
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
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();
ShortQueuer::dispatch($slotquantity, $user)->onQueue('shorts');
}
//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 Short Term Goals are Currently being met .');
}
/**
* Display the specified resource.
*
* #param \App\Short $short
* #return \Illuminate\Http\Response
*/
public function show(Short $short)
{
//
}
/**
* Show the form for editing the specified resource.
*
* #param \App\Short $short
* #return \Illuminate\Http\Response
*/
public function edit(Short $short)
{
//
}
/**
* Update the specified resource in storage.
*
* #param \Illuminate\Http\Request $request
* #param \App\Short $short
* #return \Illuminate\Http\Response
*/
public function update(Request $request, Short $short)
{
//
}
/**
* Remove the specified resource from storage.
*
* #param \App\Short $short
* #return \Illuminate\Http\Response
*/
public function destroy(Short $short)
{
//
}
}
Here is the job
<?php
namespace App\Jobs;
use App\Short;
use Illuminate\Bus\Queueable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
class ShortQueuer 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 $short) {
$short = new Short();
$short->user_id = $this->user->id;
$short->save();
//Slot Counting Event
event(new ShortCounter);
}
}
public $tries = 1;
public $timeout = 86400;
public $retryAfter = 87000;
}
here is the event
<?php
namespace App\Events;
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 ShortCounter
{
use Dispatchable, InteractsWithSockets, SerializesModels;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct()
{
//
}
/**
* Get the channels the event should broadcast on.
*
* #return \Illuminate\Broadcasting\Channel|array
*/
public function broadcastOn()
{
return new PrivateChannel('channel-name');
}
}
Here is the listener
<?php
namespace App\Listeners;
use App\Short;
use App\Goal;
use App\Events\ShortCounter;
use Illuminate\Http\Request;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
class GoalCreator
{
/**
* Create the event listener.
*
* #return void
*/
public function __construct()
{
//
}
/**
* Handle the event.
*
* #param ShortCounter $event
* #return void
*/
public function handle(ShortCounter $event)
{
$shortcount = Short::all()->count();
if($shortcount == 800) {
$goalshort = Short::latest()->first();
$goal = new Goal();
$goal->gid = unique_random('goals', 'sgid', 8);
$goal->grc = unique_random('goals', 'sgrc', 12);
$goal->status = 0;
$goal->amount = 200;
$goal->user_id = $goalshort->user_id;
$goal->save();
Short::truncate();
}
}
}
I sort it out.....I went through the error logs and solved the errors one after the other. First I forgot to include the Event Class in the Job, then a column name in my database was wrong then I restarted my server.
Related
I would like to send a mail from a button on Laravel Nova with an action (which I think is the most appropriate).
I already have a template of the mail saved in the mailable, I have made my resource but I don't know what to put inside since I need to retrieve information from this resource like for example the name, a price or the date when the line was created (in my table related to my resource).
My resource code:
<?php
namespace App\Nova;
use App\Image;
use Gloudemans\Shoppingcart\Cart;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Laravel\Nova\Fields\Currency;
use Laravel\Nova\Fields\Date;
use Laravel\Nova\Fields\Heading;
use Laravel\Nova\Fields\ID;
use Laravel\Nova\Fields\Text;
use Laravel\Nova\Http\Requests\NovaRequest;
use Techouse\IntlDateTime\IntlDateTime;
class Order extends Resource
{
/**
* The model the resource corresponds to.
*
* #var string
*/
public static $model = \App\Order::class;
public static $group = 'Paramètres';
public static function label()
{
return __('Commandes');
}
public static function singularLabel()
{
return __('Commande');
}
/**
* The single value that should be used to represent the resource when being displayed.
*
* #var string
*/
public static $title = 'id';
/**
* The columns that should be searched.
*
* #var array
*/
public static $search = [
'id',
];
/**
* Get the fields displayed by the resource.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
public function fields(Request $request)
{
return [
ID::make()->sortable(),
Text::make('Nom du client', 'name'),
IntlDateTime::make('Passée le', 'created_at')
->locale('fr')
->readonly(),
Currency::make('Prix', 'total')->currency('EUR'),
Text::make('Mode de paiement', 'gateway')
->readonly(),
Text::make('Numéro de téléphone', 'phone'),
Heading::make('Adresse de livraison'),
Text::make('Adresse', 'address')
->hideFromIndex(),
Text::make('Code postal', 'postal_code')
->hideFromIndex(),
Text::make('Ville', 'city')
->hideFromIndex(),
Text::make('Pays', 'country')
->hideFromIndex(),
];
}
/**
* Get the cards available for the request.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
public function cards(Request $request)
{
return [];
}
/**
* Get the filters available for the resource.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
public function filters(Request $request)
{
return [];
}
/**
* Get the lenses available for the resource.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
public function lenses(Request $request)
{
return [];
}
/**
* Get the actions available for the resource.
*
* #param \Illuminate\Http\Request $request
* #return array
*/
public function actions(Request $request)
{
return [];
}
}
My mailable code:
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class ResendOrder extends Mailable
{
use Queueable, SerializesModels;
/**
* Elements de contact
* #var array
*/
public $contact;
/**
* Create a new message instance.
*
* #return void
*/
public function __construct(Array $contact)
{
$this->contact = $contact;
}
/**
* Build the message.
*
* #return $this
*/
public function build()
{
return $this->view('emails.orderconfirmation')
->subject("Confirmation de commande");
}
}
And finally my Action code:
<?php
namespace App\Nova\Actions;
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 EmailOrderConfirmation extends Action
{
use InteractsWithQueue, Queueable;
/**
* Perform the action on the given models.
*
* #param \Laravel\Nova\Fields\ActionFields $fields
* #param \Illuminate\Support\Collection $models
* #return mixed
*/
public $name = 'Renvoyer le mail de confirmation de commande';
public function handle(ActionFields $fields, Collection $models)
{
return Action::message('Mail envoyé');
}
/**
* Get the fields available on the action.
*
* #return array
*/
public function fields()
{
return [];
}
}
I don't really know where to go and what to use, if you could enlighten me on that I would be very grateful, thank you!
// in EmailOrderConfirmation --nova action
// declare what you are using
// use Illuminate\Support\Facades\Mail;
// use App\Mail\ResendOrder;
public function handle(ActionFields $fields, Collection $models)
{
//loop over the orders that have been selected in nova
foreach ($models as $order) {
$contact = $order->contract; //however you are getting contract data
//assuming you have a $order->user order belongs to user relationship
//send mail to the user, with the order/contract details to create your email
Mail::to($order->user->email)->send(new ResendOrder($contact));
}
//return a message to nova
return Action::message('Mail envoyé');
}
// in Order /Nova resource
// declare what you are using
// use App\Nova\Actions\EmailOrderConfirmation;
public function actions(Request $request)
{
return [new EmailOrderConfirmation];
}
So i've got some middleware here:
namespace App\Http\Middleware;
use Closure;
use App\ChatLog;
use App\Http\Services;
class LogChat
{
protected $chatLogService;
public function __construct(ChatLogService $chatLogService)
{
$this->chatLogService = $chatLogService;
}
/**
* Handle an incoming request.
*
* #param \Illuminate\Http\Request $request
* #param \Closure $next
* #return mixed
*/
public function handle($request, Closure $next)
{
$chatLog = new ChatLog;
$chatLog->companyid = '5';
$chatLog->type = 'REQUEST';
$chatLog->ipaddress = '1';
$chatLog->name = 'bob';
$chatLog->message = 'testmessage';
$chatLog->action = 'click';
$chatLog->timeTaken = '1';
$chatLog->fullLog = 'all the log';
$this->chatLogService->store($chatLog);
return $next($request);
}
}
which calls this service here:
namespace App\Http\Services;
use App\ChatLog;
use Illuminate\Support\Facades\DB;
class ChatLogService
{
/**
* Display a listing of the resource.
*
*/
public function index()
{
//
}
/**
* Store a newly created resource in storage.
*
* #param \App\ChatLog $chatLog
*/
public function store(ChatLog $chatLog)
{
$chatLog->save();
}
/**
* Display the specified resource.
*
* #param \App\ChatLog $chatLog
*/
public function show(ChatLog $chatLog)
{
//
}
}
which is injected in here:
<?php
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* #return void
*/
public function register()
{
$this->app->bind(ChatLogService::class, function ($app) {
return new ChatLogService();
});
}
/**
* Bootstrap any application services.
*
* #return void
*/
public function boot()
{
//
}
}
But this gives me the following exception: ReflectionException
Class App\Http\Middleware\ChatLogService does not exist
What i want to do is call the "store" method in a nicely abstracted way and i feel this solution is very close - however, I can't seem to get around this error. I'm not sure if it's something simple that i'm missing, or if the approach is fundamentally wrong!
I can't see what's wrong!
Ta :)
So I am having a bit of an interesting problem. I am trying to build a forum for my website. I am trying to create a test that ensures registered users can submit new forum threads. Now, regardless of what I do, the test always ends up at the login paghe, even though I am logged in.
Here is something interesting, however, when I attempt to dd() the thread immediately after creation, Laravel seems to "skip over" the dd command and I end up with the "Thread title not found on the login page" error. I can dd() the $request object and that prints out fine, however, it seems after creating a new Thread model does Laravel skip over the dd($thread) command and I end up getting the login page once again.
I am pulling my hair out. Why is this happening?
<?php
namespace Tests\Feature;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Tests\TestCase;
use App\Thread;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Foundation\Testing\RefreshDatabase;
class CreateThreadsTest extends TestCase
{
use DatabaseMigrations;
function test_an_authenticated_user_can_create_new_forum_threads() {
$this->be(factory('App\User')->create());
$thread = factory('App\Thread')->make();
$this->post('forum/threads', $thread->toArray());
// you are missing this line
$this->get($thread->path())->assertSee($thread->title)->assertSee($thread->body);
}
}
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Thread;
class ThreadsController extends Controller
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index()
{
$threads = Thread::latest()->get();
return view('threads.index', compact('threads'));
}
/**
* Show the form for creating a new resource.
*
* #return \Illuminate\Http\Response
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*
* #param \Illuminate\Http\Request $request
* #return \Illuminate\Http\Response
*/
public function store(Request $request)
{
$thread = Thread::create([
'user_id' => auth()->id,
'title' => $request->title,
'body' => $request->body
]);
return redirect($thread->path());
}
/**
* Display the specified resource.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function show(Thread $thread)
{
return view('threads.show', compact('thread'));
}
/**
* Show the form for editing the specified resource.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function edit($id)
{
//
}
/**
* Update the specified resource in storage.
*
* #param \Illuminate\Http\Request $request
* #param int $id
* #return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
{
//
}
/**
* Remove the specified resource from storage.
*
* #param int $id
* #return \Illuminate\Http\Response
*/
public function destroy($id)
{
//
}
}
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Thread extends Model
{
protected $guarded = [];
public function path() {
return "/forum/threads/" . $this->id;
}
public function replies() {
return $this->hasMany(Reply::class);
}
public function creator()
{
return $this->belongsTo(User::class, 'user_id');
}
public function addReply($reply) {
$this->replies()->create($reply);
}
}
When you make a new model using the factory helper, it doesn't have an ID
for example
So $thread->path() will return just "/forum/threads/" which is not what you want
You have to make the request to the location from the response or query the newly created Thread record
public function test_users_can_create_statuses()
{
$this->be(factory('App\User')->create());
$thread = factory('App\Thread')->make();
$response = $this->post('/forum/threads', $thread->toArray());
$this->get($response->headers->get('Location'))
->assertSee($thread->title);
->assertSee($thread->body);
}
I setup my classes so I can use Laravel Authorization and use the Policies feature. But I keep getting this error (Class App\Policies\StatusPolicy does not exist) when defining the middleware to my methods. This is what I have:
AuthServiceProvider.php
namespace App\Providers;
use Illuminate\Support\Facades\Gate;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
class AuthServiceProvider extends ServiceProvider
{
/**
* The policy mappings for the application.
*
* #var array
*/
protected $policies = [
'App\Status' => 'App\Policies\StatusPolicy',
];
/**
* Register any authentication / authorization services.
*
* #return void
*/
public function boot()
{
$this->registerPolicies();
//
}
}
StatusController.php
namespace App\Http\Controllers;
use App\Status;
use Illuminate\Http\Request;
class StatusController extends Controller
{
public function __construct()
{
$this->middleware('can:list,App\Status')->only('index');
$this->middleware('can:update,status')->only('edit');
}
// ...
StatusPolicy.php (generated by php artisan make:policy StatusPolicy --model=Status
namespace Policies;
use App\User;
use App\Status;
use Illuminate\Auth\Access\HandlesAuthorization;
class StatusPolicy
{
use HandlesAuthorization;
/**
* Verifica se o usuário tem permissão para listar os status.
*
* #param \App\User $user
* #return bool
*/
public function list(User $user)
{
return true;
}
/**
* Determine whether the user can view the status.
*
* #param \App\User $user
* #param \App\Status $status
* #return mixed
*/
public function view(User $user, Status $status)
{
//
}
/**
* Determine whether the user can create statuses.
*
* #param \App\User $user
* #return mixed
*/
public function create(User $user)
{
//
}
/**
* Determine whether the user can update the status.
*
* #param \App\User $user
* #param \App\Status $status
* #return mixed
*/
public function update(User $user, Status $status)
{
return true;
}
/**
* Determine whether the user can delete the status.
*
* #param \App\User $user
* #param \App\Status $status
* #return mixed
*/
public function delete(User $user, Status $status)
{
//
}
}
I found the problem.
For some reason, the command php artisan make:policy created a file with a wrong namespace. The fix was to change the namespace in the StatusPolicy.php file:
From namespace Policies;
To namespace App\Policies;
change the namespace in your StatusPolicy class to App\Policies;
I using Laravel 5.4 and I am trying to write a policy for my index view. I am trying to use a Method Without a Model, I am receiving the following error:
HttpException in Handler.php line 133:
This action is unauthorized.
Here is my Controller:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\County;
use Session;
use App\Http\Controllers\Controller;
class CountyController extends Controller
{
/**
* Create a new controller instance.
*
* #return void
*/
public function __construct()
{
$this->middleware('auth');
}
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index()
{
$counties = County::orderBy('id', 'desc')->paginate(5);
$this->authorize('index');
return view('county.index', array(
'counties' => $counties
));
}
Here is my AuthServicePovider:
<?php
namespace App\Providers;
use Illuminate\Support\Facades\Gate;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
use App\Role;
use App\County;
use App\Policies\CountyPolicy;
class AuthServiceProvider extends ServiceProvider
{
/**
* The policy mappings for the application.
*
* #var array
*/
protected $policies = [
County::class => CountyPolicy::class,
];
/**
* Register any authentication / authorization services.
*
* #return void
*/
public function boot()
{
$this->registerPolicies();
Gate::define('is-Admin', function ($user) {
if($user->roles()->where('name','Admin')->first()){
return true;
}
return false;
});
}
}
Here is my Policy:
<?php
namespace App\Policies;
use App\User;
use App\Role;
use App\County;
use Illuminate\Auth\Access\HandlesAuthorization;
class CountyPolicy
{
use HandlesAuthorization;
/**
* Determine whether the user can view the county.
*
* #param \App\User $user
* #param \App\County $county
* #return mixed
*/
public function index(User $user)
{
$userRoles = $user->getRoleNames();
$acceptedRoles = ['Sudo','Admin'];
$testArr = array_intersect($acceptedRoles, $userRoles);
dd($testArr);
if(!empty($testArr)){
return true;
}
return false;
//
}
/**
* Determine whether the user can view the county.
*
* #param \App\User $user
* #param \App\County $county
* #return mixed
*/
public function view(User $user, County $county)
{
$userRoles = $user->getRoleNames();
$acceptedRoles = ['Sudo','Admin','Client'];
$testArr = array_intersect($acceptedRoles, $userRoles);
if(!empty($testArr)){
return true;
}
return false;
//
}
/**
* Determine whether the user can create counties.
*
* #param \App\User $user
* #return mixed
*/
public function create(User $user)
{
//
}
/**
* Determine whether the user can update the county.
*
* #param \App\User $user
* #param \App\County $county
* #return mixed
*/
public function update(User $user, County $county)
{
//
}
/**
* Determine whether the user can delete the county.
*
* #param \App\User $user
* #param \App\County $county
* #return mixed
*/
public function delete(User $user, County $county)
{
//
}
}
I never get to dd($testArr) in the index policy. Also the view policy is working perfectly.
How do I write a policy for my index view?
keeping everything the same but changing:
$this->authorize('index');
to
$this->authorize('index', County::class);
fixed the problem. Apparently the model class needs to be passed on actions that don't require a model. This is only described under the middleware section of Laravel's docs, not the controller helpers... A little confusing.