Refactoring multiple same queries with different value - laravel

Is there a better way to refactor this code? It's basically the same line with different values. I thought of doing a for loop but maybe there's another way.
$date = $request->date;
$underConsideration = Application::whereDate('created_at',$date)->where('status','Under consideration')->count();
$phoneScreened = Application::whereDate('created_at',$date)->where('status','Phone screened')->count();
$interviewed = Application::whereDate('created_at',$date)->where('status','Interviewed')->count();
$offerExtended = Application::whereDate('created_at',$date)->where('status','Offer extended')->count();

You should create a separate method for this.
public function myMethod()
{
$under_consideration = $this->fetchApplicationData($request, 'Under consideration');
$phone_screened = $this->fetchApplicationData($request, 'Phone screened');
$interviewed = $this->fetchApplicationData($request, 'Interviewed');
$offer_extended = $this->fetchApplicationData($request, 'Offer extended');
}
private function fetchApplicationData($request, $status)
{
return Application::
whereDate('created_at', $request->date)
->where('status', $status)
->count();
}
That is a much cleaner code.
However, I advise that you should put the items:
Under consideration, Phone screened, Interviewed, Offer extended
into a separate table on the database and just save the status_id on your main table.
One of the major advantage on this is the speed. For example, your client wants to know all record that has a status of Interviewed for a certain date span. Database searching against integer is a lot faster than string.

You could create a method to handle the select operations. Something like:
public function yourExisitingMethod() {
$date = $request->date;
$underConsideration = getData($date,'Under consideration');
$phoneScreened = getData($date,'Phone screened');
$interviewed = getData($date,'Interviewed');
$offerExtended = getData($date,'Offer extended');
}
public function getData($date, $status) {
$data = Application::whereDate('created_at',$date)->where('status',$status)->count();
return $data;
}
This would at the very least improve the maintainability of your code, and in my opinion improves reusability and readability.

Related

carregar mĂșltiplos modelos em um controller

