I am trying to send an array of a record to my client by using an API rest with Laravel.
This is my code
public function index ($id) {
$gards = DB::table('gards')
->whereRaw('date_from < Now() AND date_to > Now() AND (gard_day = 1 OR gard_night = 1)')
->get();
foreach($gards as $gard) {
$id_pharma = $gard->pharmacy_id;
$pharmacy = DB::table('pharmacies')->whereRaw("id = {$id_pharma} AND city_id = {$id}")->get();
return response()->json($pharmacy, 200);
}
}
But it sends only the first record.
Any help will be appreciated.
With your approach, you are falling into the n+1 queries dillema (read more on Google), but basically, you are doing a query for each of the lines in the 'gards' table. This is super inefficient. There may be a better way to acheive this with relations, but the following solution only executes 2 queries and you get your result.
public function index ($id) {
$ids = DB::table('gards')
->whereRaw('date_from < Now() AND date_to > Now() AND (gard_day = 1 OR gard_night = 1)')
->pluck('pharmacy_id');
//The pluck function gets all the pharmacy_id and it assigns them to the $ids variable.
$pharmacies = DB::table('pharmacies')
->whereIn('id', $ids)
->where('city_id', $id)
->get();
return response()->json($pharmacies);
}
Related
I have a query of MySQL but I need to convert it into an eloquent model laravel 8. The query is given below,
$query = "SELECT group_id FROM `chat_histories` join chat_group on chat_group.id = chat_histories.group_id where chat_group.is_group = 1 and chat_histories.created_at BETWEEN '$startDate' and '$endDate' and chat_histories.deleted_at is null group by group_id";
$query = "select count(group_id) as total_chat_thread from ($query) total_chat";
DB::select($query);
So far i have done this,
ChatHistory::leftJoin('chat_group', 'chat_group.id', '=', 'chat_histories.group_id')
->selectRaw('count(*) as totals')
->where('chat_group.is_group', 1)
->whereBetween('chat_histories.created_at', [$startDate, $endDate])
->groupBy('chat_histories.group_id')
->count('totals');
But this returns a list, but I need that count of the list. That means it's showing 22 rows, I need that 22 as return.
My Model ChatHistory relation with ChatGroup
public function chatGroup() {
return $this->belongsTo(ChatGroup::class, 'group_id', 'id');
}
My Model ChatGroup relation with ChatHistory
public function chatHistory() {
return $this->hasMany(ChatHistory::class,'group_id','id');
}
Please help to convert it into an eloquent model query
Thanks in advance.
If you have the model Group with a relation history hasMany. it should be like this.
$groupCount = ChatGroup::whereHas('chatHistory', function ($historyQB) use($startDate,$endDate) {
$historyQB->whereBetween('created_at', [$startDate, $endDate])
->whereNull('deleted_at');
})->count();
You dont need the whereNull, if the model ChatHistory has softDelete enabled.
Maybe you should consider using Models, it would be much easier/cleaner
Something like that should work
DB::table('chat_histories')->select('group_id')->join('chat_group', 'chat_group.id', 'chat_histories.group_id')->where('chat_groups.is_group', 1)->whereBetween('chat_histories.created_at', $startDate, $endDate)->whereNull('chat_histories.deleted_at')->groupBy('group_id')->count();
Can somebody help me convert this Sql Query
SELECT *
FROM customer c
LEFT JOIN customer_order co
ON c.customer_number = co.customer_number
AND co.order_status IN ('preparing', 'prepared')
WHERE c.customer_status='unpaid'
AND c.order_status = 'unserve'
AND co.cus_ord_no IS null
into Codeigniter query just like the image below for example
When query statements do not have clauses that need to change conditionally then using $this->db-query() is the way to go.
$sql = "SELECT * FROM customer c LEFT JOIN customer_order co
ON c.customer_number=co.customer_number AND co.order_status IN ('preparing', 'prepared')
WHERE c.customer_status='unpaid' AND c.order_status='unserve' AND co.cus_ord_no IS null";
$query = $this->db->query($sql)->result();
echo json_encode($query);
It might be wise to include a check on the return from query() though because if it fails (returns false) then the call to result() will throw an exception. One way that can be handled is like this.
$query = $this->db->query($sql);
if($query !== FALSE)
{
echo json_encode($query->result());
return;
}
echo json_encode([]); // respond with an empty array
Query Builder (QB) is a nice tool, but it is often overkill. It adds a lot of overhead to create a string that literally is passed to $db->query(). If you know the string and it doesn't need to be restructured for some reason you don't need QB.
QB is most useful when you want to make changes to your query statement conditionally. Sorting might be one possible case.
if($order === 'desc'){
$this->db->order_by('somefield','DESC');
} else {
$this->db->order_by('somefield','ASC');
}
$results = $this->db
->where('other_field', "Foo")
->get('some_table')
->result();
So if the value of $order is 'desc' the query statement would be
SELECT * FROM some_table WHERE other_field = 'Foo' ORDER BY somefield 'DESC'
But if you insist on using Query Builder I believe this your answer
$query = $this->db
->join('customer_order co', "c.customer_number = co.customer_number AND co.order_status IN ('preparing', 'prepared')", 'left')
->where('c.customer_status','unpaid')
->where('c.order_status','unserve')
->where('co.cus_ord_no IS NULL')
->get('customer c');
//another variation on how to check that the query worked
$result = $query ? $query->result() : [];
echo json_encode($result);
You can do
public function view_customers()
{
$sql = "SELECT * FROM customer c LEFT JOIN customer_order co ON c.customer_number = co.customer_number AND co.order_status IN ('preparing', 'prepared') WHERE c.customer_status='unpaid' AND c.order_status = 'unserve' AND co.cus_ord_no IS null";
return $this->db->query($sql)->result();
}
You can use row() for one output to object, or row_array() if one output but array. result() is multiple objects and result_array() is multiple arrays.
My way do usually is like this:
Controller:
public function view()
{
$this->load->model('My_Model');
$data = new stdclass;
$data->user_lists = $this->my_model->view_users(array('nationality'=>'AMERICAN'));
}
Model:
public function view_users($param = null) //no value passed
{
$condition = '1';
if (!empty($param)) { //Having this will trap if you input an array or not
foreach ($param as $key=>$val) {
$condition .= " AND {$key}='{$val}'"; //Use double quote so the data $key and $val will be read.
}
}
$sql = "SELECT * FROM users WHERE {$condition}"; //Use double quote so the data $condition will be read.
// Final out is this "SELECT * FROM users WHERE 1 AND nationality='AMERICAN'";
return $this->db->query($sql)->result();
}
I have a sql query that is working ok
SELECT
*
FROM
jml_gkb_eventos
WHERE
id IN (SELECT
evento_id
FROM
jml_gkb_etiqueta_evento
WHERE
etiqueta_id IN (SELECT
id
FROM
jml_gkb_etiquetas
WHERE
etiqueta REGEXP ? ) group by evento_id having count(evento_id) = ?);
But i can't figure out how convert this sql query to Eloquent model query. I know that i'm near solution (related with this problem here) and tried some variations of the following code:
$pesquisa = preg_split('/\s+/', $temp, -1, PREG_SPLIT_NO_EMPTY);
$cadeiapesquisa = implode('|', $pesquisa);
$contagem = count($pesquisa);
if (Session::get('modo') == 0){
if ( strlen($cadeiapesquisa) > 0 ){
$this['records'] = Evento::with('etiquetas')->whereHas('etiquetas', function($query) use ($cadeiapesquisa, $contagem){
$query->where('etiqueta', 'regexp', "$cadeiapesquisa")->groupBy('evento_id')->having('COUNT(evento_id) = '.$contagem);
})->orderBy('id', 'DESC')->paginate(25);
} else {
$this['records'] =Evento::paginate(25);
}
}
I get it working without the ->having() part in inner query, obviosly without the expected return, but without errors.
What i'm doing wrong ?
TIA
JL
[EDIT] - With the code above i get the following error:
I found the problem. It is with the 'count()' part not being processed by eloquent. Placing the count on DB::raw is working as expected at least with the tests i've done. The whole snipet of code with some adjustements is:
$pesquisa = preg_split('/\s+/', $temp, -1, PREG_SPLIT_NO_EMPTY);
$cadeiapesquisa = implode('|', $pesquisa);
$contagem = count($pesquisa);
if (Session::get('modo') == 0){
if ( strlen($cadeiapesquisa) > 0 ){
$this['records'] = Evento::with('etiquetas')->whereHas('etiquetas', function($query) use ($cadeiapesquisa, $contagem){
$query->where('etiqueta', 'regexp', "$cadeiapesquisa")->groupBy('evento_id')->having(DB::raw("COUNT('etiqueta_id')"), '>=', $contagem );
})->paginate(25);
} else {
$this['records'] = Evento::paginate(25);
}
}
JL
The following function (in my User Model) gives me the correct result for my chat system. Almost... I need to revert the order of the results.
public function getChatConv($cp, $page=1){
$limit = $page * 20;
$user = Authek::curUser();
$res = Chatmessage::where('receipient',$cp)->where('sender',$user->id)
->orWhere('receipient',$user->id)->where('sender',$cp)
->orderBy('created_at','desc')->take($limit)->get();
return $res;
}
It returns an object and I need an object as result. I tried already to convert the result to an array, revert the order and then convert the array back to object. This didn't work.
What I need is a nested query like the following raw SQL query:
SELECT *
FROM (
SELECT *
FROM chatmessages
WHERE (
receipient = '422'
AND sender = '22'
)
OR (
receipient = '22'
AND sender = '422'
)
ORDER BY created_at DESC
LIMIT 0 , 20
)faketable
ORDER BY created_at ASC
There are a few articles with nested queries, but I don't find a similar case and it would be good if someone could do this in Eloquent without the use of Raw queries... It must be possible.
Try this..
use take() and skip(),offset()
get 4 items from offset 3/4th:
Chatmessage::take(4)->offset(3)->get();
Or this (get 10 items from 8rd row):
Chatmessage::take(10)->skip(2)->get();
public function getChatConv($cp, $page=1){
$limit = $page * 20;
$user = Authek::curUser();
$res = Chatmessage::where('receipient',$cp)->where('sender',$user->id)
->orWhere('receipient',$user->id)->where('sender',$cp)
->orderBy('created_at','desc')->take(3)->skip(2)->get();
return $res;
}
Earlier this day a asked a question about an update query. But now i want to select some things ( and it is working ) but I also want to order them and put a limit on it.
This is the code to select all the food :
public function getFood($id)
{
$id = (int)$id;
$rowset = $this->tableGateway->select(array('kindOfFood_id' => $id));
$row = $rowset->current();
if (!$row) {
throw new \Exception("Could not find row $id");
}
return $row;
}
But how can i do this :
Select * from KindOfFood ==> order by kindOfFood_votes DESC ?
I saw on the documentation you can do something like this, but it doesn't work with me?
$rowset = $artistTable->select(function (Select $select) {
$select->where->like('name', 'Brit%');
$select->order('name ASC')->limit(2);
});
Are you looking to return only single row or multiple rows.
Try this for multiple rows -
use Zend\Db\Sql\Select; //at the top of the page among other use statements.
public function getFood($id)
{
$id = (int) $id;
$select = new Select(TABLE_NAME); //CHANGE TABLE_NAME as per needs
$select->where('kindOfFood_id = ' . $id);
$select->order('kindOfFood_votes DESC');
$resultSet = $this->tableGateway->selectWith($select); //Will get array of rows.
//$row = $rowset->current(); THIS IS FOR RETURNING ONLY SINGLE ROW NOT ALL ROWS
if (!$resultSet) {
throw new \Exception("Could not find rows with food id - $id");
}
return $resultSet;
}
Can access the returned resultSet via loop. Eg: foreach
foreach($resultSet as $row) {
echo $row->kindOfFood_id; //or something
}
Note:
If you need only
Select * from KindOfFood order by kindOfFood_votes DESC
then remove the $select->where('kindOfFood_id = ' . $id); line from above.