Laravel - How to paginate here? - mysql

I have this code and I want to paginate $shares.
How can I archive this?
$level = Share::join('follows', 'shares.user_id', '=', 'follows.user_id')
->where('follows.follower_id', Auth::user()->id)
->where('follows.level', 1)
->get(array('shares.*'));
//get 10% of shares
$count = Share::count()/10;
$count = round($count);
$top10 = Share::orderBy('positive', 'DESC')
->take($count)
->get();
$shares = $top10->merge($level);
//get only unique from shares
$unique = array();
$uniqueShares = $shares->filter(function($item) use (&$unique) {
if (!in_array($item->id, $unique)) {
$unique[] = $item->id;
return true;
} else {
return false;
}
});
//order by id
$shares = $uniqueShares->sortBy(function($share)
{
return -($share->id);
});
return View::make('layout/main')
->with('shares', $shares);

lots of reudandant unnecessary codes here.
1st:
$level = Share::join('follows', 'shares.user_id', '=', 'follows.user_id')
->where('follows.follower_id', Auth::user()->id)
->where('follows.level', 1)
->get(array('shares.*'));
Why you are taking ALL the records only to discard it later?
2nd:
$shares = $top10->merge($level); Why you are merging the two arrays?
3rd:
$uniqueShares = $shares->filter(function($item) use (&$unique) {
if (!in_array($item->id, $unique)) {
$unique[] = $item->id;
return true;
} else {
return false;
}
});
You HAD to wrote this snippet because above in 2nd, you merged the two arrays which will yield duplicated entries. So why merging?
4th:
//order by id
$shares = $uniqueShares->sortBy(function($share)
{
return -($share->id);
});
And here comes the actual data which you actually want.
So let's recape
You need
10% of total shares
order by some positive column
order by amount of shares perhaps as i am guessing.
To use the inbuilt paginate(), you'l need paginate() that's a must.
Rest is simple.
count the total result. round(Share::count()/10)
put it in paginate() as the 1st arguement.
Add the order by clause whichever is necessary.
looking at the code, it doesn't look like you will/should have duplicated data which may haved added the distinct and group by clause.
use remember in Share::count()/10; to Cache it. You don't need to run the query over and over again.
and you're done.

The way you are merging your queries you may need to manually create it the pagination in your blade, then send a variable to "take" the next set you want.
Read the Laravel Docs for more info on implementing it into your views and manually creating it.
http://laravel.com/docs/pagination

Try this, should be good to go
Share::join('follows', 'shares.user_id', '=', 'follows.user_id')
->where('follows.follower_id', Auth::user()->id)
->where('follows.level', 1)
->paginate(20);
Maybe you would like to specify columns to select in select() method.

Related

Natural sorting Ajax Datatables in Codeigniter

