I'm trying to get some data from my database with active records,and I'm having the following problem. I wanna learn how to do it with active records since after this code i have a ton of joins and other stuff. Otherwise I would write a normal query.
$this->db->where("sa.country", $country);
// I NEED TO OPEN BRACKETS HERE SO THAT I CAN GET THE LANGUAGES IF THERE IS DATA IN ONE OF THE ARRAYS
if (isset($lid[0]))$this->db->where("sa.lang", $lid[0]);
if (isset($lid[1]))$this->db->or_where("sa.lang", $lid[1]);
if (isset($lid[2]))$this->db->or_where("sa.lang", $lid[2]);
if (isset($lid[3]))$this->db->or_where("sa.lang", $lid[3]);
if (isset($lid[4]))$this->db->or_where("sa.lang", $lid[4]);
//AND CLOSE THEM HERE
My goal is to get a specific country from db, with the corresponding languages that are in the arrays.
I think you should use WHERE...IN...! See help about 'where in'.
With ActiveRecord:
$this->db->where_in("sa.lang",$lid);
Does this help?
$this->db->where("sa.country", $country);
// loop through *set* languages
foreach($lid as $item)
{
$this->db->where('sa.lang', $item);
}
// will return a query object
return $this->db->get('my_table');
Here is how I solved the problem for anyone interested in the solution.
$this->db->where("(`sa`.`lang` = '$lid[0]' OR `sa`.`lang` = '$lid[1]' OR `sa`.`lang` = '$lid[2]' OR `sa`.`lang` = '$lid[3]' OR `sa`.`lang` = '$lid[4]')");
Related
I have some properties and i want to get the object for each property, currently, I am using the eloquent in the foreach loop like this as shown in the image that will describe the best..
but it is really not a good approach because if I have 100 published property I will making 100 calls to the DB... and that is not correct?
I need a suggestion and a proper solution to this query?
Thanks in advance
Before foreach you can get all the RentalProperty items from db like this:
$allRentalProperties = RentalProperty::all();
and in foreach loop you can get those items without connecting database like this:
$propertyObj = $allRenatalProperties -> where('id', $property['id']) -> first();
Also, you can use array shorthand.
$newArray = [];
it's much simple and readable.
You can do array pluck before loop:
$propertyIds = Arr::pluck($published_properties, 'id');
Then you can make a whereIn query to get only those data which are in $published_properties object
$propertyObj = RentalProperty::whereIn('id', $propertyIds);
Then you can access that object with id if you change array key with record id.
I want to display data from cv table where user_id is $request->id.
Also, filtering is done so i have to put lots of orWhere.
Because of this my code is not working as expected.
Sorry question is a little bit confusing.
$search = $request->input('search.value');
$results = cv::with(['industrySegments','jobLocations','jobPositions','languages'])->where('user_id',$request->id);
$results->orWhere('name','LIKE',"%{$search}%");
$results->orWhere('gender','LIKE',$search);
$results->orWhere('contact','LIKE',$search);
$results->orWhere('contact2','LIKE',$search);
This code doesn't work.
whenever i type something in search button it displays data that is not supposed to be display.
I want to display only the data whose user_id is $request->id.
i think what you wanted to do is advanced where
your query will be like this
$results = cv::with(['industrySegments','jobLocations','jobPositions','languages'])->where('user_id',$request->id)->where(function($q)use($search){
$q->where('name','LIKE',"%{$search}%")->orWhere(..........;
})->get();
therefore you can play around with where / orWhere
Test next code:
$results = cv::with(['industrySegments','jobLocations','jobPositions','languages']);
if(!empty($request->id))
{
$results->where('user_id',$request->id);
}
else
{
$results->orWhere('name','LIKE',"%{$search}%");
$results->orWhere('gender','LIKE',$search);
$results->orWhere('contact','LIKE',$search);
$results->orWhere('contact2','LIKE',$search);
}
We are developing an API with LUMEN.
Today we had a confused problem with getting the collection of our "TimeLog"-model.
We just wanted to get all time logs with additional informationen from the board model and task model.
In one row of time log we had a board_id and a task_id. It is a 1:1 relation on both.
This was our first code for getting the whole data. This took a lot of time and sometimes we got a timeout:
BillingController.php
public function byYear() {
$timeLog = TimeLog::get();
$resp = array();
foreach($timeLog->toArray() as $key => $value) {
if(($timeLog[$key]->board_id && $timeLog[$key]->task_id) > 0 ) {
array_push($resp, array(
'board_title' => isset($timeLog[$key]->board->title) ? $timeLog[$key]->board->title : null,
'task_title' => isset($timeLog[$key]->task->title) ? $timeLog[$key]->task->title : null,
'id' => $timeLog[$key]->id
));
}
}
return response()->json($resp);
}
The TimeLog.php where the relation has been made.
public function board()
{
return $this->belongsTo('App\Board', 'board_id', 'id');
}
public function task()
{
return $this->belongsTo('App\Task', 'task_id', 'id');
}
Our new way is like this:
BillingController.php
public function byYear() {
$timeLog = TimeLog::
join('oc_boards', 'oc_boards.id', '=', 'oc_time_logs.board_id')
->join('oc_tasks', 'oc_tasks.id', '=', 'oc_time_logs.task_id')
->join('oc_users', 'oc_users.id', '=', 'oc_time_logs.user_id')
->select('oc_boards.title AS board_title', 'oc_tasks.title AS task_title','oc_time_logs.id','oc_time_logs.time_used_sec','oc_users.id AS user_id')
->getQuery()
->get();
return response()->json($timeLog);
}
We deleted the relation in TimeLog.php, cause we don't need it anymore. Now we have a load time about 1 sec, which is fine!
There are about 20k entries in the time log table.
My questions are:
Why is the first method out of range (what causes the timeout?)
What does getQuery(); exactly do?
If you need more information just ask me.
--First Question--
One of the issues you might be facing is having all those huge amount of data in memory, i.e:
$timeLog = TimeLog::get();
This is already enormous. Then when you are trying to convert the collection to array:
There is a loop through the collection.
Using the $timeLog->toArray() while initializing the loop based on my understanding is not efficient (I might not be entirely correct about this though)
Thousands of queries are made to retrieve the related models
So what I would propose are five methods (one which saves you from hundreds of query), and the last which is efficient in returning the result as customized:
Since you have many data, then chunk the result ref: Laravel chunk so you have this instead:
$timeLog = TimeLog::chunk(1000, function($logs){
foreach ($logs as $log) {
// Do the stuff here
}
});
Other way is using cursor (runs only one query where the conditions match) the internal operation of cursor as understood is using Generators.
foreach (TimeLog::where([['board_id','>',0],['task_id', '>', 0]])->cursor() as $timelog) {
//do the other stuffs here
}
This looks like the first but instead you have already narrowed your query down to what you need:
TimeLog::where([['board_id','>',0],['task_id', '>', 0]])->get()
Eager Loading would already present the relationship you need on the fly but might lead to more data in memory too. So possibly the chunk method would make things more easier to manage (even though you eagerload related models)
TimeLog::with(['board','task'], function ($query) {
$query->where([['board_id','>',0],['task_id', '>', 0]]);
}])->get();
You can simply use Transformer
With transformer, you can load related model, in elegant, clean and more controlled methods even if the size is huge, and one greater benefit is you can transform the result without having to worry about how to loop round it
You can simply refer to this answer in order to perform a simple use of it. However incase you don't need to transform your response then you can take other options.
Although this might not entirely solve the problem, but because the main issues you face is based on memory management, so the above methods should be useful.
--Second question--
Based on Laravel API here You could see that:
It simply returns the underlying query builder instance. To my observation, it is not needed based on your example.
UPDATE
For question 1, since it seems you want to simply return the result as response, truthfully, its more efficient to paginate this result. Laravel offers pagination The easiest of which is SimplePaginate which is good. The only thing is that it makes some few more queries on the database, but keeps a check on the last index; I guess it uses cursor as well but not sure. I guess finally this might be more ideal, having:
return TimeLog::paginate(1000);
I have faced a similar problem. The main issue here is that Elloquent is really slow doing massive task cause it fetch all the results at the same time so the short answer would be to fetch it row by row using PDO fetch.
Short example:
$db = DB::connection()->getPdo();
$query_sql = TimeLog::join('oc_boards', 'oc_boards.id', '=', 'oc_time_logs.board_id')
->join('oc_tasks', 'oc_tasks.id', '=', 'oc_time_logs.task_id')
->join('oc_users', 'oc_users.id', '=', 'oc_time_logs.user_id')
->select('oc_boards.title AS board_title', 'oc_tasks.title AS task_title','oc_time_logs.id','oc_time_logs.time_used_sec','oc_users.id AS user_id')
->toSql();
$query = $db->prepare($query->sql);
$query->execute();
$logs = array();
while ($log = $query->fetch()) {
$log_filled = new TimeLog();
//fill your model and push it into an array to parse it to json in future
array_push($logs,$log_filled);
}
return response()->json($logs);
I'm working in Laravel 4, and I have a Child model with multiple EducationProfiles:
class Child extends EloquentVersioned
{
public function educationProfiles()
{
return $this->hasMany('EducationProfile');
}
}
If I wanted to get all the EducationProfiles for each kid under age 10 it would be easy:
Child::where('date_of_birth','>','2004-03-27')->with('educationProfiles')->all();
But say (as I do) that I would like to use with() to grab a calculated value for the Education Profiles of each of those kids, something like:
SELECT `education_profiles`.`child_id`, GROUP_CONCAT(`education_profiles`.`district`) as `district_list`
In theory with() only works with relationships, so do I have any options for associating the district_list fields to my Child models?
EDIT: Actually, I was wondering whether with('educationProfiles') generates SQL equivalent to:
EducationProfile::whereIn('id',array(1,2,3,4))
or whether it's actually equivalent to
DB::table('education_profiles')->whereIn('id',array(1,2,3,4))
The reason I ask is that in the former I'm getting models, if it's the latter I'm getting unmodeled data, and thus I can probably mess it up as much as I want. I assume with() generates an additional set models, though. Anybody care to correct or confirm?
Ok, I think I've cracked this nut. No, it is NOT possible to eager load arbitrary queries. However, the tools have been provided by the Fluent query builder to make it relatively easy to replicate eager loading manually.
First, we leverage the original query:
$query = Child::where('date_of_birth','>','2004-03-27')->with('educationProfiles');
$children = $query->get();
$eagerIds = $query->lists('id');
Next, use the $eagerIds to filterDB::table('education_profile') in the same way that with('educationProfiles') would filter EducationProfile::...
$query2 = DB::table('education_profile')->whereIn('child_id',$eagerIds)->select('child_id', 'GROUP_CONCAT(`education_profiles`.`district`) as `district_list`')->groupBy('child_id');
$educationProfiles = $query2->lists('district_list','child_id');
Now we can iterate through $children and just look up the $educationProfiles[$children->id] values for each entry.
Ok, yes, it's an obvious construction, but I haven't seen it laid out explicitly anywhere before as a means of eager loading arbitrary calculations.
You can add a where clause to your hasMany() call like this:
public function educationProfilesUnderTen() {
$ten_years_ago = (new DateTime('10 years ago'))->format('Y-m-d');
return $this->hasMany('EducationProfile')->where('date_of_birth', '>', $ten_years_ago)
}
I am fairly new to programming, php, Magento, and most of all, SQL. Please forgive me if this is somehow a dumb question.
I am trying to use Magento collections to select two different columns in two different tables and join them. These two columns contain product numbers that follow the same conventions and my goal is to get and display the product numbers that field a (lets call it 'product_id') contains that field b ('item_nr') does not.
Here is my function so far, located currently in a model that will be called by a controller action.
public function importCompare() {
$orderlistCollect = Mage::getModel('personal_orderlist/orderlist')->getCollection()
->addFieldToSelect('product_id')
->addFieldToFilter('b.item_nr', null)
->getSelect()
->joinLeft( array('b'=>$this->getTable('catalog/product')), 'main_table.product_id = b.item_nr', array('b.item_nr'));
echo $orderlistCollect;
}
By echoing the variable, I get the following query.
SELECT `main_table`.`product_id`, `b`.`erp_item_nr`
FROM `mag1personal_orderlist` AS `main_table`
LEFT JOIN `` AS `b` ON main_table.product_id = b.item_nr
WHERE (b.item_nr = '')
This looks fairly close to what I want, however the big problem is that I have no idea how to retrieve the information I should derive from this query and echo it. I've tried to use a variety of collection manipulation methods to no avail. Is it easy to use them out of order as well?
Any help here is appreciated.
Collections use interfaces from PHP's standard library to implement for each-able behaviors.
If that sounded like greek, give this a try.
foreach($orderlistCollect as $item)
{
$data = $item->getData();
var_dump($data);
$sku = $item->getSku();
var_dump($sku);
$sku = $item->getData('sku');
var_dump($sku);
}
If you're interested in learning how to do with with your own PHP objects, the Object Iteration section of the manual is a good place to start. However, there's no need to dive deep on this — just treat a collection like you would an array of objects, and you'll be fine.