I want to send email with pdf attachment in SendReport job.
<?php
namespace App\Jobs;
use App\Models\Site;
use App\Models\User;
use App\Repositories\PositionRepository;
use Barryvdh\DomPDF\Facade as Pdf;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Support\Facades\Mail;
class SendReport extends Job implements ShouldQueue
{
use InteractsWithQueue, SerializesModels;
private $email = '';
private $period = '';
private $siteId = -1;
public function __construct(string $email, string $period, int $siteId)
{
$this->email = $email;
$this->period = $period;
$this->siteId = $siteId;
}
public function handle()
{
$site = Site::find($this->siteId);
$period = $this->period;
$repo = new PositionRepository();
list($searchRequests, $positions) = $repo->getTodayPositions($site);
$pdf = Pdf::loadView(
'report.report',
compact('site', 'period', 'searchRequests', 'positions')
);
$content = $pdf->output('report.pdf');
$user = User::where('email', $this->email)->first();
Mail::queue(
'emails.report',
[
'user' => $user,
],
function ($m) use ($user, $content) {
$m->to($user->email, $user->name)
->cc(env('ADMIN_EMAIL'))
->subject('Report');
$m->attachData($content, 'Report.pdf', [
'mime' => 'application/pdf',
]);
}
);
}
}
But it shows me ReflectionException in Container.php line 738: Class does not exist. If I save pdf to file and then use attach($pathToFile, ...) instead of attachData($pdfContent, ...) it works. Or if I don't pass $content to Closure, all is ok, message is sent.
Mail::queue(
'emails.report',
[
'user' => $user,
],
function ($m) use ($user) {
$m->to($user->email, $user->name)
->cc(env('ADMIN_EMAIL'))
->subject('Report');
}
);
Maybe pdf size is too big? I want to use exactly attachData() instead of attach($pathToFile, ...).
Related
I have been trying to create a point system, so after much effort i am getting this error which i could not figure out how to solve it because this is my first time working so deep
I have checked code but couldn't pinpoint the error
call to undefined app\models\User:id()
point model
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\MorphTo;
class Point extends Model
{
use HasFactory;
const TABLE = 'points';
protected $table = self::TABLE;
protected $fillable = [
'id', 'amount', 'message', 'current_points'
];
public function pointable(): MorphTo
{
return $this->morphTo();
}
public function getCurrentPoints(Model $pointable)
{
$currentPoints = Point::where('pointable_id', $pointable->id())
->where('pointable_type', $pointable->getMorphClass())
->orderBy('created_at', 'desc')
->pluck('current_points')->first();
if($currentPoints){
$currentPoints = 0;
}
return $currentPoints;
}
public function addAwards(Model $pointable, $amount, $message)
{
$award = new Static();
$award->amount = $amount;
$award->current_points = $this->getCurrentPoints($pointable) + $amount;
$award->message = $message
$pointable->awards()->save($award);
return $award;
}
}
pointable model
<?php
namespace App\Models;
interface pointable
{
public function awards();
public function countAwards();
public function addPoints($amount, $message);
}
hasPoints Traits
<?php
namespace App\Traits;
use App\Models\Point;
trait HasPoints
{
public function awards($amount = null)
{
return $this->morphMany(Point::class, 'pointable')
->orderBy('created_at', 'desc')
->take($amount);
}
public function countAwards()
{
return $this->awards()->count();
}
public function currentPoints()
{
return (new Point())->getCurrentPoints($this);
}
public function addPoints($amount, $message)
{
return (new Point())->addAwards($this, $amount, $message);
}
}
AwardPointLItener
?php
namespace App\Listeners;
use App\Events\ReplyWasCreated;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;
class AwardPointForNewReply
{
public function handle(ReplyWasCreated $event)
{
$amount = config('points.rewards.new_reply');
$message = 'User Created A New Reply';
$author = $event->reply->user;
$author->addPoints($amount, $message);
}
}
ReplyEvent
<?php
namespace App\Events;
use App\Models\Reply as Replyers;
use Illuminate\Queue\SerializesModels;
class ReplyWasCreated
{
use SerializesModels;
public $reply;
public function __construct(Replyers $reply)
{
$this->reply = $reply;
}
}
livewire reply componet
use Livewire\Component;
use App\Models\Reply as Replys;
class Reply extends Component
{
public $thread;
public $username;
public $reply_text;
public $replyCommentId = NULL;
protected $rules = [
'reply_text' => 'required'
];
public function mount(Thread $thread)
{
$this->thread = $thread;
}
public function render()
{
$replys = Replys::whereNull('parent_id')
->with('replies')
->with('user')
->where('thread_id', $this->thread->id)->paginate()->withQueryString();
return view('livewire.thread.reply',[
'replys' => $replys,
]);
}
public function save_reply()
{
$this->validate();
$replyevent = Replys::create([
'thread_id' => $this->thread->id,
'user_id' => auth()->user()->id,
'reply_text' => $this->reply_text,
'parent_id' => $this->replyCommentId
]);
event(new ReplyWasCreated($replyevent));
// $this->username = '';
$this->reply_text = '';
$this->replyCommentId = NULL;
}
public function deleteReply($id)
{
$reply = Replys::FindOrFail($id);
$reply->delete();
}
public function replys($replyId)
{
$this->replyCommentId = $replyId;
}
}
To get the id of a model, you simply access its id property. There is no id() method.
$currentPoints = Point::where('pointable_id', $pointable->id)
I need to modify /vendor/laravel/fortify/src/Contracts/CreatesNewUsers.php interface
and to add 1 more bool parameter, as using CreateNewUser in different places of the app
validations rules are different, say in some places password is not filled on user creation, but must be separate function.
So I copied file /project/resources/fortify/CreatesNewUsers.php with content :
<?php
namespace Laravel\Fortify\Contracts;
interface CreatesNewUsers
{
public function create(array $input, bool $makeValidation);
}
and in app/Actions/Fortify/CreateNewUser.php I modified :
<?php
namespace App\Actions\Fortify;
use App\Models\User;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
//use Laravel\Fortify\Contracts\CreatesNewUsers;
use Resources\Fortify\CreatesNewUsers; // Reference to my interface
use Laravel\Jetstream\Jetstream;
class CreateNewUser implements CreatesNewUsers
{
use PasswordValidationRules;
public function create(array $input, bool $makeValidation)
{
...
But trying to use this class I got error
Interface "Resources\Fortify\CreatesNewUsers" not found
Which is the valid way ?
Thanks!
I moved interface at file app/Actions/Fortify/CreatesNewUsers.php :
<?php
namespace App\Actions\Fortify;
interface CreatesNewUsers
{
public function create(array $input, bool $make_validation, array $hasPermissions);
}
and modified app/Actions/Fortify/CreateNewUser.php :
<?php
namespace App\Actions\Fortify;
use App\Models\User;
use Illuminate\Database\QueryException;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use DB;
use App\Actions\Fortify\CreatesNewUsers;
use Laravel\Jetstream\Jetstream;
use Spatie\Permission\Models\Permission;
class CreateNewUser implements CreatesNewUsers
{
use PasswordValidationRules;
/**
* Validate and create a newly registered user.
*
* #param array $input
*
* #return \App\Models\User
*/
public function create(array $input, bool $make_validation, array $hasPermissions)
{
if ($make_validation) {
$userValidationRulesArray = User::getUserValidationRulesArray(null, '', []);
if (\App::runningInConsole()) {
unset($userValidationRulesArray['password_2']);
}
$validator = Validator::make($input, $userValidationRulesArray);//->validate();
if ($validator->fails()) {
$errorMsg = $validator->getMessageBag();
if (\App::runningInConsole()) {
echo '::$errorMsg::' . print_r($errorMsg, true) . '</pre>';
}
return $errorMsg;
}
} // if($make_validation) {
$newUserData = [
'name' => $input['name'],
'email' => $input['email'],
'account_type' => $input['account_type'],
'phone' => $input['phone'],
'website' => $input['website'],
'notes' => $input['notes'],
'first_name' => $input['first_name'],
'last_name' => $input['last_name'],
];
if (isset($input['password'])) {
$newUserData['password'] = Hash::make($input['password']);
}
if (isset($input['status'])) {
$newUserData['status'] = $input['status'];
}
if (isset($input['activated_at'])) {
$newUserData['activated_at'] = $input['activated_at'];
}
if (isset($input['avatar'])) {
$newUserData['avatar'] = $input['avatar'];
}
try {
DB::beginTransaction();
$newUser = User::create($newUserData);
foreach ($hasPermissions as $nextHasPermission) {
$appAdminPermission = Permission::findByName($nextHasPermission);
if ($appAdminPermission) {
$newUser->givePermissionTo($appAdminPermission);
}
}
DB::commit();
return $newUser;
} catch (QueryException $e) {
DB::rollBack();
if (\App::runningInConsole()) {
echo '::$e->getMessage()::' . print_r($e->getMessage(), true) . '</pre>';
}
}
return false;
}
}
It allows me to use CreateNewUser from different parts of app, like seeders, adminarea, user registration
with different behaviour. For me it seems good way of using fortify and CreateNewUser...
I write a code using laravel 8 and i want to create CRUD Testing for all model so i can called it in every test case, for example I Have Operator Test that extends TestCase (crud testing master) ref : crud test, this is my Operator Test looks like,..
<?php
namespace Tests\Feature;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Tests\TestCase;
class OperatorTest extends TestCase
{
use RefreshDatabase, WithFaker;
public function test_user_can_update_an_operator()
{
$this->setBaseRoute('master.operator');
$this->setBaseModel('App\Models\Operator');
$this->signIn();
$this->attributes = [
'username' => 'test update',
'level' => 1,
'category_id' => 1,
'password' => 'password'
];
$this->update($this->attributes);
}
}
and this is my TestCase.php looks like,...
<?php
namespace Tests;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
use App\Models\Operator;
use Illuminate\Foundation\Testing\WithFaker;
abstract class TestCase extends BaseTestCase
{
use CreatesApplication;
use RefreshDatabase;
protected $base_route = null;
protected $base_model = null;
protected function signIn($user = null)
{
$user = $user ?? Operator::factory()->create();
$this->actingAs($user);
return $this;
}
protected function setBaseRoute($route)
{
$this->base_route = $route;
}
protected function setBaseModel($model)
{
$this->base_model = $model;
}
protected function update($attributes = [], $model = '', $route = '')
{
$this->withoutExceptionHandling();
$route = $this->base_route ? "{$this->base_route}.update" : $route;
$model = $this->base_model ?? $model;
$model = create($model);
if (! auth()->user()) {
$this->expectException(\Illuminate\Auth\AuthenticationException::class);
}
$response = $this->patchJson(route($route, $model->id), $attributes);
tap($model->fresh(), function ($model) use ($attributes) {
collect($attributes)->each(function($value, $key) use ($model) {
$this->assertEquals($value, $model[$key]);
});
});
return $response;
}
}
after that when I tun php artisan test, i got an error like this :
anything worng in my codes ? i used laravel 8.
You need to initialize the model first and then call the model factory.
The create function is undefined at line 64.
Instead of
$model = create($model);
Use bellow code
$model = app()->make($model)
$model = $model::factory()->create();
More information on app()->make() and factory.
MODEL:
namespace App;
use Illuminate\Http\Request;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Storage;
class product extends Model
{
public function create(Request $request) {
$file = $request->file('photo');
if ( $request->hasFile('photo') && $request->file('photo')->isValid() )
{
$extension = $file->extension();
$name = 'bjdsakbhdebkhdabhkedbhe'.$extension;
$path = $file->storeAs('public/images',$name);
}
else {
return 'error';
}
product::create([
'photo' => $path,
]);
}
protected $fillable = ['name', 'price', 'roast', 'origin', 'photo', 'stock'];
}
CONTROLLER
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\product;
use Illuminate\Foundation\Auth\AuthenticatesUsers;
use Illuminate\Support\Facades\Auth;
class adminController extends Controller
{
public function __construct() {
$this->middleware('auth');
}
public function create(Request $request) {
ini_set('max_execution_time', 300);
$validatedData = $request->validate([
'photo' => 'required|file|image'
]);
$new = new product;
$new->create($request);
}
}
I am trying to upload a file image. I have reworked the above code several times and an error is thrown. Absolutely NO idea why the file is not uploading. It is not a server error. File size and time allowed have been adjusted.
Why are you calling product::create inside your create method in product class? This causes an infinite recursion.
when trying to get data and returns it via transformers got an error Class 'App\\Api\\V1\\Controllers\\Auth\\ApiController' not found. Using ApiController to extends.I put APIcontroller to App\\Api\\V1\\Controllers\\Front folder.
LoginController Code and extends it to ApiController:
<?php
namespace App\Api\V1\Controllers\Auth;
use Auth;
use Carbon\Carbon;
use Tymon\JWTAuth\JWTAuth;
use App\Http\Controllers\Controller;
use App\Api\V1\Requests\LoginRequest;
use Tymon\JWTAuth\Exceptions\JWTException;
use Symfony\Component\HttpKernel\Exception\HttpException;
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
use App\User;
use App\UserDeviceData;
use Illuminate\Http\Request;
use App\Transformers\UserTransformer;
class LoginController extends ApiController // extends to API controller
{
public function login(LoginRequest $request, JWTAuth $JWTAuth)
{
$credentials = $request->only(['email', 'password']);
try {
$token = Auth::guard()->attempt($credentials);
if(!$token) {
return response()->json([
'message' => "Email and password do not match",
'status_code' => 403,
]);
}
$user = Auth::user();
$user->last_login = Carbon::now();
$user->save();
$user = Auth::user();
$user->UserDeviceData()->firstOrCreate([
'device_id' => $request->device_id
]);
} catch (JWTException $e) {
return response()->json([
'message' => "Internal server error",
'status_code' => 500,
]);
}
return $this->response->collection($user, new UserTransformer);
}
}
Api controller code : and set namespace App\Api\V1\Controllers\Front;
<?php
namespace App\Api\V1\Controllers\Front;
use App\Support\Response;
use App\Support\Parameters;
abstract class ApiController extends Controller
{
protected $response;
protected $parameters;
public function __construct(Response $response, Parameters $parameters)
{
$this->response = $response;
$this->parameters = $parameters;
}
}
What is the problem in my code?
As ApiController and LoginController are using a different namespace, you need to use your ApiController in LoginController.
use App\Api\V1\Controllers\Front\ApiController;
You also forgot to use Controller in ApiController:
use App\Http\Controllers\Controller;