Struggling to figure out how to set natural sorting in AJAX Datatables using Codeigniter Active record.
The field that should be sorted has, in most cases, just digits...in other cases a string, so the MySQL table field is set as VARCHAR.
I need to srt naturally the field to be displayed in Datatables.
The Active record Codeigniter query is the following.
function list_all($limit,$start,$col,$dir)
{
$this->rmi_db->select ("
$this->table_dev.id,
$this->table_dev.fl,
$this->table_dev.mm,
$this->table_dev.batch,
$this->table_dev.n,
$this->table_dev.ditta,
$this->table_dev.tipo,
$this->table_dev.costruzione,
$this->table_dev.motori,
$this->table_dev.nc,
$this->table_dev.serie,
$this->table_dev.ca,
$this->table_dev.consegna,
$this->table_dev.matr_usaf AS usaf,
$this->table_dev.matr_usn AS usn,
$this->table_dev.matr_caf AS caf,
$this->table_dev.matr_raf AS raf,
$this->table_dev.codici,
$this->table_dev.note,
$this->table_dev.reg_civili,
$this->table_dev.matricola_civ,
$this->table_dev.prima_reg,
$this->table_dev.n_contratto,
$this->table_dev.data_contratto,
$this->table_dev.importo_contratto,
$this->table_dev.note_contratto,
$this->table_dev.f29,
$this->table_dev.f30,
");
$this->rmi_db->from("$this->table_dev");
$this->rmi_db->where("$this->table_dev.mm !=", "");
$this->rmi_db->limit($limit, $start);
$this->rmi_db->order_by($col, $dir);
$query = $this->rmi_db->get();
if($query->num_rows()>0)
{
return $query->result();
}
else
{
return null;
}
}
The mm field should be sorted naturally. I have no idea how and if it's possible to fix the issue.
I tried the solution in this discussion solutions, the Bin way, but the select doesn't work properly ( got 500 server error)
Thanks a lot for any help
Using Solution, Try below. It should work but not tested.
function list_all($limit,$start,$col,$dir)
{
$this->rmi_db->select ("
$this->table_dev.id,
$this->table_dev.fl,
$this->table_dev.mm,
$this->table_dev.mm, CAST($this->table_dev.mm as SIGNED) AS casted_column,//changed
$this->table_dev.batch,
$this->table_dev.n,
$this->table_dev.ditta,
$this->table_dev.tipo,
$this->table_dev.costruzione,
$this->table_dev.motori,
$this->table_dev.nc,
$this->table_dev.serie,
$this->table_dev.ca,
$this->table_dev.consegna,
$this->table_dev.matr_usaf AS usaf,
$this->table_dev.matr_usn AS usn,
$this->table_dev.matr_caf AS caf,
$this->table_dev.matr_raf AS raf,
$this->table_dev.codici,
$this->table_dev.note,
$this->table_dev.reg_civili,
$this->table_dev.matricola_civ,
$this->table_dev.prima_reg,
$this->table_dev.n_contratto,
$this->table_dev.data_contratto,
$this->table_dev.importo_contratto,
$this->table_dev.note_contratto,
$this->table_dev.f29,
$this->table_dev.f30,
");
$this->rmi_db->from("$this->table_dev");
$this->rmi_db->where("$this->table_dev.mm !=", "");
$this->rmi_db->limit($limit, $start);
$this->rmi_db->order_by($col, $dir);
$this->rmi_db->order_by('casted_column', 'ASC'); // changed
$this->rmi_db->order_by($this->table_dev.mm, 'ASC'); // changed
$query = $this->rmi_db->get(); //changed
if($query->num_rows()>0)
{
return $query->result();
}
else
{
return null;
}
}
comment if you face any issue

How to get last inserted id with insert method in laravel

In my laravel project I am inserting multiple records at time with modelname::insert method. Now I want to get last inserted id of it.I read somewhere when you insert multiple records with single insert method and try to get the last_record_id it will gives you the first id of the last inserted query bunch. But my first question is how to get last record id with following code .If I am able to get first id of the bunch .I ll make other ids for other record by my own using incremental variable.
Code to insert multiple record
if(!empty($req->contract_name) && count($req->contract_name)>0)
{
for($i=0; $i<count($req->contract_name); $i++)
{
$contract_arr[$i]['client_id'] = $this->id;
$contract_arr[$i]['contract_name'] = $req->contract_name[$i];
$contract_arr[$i]['contract_code'] = $req->contract_code[$i];
$contract_arr[$i]['contract_type'] = $req->contract_type[$i];
$contract_arr[$i]['contract_ext_period'] = $req->contract_ext_period[$i];
$contract_arr[$i]['contract_email'] = $req->contract_email[$i];
$contract_arr[$i]['created_at'] = \Carbon\Carbon::now();
$contract_arr[$i]['updated_at'] = \Carbon\Carbon::now();
$contract_arr[$i]['created_by'] = Auth::user()->id;
$contract_arr[$i]['updated_by'] = Auth::user()->id;
if($req->startdate[$i] != ''){
$contract_arr[$i]['startdate'] = date('Y-m-d',strtotime($req->startdate[$i]));
}
if($req->enddate[$i] != ''){
$contract_arr[$i]['enddate'] = date('Y-m-d',strtotime($req->enddate[$i]));
}
}
if(!empty($contract_arr)){
Contract::insert($contract_arr);
}
}
You should be able to call it like this
$lastId = Contract::insert($contract_arr)->lastInsertId();
If i see right, you're using a Model. Direct inserting only shows an success boolean. Try this instead:
Contract::create($contract_arr)->getKey()

Eloquent simplify / combine query

I'm trying to simplify the following query. I have a meter and a relation (+ or -) and I would like to sum date-ranges based on the meter criteria. The positive meters should be summed up and the negative ones subtracted from the sum. As showed below, I split the meter array into two arrays ($meter_plus, $meter_minus) with ids only, both for sum values, but $meter_minus should be subtracted.
// Edit: Fetching meters
$begin = new \DateTime($from);
$end = new \DateTime($to);
$end = $end->modify('+1 day');
// find points and meters by group
$grouping = App\Grouping::with('points.meters')->find($group_id);
$meter_plus = [];
$meter_minus = [];
// each group has one-to-many points, each point has one-to-many meters
foreach($grouping->points as $point) {
foreach($point->meters as $meter) {
if($meter->Relation == '+') {
array_push($meter_plus, $meter);
} else {
array_push($meter_minus, $meter);
}
}
}
// Edit2: Point - Meter relation
public function meters()
{
return $this->belongsToMany('App\EnergyMeter', 'meteringpoint_energymeter_relation', 'point_id', 'meter_id')
->whereHas('users', function ($q) {
$q->where('UserID', Auth::id());
})
->where('Deleted', 0)
->select('*', 'meteringpoint_energymeter_relation.Relation')
->orderBy('EMNumber');
}
--
$plus = Data::selectRaw('sum(values) as data')
->where('PointOfTime', '>', $begin->format('U'))
->where('PointOfTime', '<=', $end->format('U'))
->whereIn('meter_id', collect($meter_plus)->lists('id'))
->first();
$minus = Data::selectRaw('sum(values) as data')
->where('PointOfTime', '>', $begin->format('U'))
->where('PointOfTime', '<=', $end->format('U'))
->whereIn('meter_id', collect($meter_minus)->lists('id'))
->first();
$data = $plus->data - $minus->data
This works fine but I would like to
improve the query
calculate the final sum in query
Use whereBetween for your PointOfTime range and sum instead of selectRaw. Also, if $meter_plus is already an array of just the id's, you don't need to do whatever it is you're doing with collect. You might also want to indicate a table to query.
$plus = Data::table('some_table')
->sum('values')
->whereBetween('PointOfTime',array($begin->format('U'), $end->format('U')))
->whereIn('meter_id', $meter_plus)
->sum('values')
->get();

Code Igniter - not showing the entry I need

I have the following code to get one line for each MAC with the LATEST state. The problem I have is that I get one line but not with the latest state but rather with the earliest.
function get_active_devices($min_duration, $max_duration)
{
//get all active devices DESC order
$this->db->distinct();
$this->db->group_by('mac');
$this->db->order_by("id", "desc");
$this->db->select('data.mac, state, time, iot_bo.notified, iot_bo.op_state, iot_bo.Name');
$this->db->where('time >', time()-$max_duration);
$this->db->where('time <', time()-$min_duration);
$this->db->join('iot_bo', 'iot_bo.mac = data.mac');
$this->db->where('iot_bo.op_state', '1');
$query = $this->db->get();
return $query;
}
Have you tried the query without the distinct and groupBy first? May be the result you want isn't in the total result set to begin with. Because there doesn't seem to be anything wrong with your use of db methods as it is.

Magento: Subtraction and Division on addAttributeToFilter

I'm a newbie with Magento getResourceModel, and I'm trying to add a simple filter to my query, but i can't figure that using getResourceModel.
Original Query:
$collection = Mage::getResourceModel('catalog/product_collection');
Mage::getModel('catalog/layer')->prepareProductCollection($collection);
$collection->addAttributeToFilter('promotion', 1)->setOrder('price', 'desc');
I just want add the where clause:
(`price` - `final_price`) >= (`price` * 0.4)
Someone can help me to do this?
This is all, thanks!
So finally I found the correct way to do this, sorry to delay to post the answer here and thanks #feeela.
Looking the file /lib/Zend/Db/Select.php I found that exists the where function:
public function where($cond, $value = null, $type = null)
{
$this->_parts[self::WHERE][] = $this->_where($cond, $value, $type, true);
return $this;
}
So, what we need is just add a call to this function giving the condition that we want. In my case, I just add a condition to filter products that have 40% of discount.
$collection = Mage::getResourceModel('catalog/product_collection');
Mage::getModel('catalog/layer')->prepareProductCollection($collection);
$collection->addAttributeToFilter('promotion', 1)
->addStoreFilter();
$collection->getSelect()->where( '(`price` - `final_price`) >= (`price` * 0.4)' );
So, I hope that this can be helpful for some dudes!
Grazie tutti!