How to create a validation when importing CSV in Laravel using Maatwebsite? - laravel

How to create a validation when importing CSV. I'm using the "maatwebsite/excel": "^3.1" if the imported csv column header name is not exact with the database column it should display some validation. This is my reference LaravelDaily
/
Laravel-8-Import-CSV
Importing CSV
public function parseImport(CsvImportRequest $request)
{
if ($request->has('header')) {
$headings = (new HeadingRowImport)->toArray($request->file('csv_file'));
$data = Excel::toArray(new AwardeesImport, $request->file('csv_file'))[0];
} else {
$data = array_map('str_getcsv', file($request->file('csv_file')->getRealPath()));
}
if (count($data) > 0) {
$csv_data = array_slice($data, 0, 6);
$csv_data_file = CsvData::create([
'csv_filename' => $request->file('csv_file')->getClientOriginalName(),
'csv_header' => $request->has('header'),
'csv_data' => json_encode($data)
]);
} else {
return redirect()->back();
}
return view('admin.import-csv.import-fields', [
'headings' => $headings ?? null,
'csv_data' => $csv_data,
'csv_data_file' => $csv_data_file
])->with('success', 'The CSV file imported successfully');;
}
When parsing CSV
public function processImport(Request $request)
{
$data = CsvData::find($request->csv_data_file_id);
$csv_data = json_decode($data->csv_data, true);
foreach ($csv_data as $row) {
$awardees = new SIS();
foreach (config('app.db_fields') as $index => $field) {
if ($data->csv_header) {
$awardees->$field = $row[$request->fields[$field]];
} else {
$awardees->$field = $row[$request->fields[$index]];
}
}
$awardees->save();
}
return redirect()->action([ImportController::class, 'index'])->with('success', 'Import finished.');
}
CsvImportRequest
public function rules()
{
return [
'csv_file' => 'required|mimes:csv,txt'
];
}
config/app.php
'db_fields' => [
'email_address',
'surname',
'first_name',
'middle_name',
'course',
'year_level',
'contact_number',
'gwa_1st',
'gwa_2nd',
'applying_for',
'remarks',
'comments'
]
if one of those field is missing it should show the validation error

Related

Type error: Too few arguments to function Illuminate\Mail\Mailer::__construct(), 0 passed - Laravel 5.5

I keep getting while trying to use the mailer
FatalThrowableError in Mailer.php line 93:
Type error: Too few arguments to function Illuminate\Mail\Mailer::__construct(), 0 passed in /var/www/app/app/Services/SendOtpMail.php on line 42 and at least 2 expected
in Mailer.php line 93
at Mailer->__construct() in SendOtpMail.php line 42
at SendOtpMail->send('test#company.com', array('from' => 'no-reply#company.com', 'from_name' => 'Some Company', 'subject' => 'Login Verification', 'data' => array('token' => '3486', 'user' => object(User)), 'view' => 'emails.password')) in GetOtpForLoginService.php line 59
at GetOtpForLoginService->sendEmail('3486', object(User))
Send mail function
public function sendEmail($otp, $user)
{
$user = User::where('email', $user->email)->firstOrFail();
(new SendOtpMail())->send($user->email, [
'from' => env('MAIL_DEAFULT_SENDER'),
'from_name' => env('MAIL_DEAFULT_SENDER_ALIAS'),
'subject' => 'Login Verification',
'data' => [
'token' => $otp,
'user' => $user
],
'view' => 'emails.password'
]);
return true;
}
SendOtpMail.php
<?php
namespace App\Services;
use Illuminate\Mail\Mailer;
class SendOtpMail
{
public function send($to, array $options = array())
{
$callback = function($message) use ($options, $to) {
$message->from($options['from'], isset($options['from_name']) ? $options['from_name'] : null);
$message->to($to, isset($options['to_name']) ? $options['to_name'] : null);
if(isset($options['subject'])) $message->subject($options['subject']);
if(isset($options['priority'])) $message->priority($options['priority']);
if(isset($options['priority'])) $message->priority($options['priority']);
if(isset($options['files'])) {
if (is_array($options['files'])) {
foreach ($options['files'] as $file) {
$message->attach($options[$file]);
}
} else {
$message->attach($options['files']);
}
}
if(isset($options['cc'])) $message->subject($options['cc'], isset($options['cc_name']) ? $options['cc_name'] : null);
if(isset($options['bcc'])) $message->subject($options['bcc'], isset($options['bcc_name']) ? $options['bcc_name'] : null);
};
if(isset($options['view'])) {
$data = isset($options['data']) ? $options['data'] : array();
(new Mailer())->send($options['view'], $data, $callback);
} else {
(new Mailer())->raw($options['message'], $callback);
}
}
}
You are seeing that error because you are instantiating an Illuminate\Mail\Mailer object without specifying its required parameters in the constructor:
// from Laravel source code
public function __construct(string $name, Factory $views, TransportInterface $transport, Dispatcher $events = null)
{
$this->name = $name;
$this->views = $views;
$this->events = $events;
$this->transport = $transport;
}
I suggest you don't send emails this ways. Pls check the docs and follow the instructions.

