Laravel - Copy collection data to another table and delete - php

I want to delete entries which are older than 3 days and move them to another (archive) table.
So far I do it like this:
public function handle() {
$route = Route::where('created_at', '<=', Carbon::now()->subDays(3))->get();
$routeCopy = $route;
$route = Route::where('created_at', '<=', Carbon::now()->subDays(3))->delete();
foreach ($routeCopy as $r) {
$routeArchive = new RouteArchive();
$routeArchive->id = $r->id;
$routeArchive->startLocation = $r->startLocation;
$routeArchive->endLocation = $r->endLocation;
$routeArchive->save();
}
}
Is there a way to avoid double querying in this case?
Btw Route and RouteArchive are not same. Route contains many other columns including id, startLocation, endLocation... RouteArchive contains only id, startLocation and endLocation.

Assuming that you have a primary key set up on the route table, you should be able to do something like this
public function handle() {
$route = Route::where('created_at', '<=', Carbon::now()->subDays(3))->get();
// $routes = $route;
// $route = Route::where('created_at', '<=', Carbon::now()->subDays(3))->delete();
foreach ($route as $r) {
$routeArchive = new RouteArchive();
$routeArchive->id = $r->id;
$routeArchive->startLocation = $r->startLocation;
$routeArchive->endLocation = $r->endLocation;
$routeArchive->save();
$r->delete();
}
}

Related

Update multiple ids against single id (Laravel)

I want to update multiple Departments against one unit. I tried this method, but it's not correct.
How can I update multiple departments ids?
Form:
Request:
Controller Function:
$pre_data = UnitDepartment::where('unit_id', $request->id)->get();
if ($pre_data) {
foreach ($pre_data as $value) {
$value->delete();
}
$department = $request->department_id;
foreach ($department as $value) {
$unitDepart = new UnitDepartment();
$unitDepart->unit_id = $request->id;
$unitDepart->department_id = $value;
$unitDepart->save();
}
}
table:
I found that is the table related to departments and units.
So you can build the relationship many-to-many between them,
Create the relationship in your models,
In Unit model:
public function departments()
{
return $this->belongsToMany('App\Unit','unit_department','unit_id','department_id');
}
In Department Model:
public function units()
{
return $this->belongsToMany('App\Department','unit_department','department_id','unit_id');
}
Attach the new relationship, simply use:
Unit::find($request->unit_id)->departments()
->sync($request->department_id);
Unfortunately, you cannot use softDelete on sync().
And I don't think you need to soft delete with unit_departments. As a pivot then it should be irrelevant if it is deleted or not.
And if user update the relationship on the frequent, this table will grow fast.
If you really need to soft-delete, you can write it like this:
$department_ids = $request->department_id;
$unit_id = $request->unit_id
// soft delete the unit_departments not in request:
UnitDepartment::where('unit_id', $unit_id)->whereNotIn('department_id', $department_ids)->delete();
// insert the new department_id+unit_id relationship
$exist_department_ids = UnitDepartment::where('unit_id', $unit_id)->whereIn('department_id', $department_ids)->pluck('department_ids')->all();
$dept_ids = array_diff($exist_department_ids, $department_ids);
$depts = collect($dept_ids)->map(function($dept_id) use ($unit_id) {
return ['department_id' => $dept_id, 'unit_id' => $unit_id];
});
UnitDepartment::insert($depts);
the problem is you're sending unit_id in the request, however using $request->id in the query which is wrong.
Change every occurance of $request->id with $request->unit_id in the controller.
to select pre data correctly
use
$pre_data = UnitDepartment::where('unit_id', $request->id)->first();
i tried this
$unit = UnitDepartment::where('unit_id', $request->unit_id)->get();
foreach ($unit as $item) {
$existDepartment[] = $item->department_id;
}
$newDepartment = $request->department_id;
$result = array_diff($newDepartment, $existDepartment);
if ($result) {
foreach ($result as $item) {
$data = new UnitDepartment();
$data->unit_id = $request->unit_id;
$data->department_id = $item;
$data->save();
}
}

How count a column from a tableB where tableA.y = TableB.y laravel

