Catch an error while importing huge CSV in queue using laravel excel - laravel-5

I am using ShouldQueue method to have the large CSV into Queue but the errors of validations I am not able to catch them!
public function registerEvents(): array
{
return [
ImportFailed::class => function(ImportFailed $event) {
dd($event); // This I will write into the FILE or send EMAIL but the job runs successfully but validation errors keep empty.
$this->importedBy->notify(new ImportHasFailedNotification);
},
];
}
My code looks like below
public function registerEvents(): array
{
return [
ImportFailed::class => function(ImportFailed $event) {
$filename = public_path('tmp').'/validation_error.txt';
$myfile = fopen($filename, "w");
fwrite($myfile, "domo");
fclose($myfile);
},
];
}
I am in hope that if there is any error validation_error.txt file will have "Demo" inside it.
Also, I have crossed verify by removing ShouldQueue it gives me proper errors for email already exists a kind of.
Please help if you have any ideas! Thanks!

Related

Laravel request remove fields before validation

I am trying to remove some fields before they are validated.
Trying to attempt this inside prepareForValidation()
use Illuminate\Foundation\Http\FormRequest;
class VideoRequest extends ApiRequest
{
// ..code..
protected function prepareForValidation()
{
$this->merge([
'public' => $this->toBoolean($this->public),
'notify' => $this->toBoolean($this->notify),
]);
$video_id = $this->route('video_id');
if($this->isMethod('put') && Video::salesStarted($video_id)){
Log::info('removing sales');
// attempt 1
$this->except(['sales_start', 'tickets', 'price']);
// attempt 2
$this->request->remove('sales_start');
// attempt 3
$this->offsetUnset('sales_start');
}
if($this->isMethod('put') && Video::streamStarted($video_id)){
Log::info('removing streams');
// attempt 1
$this->except(['stream_start', 'stream_count', 'archive']);
// attempt 2
$this->request->remove('sales_start');
// attempt 3
$this->offsetUnset('sales_start');
}
$thumb = $this->uploadThumbnail($video_id);
if($thumb !== null){
$this->merge($thumb);
}
}
// ..code..
}
I made sure the code was entering inside the if statement, however the fields are not being removed.
Running $this->request->remove() and $this->except() have no effect.
If I add safe() it throws Call to a member function safe() on null.
I also tried to use unset() but nothing seems to work.
The rules for the dates are like so:
'sales_start' => 'sometimes|required|date|after:now|before:stream_start',
'stream_start' => 'sometimes|required|date|after:now',
but the $request->validated() returns the errors although it shouldn't be validating the deleted fields.
"sales_start": [
"The sales start must be a date after now."
],
"stream_start": [
"The stream start must be a date after now."
]
Why are the fields not being deleted?
Edit
As requested I added some code.
This is what ApiRequest looks like:
use Illuminate\Http\Exceptions\HttpResponseException;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Contracts\Validation\Validator;
abstract class ApiRequest extends FormRequest
{
protected function failedValidation(Validator $validator): void
{
$response['data'] = [];
$response['api_status'] = 'ng';
$response['status_message'] = 'failed validation';
$response['errors'] = $validator->errors()->toArray();
throw new HttpResponseException(
response()->json( $response, 422 )
);
}
protected function toBoolean($booleable)
{
return filter_var($booleable, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
}
}
And the request is called from the controller like so:
public function update(VideoRequest $request, $video_id)
{
... some code ...
$validated = $request->validated();
... some code ...
}
so $this refers to the VideoRequest that extends FormRequest.
Can't find anything about deleting. But acording to Laravel docs you pick what keys you need from a request as follows:
$request->only(['username', 'password']);
// plug everything you need into the array.
$request->except(['username', 'password']);
//plug everything you don't need into the array
The latter is probably most useful to you.
Example:
Say I have the following keys: ['username', 'password', 'randomVal'];
$request->only(['username', 'password']);
// Output:
['username', 'password']
$request->except(['username', 'password']);
// Output:
['randomVal']
To remove (unset) a key from a Request before it goes to the Controller you can use offsetUnset()
inside your request:
protected function prepareForValidation()
{
$this->offsetUnset('sales_start');//same goes for the other key to remove...
}
This is a bit of an ugly answer.
Instead of modifying the request before the validation, I tried adding exclude when getting rules().
So something along these lines:
public function rules() {
$ex = $this->isMethod('put') && Video::salesStarted($video_id) ? 'exclude|' : '';
return [
'sales_start' => $ex.'sometimes|required|other_stuff',
];
}
Note that the validation 'exclude' only works if added first.
So this won't work:
'sometimes|required|other_stuff|exclude' //exclude is called last
I am still unable to find out why remove(), exclude(), offsetUnset() were not working, so this is not the right answer, but I hope it helps if someone is having the same issue.
Edit
Setting this as correct answer as I was unable to find an alternative solution/fix.

Importing generated csv from Laravel into Google Sheets

I'm trying to import an automatically generated csv into Google Sheets using this as cell value:
=importData("https://example.com/reports/some-report")
When I try importData on a static file on the server everything works as expected (like =importData("https://example.com/storage/some-static-report.csv") )
..but when I generate the file on the fly () I get a #N/A in the cell; "Resource at url not found." error.
This is the Laravel code to generate the csv:
public function downloadReportsAsCSV(Request $request) {
$list = [];
$list[] = ['timestamp', 'id', 'value'];
// ... fill the list with data here
$callback = function() use ($list) {
$out = fopen('php://output', 'w+');
// Write CSV lines
foreach ($list as $line) {
fputcsv($out, $line);
}
fclose($out);
};
$name = 'somereport.csv';
$headers = [
'Content-Type' => 'text/csv',
'Content-Disposition' => 'attachment; filename='. $name,
];
return response()->stream($callback, 200, $headers);
}
The route to this method is public so authentication is not a problem in this case.
When I call https://example.com/reports/some-report in a browser it downloads the file (as somereport.csv), but somehow Google Sheeds can't handle it the way I expect it to.
Any ideas on how to make this work?
It seems to be working after all, it's just that Google Sheets apparently needed quit some time before updating the field (at least a couple of minutes).
If anyone has any idea how to trigger Google Sheets to update the data immediately I'd sure like to know.

How to Convert received data from Database to string in laravel?

So before everything this is not duplicate.
I've got a callback method which will get 2 parameters from payment getway. the function they gave us need Amount to make sure everything is correct and base on Amount they gonna gave us payment status, but they won't post it, i should get it from my Database which i've did base on this code :
public function order(Request $request){
$MerchantID = 'xxxxxxxxxxx';
$Authority =$request->get('Authority') ;
$Amount = Invoice::select('invoice_balance')->where('authority',$Authority)->get();
if ($request->get('Status') == 'OK') {
$client = new nusoap_client('https://www.localhost.com/pg/services/WebGate/wsdl', 'wsdl');
$client->soap_defencoding = 'UTF-8';
$result = $client->call('PaymentVerification', [
[
'MerchantID' => $MerchantID,
'Authority' => $Authority,
'Amount' => $Amount,
],
]);
if ($result['Status'] == 100) {
return 'Done.';
} else {
return 'Error with 1';
}
}
else
{
return 'Error with 2';
}
// return $Amount;
}
when i use this code i get The Response content must be a string or object implementing __toString(), "boolean" given. which i'm pretty sure it's just about Amount part, because when use manual value for Amount (exact amount of cart in $Amount = amount), it's gonna gave me The Response content must be a string or object implementing __toString(), "boolean" given. Error.
I've also tried someways in other questions but didn't worked. if u remove whole if(status... part and only return $Amount to make sure it work it gonna gave [{"invoice_balance":"2000"}] which i don't know if this is my mistake or not. please help me, i'm in learning process.
Invoice Model(if needed):
class Invoice extends Model {
protected $fillable = [
'from_user_id', 'to_user_id', 'invoice_title', 'invoice_description', 'invoice_balance', 'invoice_due_date', 'status'
];
protected $hidden = [
'authority'
];
public function user()
{
return $this->belongsTo(User::class);
}
}
well the solution was changing
$Amount = Invoice::select('invoice_balance')->where('authority',$Authority)->get();
to
$Amount = Invoice::select('invoice_balance')->where('authority',$Authority)->value('authority');
Need more information:
Do this and tell me what the output is:
public function order(Request $request){
dd($request->input());
}

Laravel 5.3 - Attach Multiple Files To Mailables

How does one go about attaching multiple files to laravel 5.3 mailable?
I can attach a single file easily enough using ->attach($form->filePath) on my mailable build method. However, soon as I change the form field to array I get the following error:
basename() expects parameter 1 to be string, array given
I've searched the docs and also various search terms here on stack to no avail. Any help would be greatly appreciated.
Build Method:
public function build()
{
return $this->subject('Employment Application')
->attach($this->employment['portfolio_samples'])
->view('emails.employment_mailview');
}
Mail Call From Controller:
Mail::to(config('mail.from.address'))->send(new Employment($employment));
You should store your generated email as a variable, then you can just add multiple attachments like this:
public function build()
{
$email = $this->view('emails.employment_mailview')->subject('Employment Application');
// $attachments is an array with file paths of attachments
foreach ($attachments as $filePath) {
$email->attach($filePath);
}
return $email;
}
In this case your $attachments variable should be an array with paths to files:
$attachments = [
// first attachment
'/path/to/file1',
// second attachment
'/path/to/file2',
...
];
Also you can attach files not only by file paths, but with MIME type and desired filename, see documentation about second case of use for the `attachment` method: https://laravel.com/docs/master/mail#attachments
For example, your $attachments array can be something like this:
$attachments = [
// first attachment
'path/to/file1' => [
'as' => 'file1.pdf',
'mime' => 'application/pdf',
],
// second attachment
'path/to/file12' => [
'as' => 'file2.pdf',
'mime' => 'application/pdf',
],
...
];
After you can attach files from this array:
// $attachments is an array with file paths of attachments
foreach ($attachments as $filePath => $fileParameters) {
$email->attach($filePath, $fileParameters);
}
Best solution work for me
$email = $this->from($from)->subject("Employment Application")
->view('emails.employment_mailview');
foreach ($files as $file) {
$path = '/path/to/'.$file->file;
$attachments->push($path);
}
$attachments = collect([]);
foreach ($attachments as $filePath) {
$email->attach($filePath);
}
return $email;
This worked for me, maybe it will work for more people.
As I am getting the files via $request this was the solution works for me.
obs: sorry I'm using translate. From Portuguese(Brazil) to English.
thanks #AlexanderReznikov, it helped me a lot.
class SendMailextends Mailable
{
protected $inputs;
protected $files;
public function __construct(array $inputs, array $files)
{
$this->inputs = $inputs;
$this->files = $files;
}
public function build()
{
if (isset($this->files)){
$email = $this->from('you#mail')->view('email.email-contact')->subject('Email teste mulptiple files');
for ($indice = 0; $indice < count($this->files['files']); $indice++) {
$files = $this->files[$indice];
$pathName = $files->getPathname();
$attachments = $pathName;
$fileName = $files->getClientOriginalName();
$email->attach($attachments,['as' => "$fileName"]);
}
return $email;
}else{
// file empty, send email
return $this->from('you#mail','name')->subject('Email teste mulptiple files')
->view('email.email-contact');
}
}
}

How to display the soap xml message before it's send using laravel-soap

I managed to use laravel-soap to send and receive requests, but for debugging purposes I want to print/echo the exact xml being send and received.
I tried to use
->trace(true);
but that doesn't seem to help.
So how do I print out the actual soap xml message being send and received
Update: This is my code
<?php
namespace App\Http\Controllers;
use Artisaninweb\SoapWrapper\Facades\SoapWrapper;
class IsController extends Controller {
public function demo()
{
// Add a new service to the wrapper
SoapWrapper::add(function ($service) {
$service
->name('Test')
->wsdl('http://link.to.provider/program.asmx?wsdl')
->trace(true);
});
$data = [
'UserName' => 'XXXXXXX',
'Password' => 'XXXXXXX',
];
// Using the added service
SoapWrapper::service('Test', function ($service) use ($data) {
//var_dump($service->getFunctions());
var_dump($service->getLastRequest());
//dd($service->call('Login', [$data]));
//dd($service->getLastResponse());
});
}
}
I already tried replacing
echo htmlentities($service->getLastResponse());
with
dd($service->getLastResponse());
and
var_dump($service->getLastResponse());
The result is the; same the text "NULL"
If you want to echo it out, try this;
echo htmlentities($service->getLastRequest());
And, for the response:
echo htmlentities($service->getLastResponse());

Resources