Axios returns error status code 500 when there is data present

I am using Laravel 8, VueJS and Axios for my application then every time I try to fetch all records from my database it returns an error with status code 500. Even though when fetching the data using Postman/Insomnia it returns the data without an error.
I tried to empty the table where it fetches the data the error disappears and it returns empty data with status code 200.
Store Module:
import axios from 'axios'
export default {
namespaced: true,
state: {
courses: [],
teacher: '',
},
getters: {
allCourses(state) {
return state.courses
},
},
actions: {
async fetchAllCourses({ commit }) {
const response = await axios.get('teacher/course-management/list')
console.log(response.data.data)
commit('SET_COURSES', response.data.data)
}
},
mutations: {
SET_COURSES(state, courses) {
state.courses = courses
}
}
Controller:
public function fetchAllCourses() {
try {
$courses = Course::all()->sortBy('id');
$data = $courses->transform(function ($course) {
// ! Get teacher id
$teacherId = $this->user->teacher->id;
// ! Get teacher name by id
$teacherName = $this->getTeacherName($teacherId);
return [
'id' => $course->id,
'teacher_id' => $course->teacher_id,
'teacher' => $teacherName,
'section' => $course->section,
'code' => $course->code,
'status' => $course->status,
'image' => $course->image,
];
});
return $this->success('Request success', $data);
} catch (\Exception $e) {
return $this->error($e->getMessage(), $e->getCode());
}
}
Problem solved.
public function fetchAllCourses() {
try {
$courses = Course::all()->sortBy('id');
$data = $courses->transform(function ($course) {
return [
'id' => $course->id,
'teacher_id' => $course->teacher_id,
'teacher' => $this->getTeacherName($course->teacher_id),
'section' => $course->section,
'code' => $course->code,
'status' => $course->status,
'image' => $course->image,
];
});
return $this->success('Request success', $data);
} catch (\Exception $e) {
return $this->error($e->getMessage(), $e->getCode());
}
}

How to save data when I delete a row or id?

My form is like this I have four row in database
May admin delete 2 rows or id.
How to save it
public function important_store(SettingRequest $request)
{
$importants = collect([]);
if ($request->importants) {
foreach ($request->helps as $help) {
$model = Important::updateOrCreate([
'title' => $help['title']
], [
'link' => $help['link']
]);
$importants->push($model);
}
}
Help::whereNotIn('id', $importants->pluck('id'))->delete();
return redirect()->back();
}

Extend Laravel package

I've searched around and couldn't find a definitive answer for this...
I have a package DevDojo Chatter and would like to extend it using my application. I understand I'd have to override the functions so that a composer update doesn't overwrite my changes.
How do I go about doing this?
UPDATE
public function store(Request $request)
{
$request->request->add(['body_content' => strip_tags($request->body)]);
$validator = Validator::make($request->all(), [
'title' => 'required|min:5|max:255',
'body_content' => 'required|min:10',
'chatter_category_id' => 'required',
]);
Event::fire(new ChatterBeforeNewDiscussion($request, $validator));
if (function_exists('chatter_before_new_discussion')) {
chatter_before_new_discussion($request, $validator);
}
if ($validator->fails()) {
return back()->withErrors($validator)->withInput();
}
$user_id = Auth::user()->id;
if (config('chatter.security.limit_time_between_posts')) {
if ($this->notEnoughTimeBetweenDiscussion()) {
$minute_copy = (config('chatter.security.time_between_posts') == 1) ? ' minute' : ' minutes';
$chatter_alert = [
'chatter_alert_type' => 'danger',
'chatter_alert' => 'In order to prevent spam, please allow at least '.config('chatter.security.time_between_posts').$minute_copy.' in between submitting content.',
];
return redirect('/'.config('chatter.routes.home'))->with($chatter_alert)->withInput();
}
}
// *** Let's gaurantee that we always have a generic slug *** //
$slug = str_slug($request->title, '-');
$discussion_exists = Models::discussion()->where('slug', '=', $slug)->first();
$incrementer = 1;
$new_slug = $slug;
while (isset($discussion_exists->id)) {
$new_slug = $slug.'-'.$incrementer;
$discussion_exists = Models::discussion()->where('slug', '=', $new_slug)->first();
$incrementer += 1;
}
if ($slug != $new_slug) {
$slug = $new_slug;
}
$new_discussion = [
'title' => $request->title,
'chatter_category_id' => $request->chatter_category_id,
'user_id' => $user_id,
'slug' => $slug,
'color' => $request->color,
];
$category = Models::category()->find($request->chatter_category_id);
if (!isset($category->slug)) {
$category = Models::category()->first();
}
$discussion = Models::discussion()->create($new_discussion);
$new_post = [
'chatter_discussion_id' => $discussion->id,
'user_id' => $user_id,
'body' => $request->body,
];
if (config('chatter.editor') == 'simplemde'):
$new_post['markdown'] = 1;
endif;
// add the user to automatically be notified when new posts are submitted
$discussion->users()->attach($user_id);
$post = Models::post()->create($new_post);
if ($post->id) {
Event::fire(new ChatterAfterNewDiscussion($request));
if (function_exists('chatter_after_new_discussion')) {
chatter_after_new_discussion($request);
}
if($discussion->status === 1) {
$chatter_alert = [
'chatter_alert_type' => 'success',
'chatter_alert' => 'Successfully created a new '.config('chatter.titles.discussion').'.',
];
return redirect('/'.config('chatter.routes.home').'/'.config('chatter.routes.discussion').'/'.$category->slug.'/'.$slug)->with($chatter_alert);
} else {
$chatter_alert = [
'chatter_alert_type' => 'info',
'chatter_alert' => 'You post has been submitted for approval.',
];
return redirect()->back()->with($chatter_alert);
}
} else {
$chatter_alert = [
'chatter_alert_type' => 'danger',
'chatter_alert' => 'Whoops :( There seems to be a problem creating your '.config('chatter.titles.discussion').'.',
];
return redirect('/'.config('chatter.routes.home').'/'.config('chatter.routes.discussion').'/'.$category->slug.'/'.$slug)->with($chatter_alert);
}
}
There's a store function within the vendor package that i'd like to modify/override. I want to be able to modify some of the function or perhaps part of it if needed. Please someone point me in the right direction.
If you mean modify class implementation in your application you can change the way class is resolved:
app()->bind(PackageClass:class, YourCustomClass::class);
and now you can create this custom class like so:
class YourCustomClass extends PackageClass
{
public function packageClassYouWantToChange()
{
// here you can modify behavior
}
}
I would advise you to read more about binding.
Of course a lot depends on how class is created, if it is created using new operator you might need to change multiple classes but if it's injected it should be enough to change this single class.

Undefined index: description - Uploading Excel File

Is there a way i can stop the reader from reading the excel file when any of the row data is different? When i upload an excel file, i get Undefined index: description which means description cannot be found in the file uploaded.
Is there a way i can just handle this error ?
if ($request->file('imported-file')) {
$path = $request->file('imported-file')->getRealPath();
$data = Excel::load($path, function($reader) {
$reader->calculate(false);
})->get();
if (($request->file('imported-file')->getClientOriginalExtension()) != 'xlsx') {
return redirect('')->with('error','File Format may not be supported');
} else {
if (!empty($data) && $data->count()) {
foreach ($data->toArray() as $row) {
if (!empty($row)) {
$dataArray[] = [
'name' => $row['name'],
'description' => $row['description'],
];
}
}
if (!empty($dataArray)) {
Item::insert($dataArray);
return redirect('')->with('status','successfully added');
}
}
}
}
Instead of:
'description' => $row['description'],
you could use
'description' => array_get($row, 'description'),
I was also facing the same issue, here is my solution, Hope it will help someone.
Note : This is for Laravel 6.0, Importer class must implements ToModel, WithHeadingRow these two interfaces,
return new Holiday([
'name' => Arr::get($row,'name'),
'start_date' => Arr::get($row,'start_date'),
'end_date' => Arr::get($row,'end_date'),
]);

Resources