I would like to count number of courses and questions of each modules.
When I try it with this code below, it displays the counting of all questions
//$data = DB::table('module')->orderBy('idmodule', 'desc')->paginate(5);
$data = DB::table('module')
->leftJoin('cours', 'module.idmodule', '=', 'cours.id_module')
->leftJoin('question', 'cours.id_cours', '=', 'question.id_cours')
->select('module.*', 'cours.*',DB::raw("count(cours.id_module) as cours"),DB::raw("count(question.id_cours) as quest"))
->groupBy('module.idmodule')
->get();
$id = Auth::id();
return view('admin.modules',compact('data'))>with('profile',profile::find($id));
If you declare the relation between Module->Cour and Module->Question, you can simply do
$modules = Modules::withCount(['cours', 'questions'])->get();
Module.php :
public function cours()
{
return $this->hasMany(Cour::class, 'id_module', 'idmodule');
}
public function questions()
{
return $this->hasManyThrough(Question::class, Cour::class, 'id_module', 'id_cours', 'idmodule', 'id_cours');
}

Laravel/LaraCSV Managing Complex Relationships

I'm running into some issues with my Collection/Model relationships with regards to LaraCSV. Here is its documentation: https://github.com/usmanhalalit/laracsv#full-documentation. I have 3 models that interact right now: Doctor, Patient, Script
Doctor belongsToMany Patient
Patient belongsToMany Doctor
Patient hasMany Script
Script belongsTo Patient
I also created a relationship link inside of my Doctor model that can be used to tie Doctor to Script, but does not appear to work in this instance:
public function scripts() {
$this->load(['patients.scripts' => function($query) use (&$relation) {
$relation = $query;
}]);
return $relation;
}
What I am attempting to do is allow admin staff and our users to download CSV files that contain all of their scripts. While this works fine for admin staff as I can reference the models directly, I am not able to make it work for users because they are tied to the doctors, and I cannot seem to tie this into scripts as normal. Here is a perfectly working version for admin staff:
$doctors = Doctor::orderBy('last_name', 'asc')->get();
$patients = Patient::orderBy('last_name', 'asc')->get();
$scripts = Script::orderBy('prescribe_date', 'desc')->get();
$csvExporter->beforeEach(function ($script) use ($doctors, $patients) {
$patient = $patients->where('id', $script->patient_id)->first();
$doctor = $patient->doctors->first();
$script->patient = $patient->full_name;
$script->doctor = $doctor->full_name;
});
Here is how the user-specific version appears:
$doctors = User::
find(Auth::user()->id)
->doctors()
->orderBy('last_name', 'asc')
->get();
$patients = Patient::orderBy('last_name', 'asc')->get();
$scripts = $doctors->scripts()->get();
Trying to chain in my Doctor model scripts() function results in an error: Method Illuminate\Database\Eloquent\Collection::scripts does not exist.
$doctors = User::
find(Auth::user()->id)
->doctors()
->orderBy('last_name', 'asc')
->get();
$patients = array();
$scripts = array();
foreach ($doctors as $doctor_fe) {
foreach ($doctor_fe->patients as $patient_fe) {
$patients[] = $patient_fe;
foreach ($patient_fe->scripts as $script_fe) {
$scripts[] = $script_fe;
}
}
}
I also tried to pull the information using arrays, but unfortunately, it must be a Collection passed in via this error: Argument 1 passed to Laracsv\Export::addCsvRows() must be an instance of Illuminate\Database\Eloquent\Collection, array given
I settled by placing all of the patients belonging to the user's doctors through a foreach loop, then using another one to grab the patient's id. I then took the patient's id array and used the whereIn function to compare the Script's patient_id field to get the correct strips.
$doctors = User::
find(Auth::user()->id)
->doctors()
->orderBy('last_name', 'asc')
->get();
$patients_array = array();
foreach ($doctors as $doctor_fe) {
$patients_fe = $doctor_fe->patients;
foreach ($patients_fe as $patient_fe) {
$patients_array[] = $patient_fe->id;
}
}
$patients = Patient::orderBy('last_name', 'asc')->get();
$scripts = Script::whereIn('patient_id', $patients_array)->get();
$csvExporter->beforeEach(function ($script) use ($doctors, $patients) {
$patient = $patients->where('id', $script->patient_id)->first();
$patient_initials = substr($patient->first_name, 0, 1) . substr($patient->last_name, 0, 1);
$doctor = $patient->doctors->first();
$script->patient = $patient_initials;
$script->doctor = $doctor->full_name;
});
If I interpret you question correctly, you want to get all scripts of all patients of a doctor. Laravel provides the hasManyThrough() Method for this:
class Doctor extends Model
{
/**
* Get all of the scripts for the patient.
*/
public function scripts()
{
return $this->hasManyThrough(App\Script::class, App\Patient::class);
}
}
The first param is the model you want to get (the scripts); the 2nd param is the intermediate model (the patient).
To use it:
$doctor = Doctor::first();
$scripts = $doctor->scripts;

BadMethodCallException in Macroable.php line 81:Method update does not exist