In my Create function, from my products controller. I make several calls to other models that are used to mount combos on the view blade.
$grade = Grade::all();
$marca = Marca::all();
$ncm = Ncm::all();
$clafiscal = Clafiscal::all();
$Otributaria = Origemtributaria::all();
$unidade = Unidade::all();
...
return view('products.create',
compact(
'page',
'etiqueta',
'compCusto',
'grade',
'marca',
'ncm' ,
'clafiscal',
'Otributaria',
'grupo',
'colecao'...);
Is it possible for me to reduce these calls?
I believe there is no other way to compact multiple values.
But, if your problem is related to the dirty controller (with many function calls and responsibilities), you should try to create a more specific method, with will handle this dependencies load and dependencies compact.
Try something like this:
public function loadDependencies()
{
$dependencias = [];
$dependencias['grade'] = Grade::all();
$dependencias['marca'] = Marca::all();
$dependencias['ncm'] = Ncm::all();
$dependencias['clafiscal'] = Clafiscal::all();
$dependencias['Otributaria'] = Origemtributaria::all();
$dependencias['unidade'] = Unidade::all();
return compact($dependencias);
}
public function create()
{
return view('products.create', $this->loadDependencies());
}

How to call information from one model to another Codeigniter

I'm stuck on this from a while.Can't figured it out.I reed documantion, tried with several videos and tried like 10 different ways, nothing is working yet.So I have one view/model for one thing, in this example Destination and I have separate files for Offers.The controllers for both are in one file.I want tho the information that is in destination to go to Offers as well.Please help I can't figure out what I'm missing:
So here is the most important parts:
destination_model.php
<?php class Destination_model extends CI_Model
{
public function getDestinationDetails($slug) {
$this->db->select('
id,
title,
information
');
$this->db->where('slug', $slug);
$query = $this->db->get('destinations')->row();
if(count($query) > 0)
{
return $query;
}
else
{
// redirect(base_url());
}
}
public function getOffersByDestination($destination_id)
{
$this->db->select('
o.short_title,
o.price,
o.currency,
o.information,
o.long_title_slug,
oi.image,
c.slug as parent_category
');
$this->db->from('offers o');
$this->db->join('offers_images oi', 'oi.offer_id = o.id', 'left');
$this->db->join('categories c', 'c.id = o.category');
$this->db->group_by('o.id');
$this->db->where('o.destination', $destination_id);
$this->db->where('o.active', '1');
return $this->db->get();
} }
And then in the controller for offers I put this:
$this->load->model('frontend/destination_model');
$this->params['destination'] = $this->destination_model->getOffersByDestination($data->id);
All I need is the title and the information about the destination.
Here is the whole controller for the offers:
$data = $this->slugs_model->getOfferDetails(strtok($this->uri->segment(2), "."));
$this->load->model('frontend/offers_model');
$this->load->model('frontend/destination_model');
$this->params['main'] = 'frontend/pages/offer_details';
$this->params['title'] = $data->long_title;
$this->params['breadcumb'] = $this->slugs_model->getSlugName($this->uri->segment(1));
$this->params['data'] = $data;
$this->params['images'] = $this->slugs_model->getOfferImages($data->id);
$this->params['similar'] = $this->slugs_model->getSimilarOffers($data->category, $data->id);
$this->params['destination'] = $this->destination_model->getOffersByDestination($data->id);
$this->params['offers'] = $this->offers_model->getImportantOffers($data->offers, $data->category, $data->id);
You need to generate query results after you get it from model,
e.g: row_array(), this function returns a single result row.
here's the doc: Generating Query Results
try this:
$this->load->model('frontend/destination_model');
$data['destination'] = $this->destination_model->getOffersByDestination($data->id)->row_array();
$this->load->view('view_name', $data);
And in your view echo $destination['attribut_name'];,
or you can print the array, to see if it's work print_r($destination);

Querying counts from large datasets using eloquent

I have the following relationships:
A Job has many Roles.
public function roles()
{
return $this->hasMany(Role::class);
}
A Role has many Shifts and Assignments through shifts.
public function shifts()
{
return $this->hasMany(Shift::class);
}
public function assignments()
{
return $this->hasManyThrough(Assignment::class, Shift::class);
}
A Shift has many Assignments.
public function assignments()
{
return $this->hasMany(Assignment::class);
}
I need to get a count of all assignments with a certain status, let's say "Approved". These counts are causing my application to go extremely slowly. Here is how I have been doing it:
foreach ($job->roles as $role){
foreach ($role->shifts as $shift) {
$pendingCount = $shift->assignments()->whereStatus("Pending")->count();
$bookedCount = $shift->assignments()->whereIn('status', ["Booked"])->count();
}
}
I am certain that there must be a better, faster way. Some of these queries are taking upwards of 30+ seconds. There are hundreds of thousands of Assignments, which I know is affecting performance. How can I speed up these queries?
You're running into the N+1 issue here a few times. You want to lazy load the nested assignment through jobs then you can access the relation and your where() and whereIn() calls are executed on the returned collection instead of on the query builder which is why you have to use where('status', "Pending") instead of whereStatus("Pending") in my example because the collection won't automatically resolve this constraint:
$job = Job::with('roles.assignments')->find($jobId);
foreach ($job->roles as $role) {
$pendingCount = $role->assignments->where('status', "Pending")->count();
$bookedCount = $role->assignments->whereIn('status', ["Booked"])->count();
}
This should be a lot quicker for you.
UPDATE
You could even take that one step further and map the result and store the results in a property on the role:
$job->roles->map(function($role) {
$role->pending_count = $role->assignemnts->where('status', "Pending")->count();
$role->booked_count = $role->assignments->whereIn('status', ["Booked"])->count();
return $role;
});

Laravel 5.1 How to join two collections of objects

All warehouses tables have differemt number of columns. So I can't use union inside a query. But I hate this way to join this collection of objects.
There is a better (clear) way?
Thx :)
public function index()
{
$warehouses1 = Farm_warehouse::all();
$warehouses2 = Butchery_warehouse::all();
$warehouses3 = Grape_warehouse::all();
$warehouses4 = Iron_warehouse::all();
$warehouses5 = Rice_warehouse::all();
$warehouses6 = Silk_warehouse::all();
$warehouses7 = Wood_warehouse::all();
$warehouses2 = $warehouses1->merge($warehouses2);
$warehouses3 = $warehouses2->merge($warehouses3);
$warehouses4 = $warehouses3->merge($warehouses4);
$warehouses5 = $warehouses4->merge($warehouses5);
$warehouses6 = $warehouses5->merge($warehouses6);
$warehouses = $warehouses6->merge($warehouses7);
return view('warehouses.index', compact('warehouses'));
}
This may not be the improvement you are looking for but couldn't you chain it together like this?
public function index()
{
$warehouses = Farm_warehouse::all();
$warehouses->merge(Butchery_warehouse::all());
$warehouses->merge(Grape_warehouse::all());
$warehouses->merge(Iron_warehouse::all());
$warehouses->merge(Rice_warehouse::all());
$warehouses->merge(Silk_warehouse::all());
$warehouses->merge(Wood_warehouse::all());
return view('warehouses.index', compact('warehouses'));
}
I think that's a bit easier to read, but may be you can extract it out to a base Warehouse Model or try digging into the Collection class for something more fruitful. Hope this helps.

Magento - get bundled products where a simple product belongs to

I want to show all bundles on a simple product's page and so need to retrieve the information. I searched and tried a lot. This post sounds promising, but is either not working or maybe not for my problem:
Magento - get a list of bundled product ids from a product id
I found a solution for grouped products but this can't be applied here.
$grouped_product_model = Mage::getModel('bundle/product_selection');
$groupedParentId = $grouped_product_model->getParentIdsByChild($product->getId());
I found the table catalog_product_bundle_selection to be the right place to search, but I wonder if there is a clean way and existing function to search this table by product_id than just to hack this.
I didn't find a solution in Mage_Bundle.
What did I miss?
After getting first aid from vrnet I wrote a new block class, so I can update the layout
class Thomaier_Catalog_Block_Product_View_BundledSelect extends Mage_Catalog_Block_Product_View
{
protected $_simpleProducts = array( '3' ); // just an example
public function getBundles() {
$bundleIds = array();
$bundlesCollectionModel = Mage::getResourceModel('bundle/selection_collection');
$bundlesCollection = $bundlesCollectionModel->getSelect()
->where('`selection`.`product_id` in (' . join(',', (array)$this->_simpleProducts) . ')');
foreach ($bundlesCollection as $bundleItem) {
$bundleIds[] = $bundleItem->getParentProductId();
}
...
}
}
I skipped some parts. As I mentioned in the comment, the SQL query works fine when I try it in phpmyadmin, but $bundleItem is not created and ->load() throws an exception.
Thanks for advice.
Below is a method I wrote for a client having the same request with an extra : the ability to shuffle the result.
Hope it helps.
protected $_simpleProducts = array(); // Array with IDs of simple products you want bundles from.
protected $_shuffle = false;
public function getBundles() {
$bundleIds = array();
/*Rather than using a collection model
and make operations with getSelect,
a more elegant way is to extend
Mage_Bundle_Model_Mysql4_Selection_Collection
with a method that would be something like
setProductIdsFilter($productIds)*/
$bundlesCollectionModel = Mage::getResourceModel('bundle/selection_collection');
$bundlesCollection = $bundleCollectionModel->getSelect()
->where('`selection`.`product_id` in (' . join(',', (array)$this->_simpleProducts) . ')');
foreach ($bundlesCollection as $bundleItem) {
$bundleIds[] = $bundleItem->getParentProductId();
}
if (count($bundleIds)) {
$allowBundles = Mage::getResourceModel('catalog/product_collection')
->addIdFilter($bundleIds)
->addFieldToFilter('status', Mage_Catalog_Model_Product_Status::STATUS_ENABLED);
if ($this->_shuffle) {
$allowBundles->getSelect()->order('rand()');
}
if ($allowBundles->count()) {
return $allowBundles;
}
}
return;
The following is the best way to work with these. This way you do not rely on a custom query but instead you can use the core methods:
$bundlesCollection = Mage::getResourceModel('bundle/selection')
->getParentIdsByChild($simple_product_ids_array_or_int);
foreach ($bundlesCollection as $bundleProdId) {
//do anything you want with the bundleProdId array elements
}

Resources