I an developing a page to create, update, delete and view an event in which there is error while updating the event. There is a event table and a event_collection table. In that event_collection table there is event_id which is id of an event and a collection_id which is from other table collection.
When i create an event, all the data gets stored in event table except the collection one. in the collection table data gets stored in one by one manner like if I check 2 items in collection, it will generate 2 ids with same event_id and 2 collection_ids.
There is problem in update, when i try to update the code, it gives me error as
BadMethodCallException in Macroable.php line 81:
Method update does not exist.
Update method is:
public function update(EventRequest $request, $id)
{
$event = Event::findOrFail($id);
$input = $request->all();
$input['days_of_week'] = serialize(Input::get('days_of_week'));
$query = $event->update($input);
$checkbox_selection = Input::get('agree');
$choosen_checkbox = $id;
$collection_event = EventCollection::where('event_id',$choosen_checkbox)->get();
// return $collection_event;
if (!is_null($checkbox_selection)) {
foreach ($checkbox_selection as $collection) {
// $collection_id = $id;
foreach($collection_event as $k){
// return $k;
if($k->event_id == $choosen_checkbox){
$data = $request->all();
$data['event_id']= $choosen_checkbox;
$data['collection_id'] = $collection;
$collection_event->update($data);
}
}
}
}
My store method is:
public function store(Request $request)
{
$checkbox = Input::get('days_of_week');
$checkbox_selection = Input::get('agree');
// return $checkbox_collection;
$input = $request->all();
$input['days_of_week'] = serialize($checkbox);
$query = Event::create($input);
$event_id = $query->id;
$pro_id = $query->provider_org_id;
/*For the checkbox selection, if they are multiple store each separately*/
if (!is_null($checkbox_selection)) {
foreach ($checkbox_selection as $collection) {
$collection_id = $query->id;
if($collection_id){
$data = $request->all();
$data['event_id']= $collection_id;
$data['collection_id'] = $collection;
$create_collection = EventCollection::create($data);
}
}
}
return view('event.pic_upload',compact('event_id','pro_id'));
}
Store method works properly! Can someone please tell any solution? I am badly stucked in this.
I do not think the 'update' method works on collections.
This line will return a collection
$collection_event = EventCollection::where('event_id',$choosen_checkbox)->get();
You do not want a collection, rather a query. As given in the docs:
`App\Flight::where('active', 1)
->where('destination', 'San Diego')
->update(['delayed' => 1]);`
Try removing the '->get()' from the statement.

Getting distinct rows from paginated result set in Laravel

I have created the following for a product catelog/lister:
public function index($type_id = null) {
$filters = $sort = array();
if (isset($type_id)) {
$filters['type'] = $type_id;
} else {
$filters['type'] = Input::get('type');
}
$filters['search'] = Input::get('search');
$filters['brand'] = Input::get('brand');
$sort['sort'] = Input::get('sort');
$sort['sortdir'] = Input::get('dir');
$productsPaginated = $this->fetchProducts($filters, $sort);
return View::make('products.products', array(
'productsList' => $productsPaginated
)
);
}
public function fetchProducts($filters, $sorts, $perpage = 2) {
print_r($filters);
$Product = Product::query();
if (!empty($filters['search']))
$Product->where('name', 'LIKE', '%' . $filters['search'] . '%');
if (isset($filters['type']))
$Product->where('type_id', $filters['type']);
if (isset($filters['brand']))
$Product->where('brand_id', $filters['brand']);
if (isset($sorts['sort']))
$Product->orderBy($sorts['sort'], $sorts['sortdir']);
$Product = $Product->paginate($perpage);
return $Product;
}
Which works well so far.
I am now trying to create some filters so a user can further filter the results.
How can I access and determine distinct rows based on a column in:
$productsPaginated = $this->fetchProducts($filters, $sort);
?
The groupBy method not only exists on the query builder but also on the collection class. (which will be returned when calling paginate)
Take a look at the source on github
So add an argument to your function and use groupBy
public function fetchProducts($filters, $sorts, $perpage = 2, $groupBy = null) {
// code omitted for brevity
$Product = $Product->paginate($perpage);
if($groupBy){
$Product = $Product->groupBy($groupBy);
}
return $Product;
}
Update
Then there's the lists function that works on collections as well as on query builders...
$Product->lists('column-name');
Update 2
I was curious so I did some testing and a found something very weird and I have no idea if its a bug or a feature I don't understand
When calling groupBy the collection returned has actually only one item (index "") and this item contains an array of the "original" items. So to make lists work. I found this workaround
$Product = $Product->groupBy($groupBy);
$Product = new Collection($Product[""]); // \Illuminate\Support\Collection
$Product = $Product->lists('column-name');

Categories