This is for Laravel 5.2. I have a method defined as follows in my Users model:
public function name()
{
return "$this->name_first $this->name_last";
}
I'm trying to figure out how to use that as part of a query, but it seems like it isn't possible for a somewhat obvious reason: the database doesn't know anything about the method and that makes perfect sense. However, the concept of what I'm trying to achieve makes sense in certain contexts, so I'm trying to see if there's a way to accomplish it naturally in Eloquent.
This doesn't work, but it represents what I'm trying to accomplish:
public function index(Request $request)
{
$query = new User();
if(Request::has('name')) {
$query = $query->where('name', 'LIKE', '%' . Request::input('name') . '%');
}
return $query->get();
}
In short, the database only knows about name_first and name_last, but I'd like to be able to search (and sort) on name without storing it. Maybe storing the concatenated name is no big deal and I should just do it, but I'm also trying to learn.
I agree with Bogdan, The issue of having spaces either in the first or the last name makes querying on the individual columns difficult, so this is probably the way to go. Code reuse can be increased by defining it as a custom scope:
https://laravel.com/docs/5.2/eloquent#local-scopes
// class User
public function scopeOfFullNameLike($query, $fullName)
{
return $query->whereRaw('CONCAT(name_first, " ", name_last) LIKE "%?%"', [$fullName]);
}
// ...
User::ofFullNameLike('john doe')->get();
That would mean you should be concatenating the column value at the database level. Which means you could use CONCAT and a whereRaw clause:
$query->whereRaw('CONCAT(name_first, " ", name_last) LIKE ?', ['%' . Request::input('name') . '%']);
Or as an alternative if you want the full name to be selected as part of the result, you could concatenate within the select and use having instead of where to be able to use a column alias:
$query->select('*', DB::raw('CONCAT(name_first, " ", name_last) as name'))
->having('name', 'LIKE', '%' . Request::input('name') . '%');
Not the most compact solutions, but things involving MySQL functions need some raw SQL to work with the Query Builder.
Related
I have a table like this
Teacher Table
What I am trying to do is to get the row which contains the subjects 1(or any other number like 7,8 etc.)
This is what I have tried in my controller.
public function allTeachers($sub_id) //receiving $sub_id(to be searched)
{
$teachers_all=Teacher::where('subjects','like','%'.','.$sub_id.'%')->latest()->paginate(50);
dd($teachers_all);
}
The problem here is that, I am getting all the rows which contains subjects as '1',e.g. if it is '3,11,22' or '41,5' it gets selected.
But what I am trying to achieve is it should only return where subjects string contains '1' followed by any other number after ',' or '1,2,44,31,23' etc.
I am using laravel, I hope I made the question clear.
The solution to your question would be either to use find_in_set or concat to fill some missing commas and then search for the value:
Teacher::whereRaw('find_in_set("' . $sub_id . '", subjects) <> 0')
->latest()
->paginate(50);
or
Teacher::whereRaw('concat(",", colors, ",") like "%,' . $sub_id . ',%"')
->latest()
->paginate(50);
That being said, #bromeer's comments hold true in any case. MySQL isn't around comma-separated values in fields. Both examples shown above aren't an ideal solution. You should look into relationships a bit more.
I suggest using a many-to-many relationship in your case. For that, create a pivot table called teacher_subject and add the relation to your Teacher model:
public function subjects()
{
return $this->belongsToMany(Subject::class);
}
To find any teachers teaching a specific subject, use whereHas like this:
Teacher::whereHas('subjects', function (Builder $query) use ($sub_id) {
$query->where('id', $sub_id);
})->latest()->paginate(50);
I built small search form helps me search in jobsTable from db
jobs Table has jobTitle, jobCompany, jobGovernorate, jobLocation and created_at column
And posted data from search form:
{"jobTitle":"designer","jobCompany":null,"jobGovernorate":null,"jobLocation":null,"postingDate":"ad"}
I mean some input may be null, so how to write dynamic where clause for inputs have value, i want search engine able to search by JobTitle, JobCompany or All inputs if have value.
Hint: fields name and table columns name are same
if there's a way to retrieve jobs from my db like
DB::table('jobs')->where($request->all())
Sorry for poor english, I don't know how to explain my question
I prefer to define all search fields.
$searchFields = ['jobTitle','jobCompany','jobGovernorate','jobLocation','postingDate'];
$jobQuery = DB::table('jobs');
foreach ($searchFields as $field) {
if ($request->has($field)) {
$jobQuery->where($field, $request->input($field));
}
}
$results = $jobQuery->get();
you have to code the query, I mean, what are you looking for?
something like
DB::table('jobs')->where([
['jobTitle', 'like', $request->jobTitle . '%'],
['jobCompany', 'like', $request->jobCompany . '%']])->get();
I am very new to Laravel and am going through the tutorials and am stuck on something.
I have a complex query that I need to reuse with one parameter change in the where clause. I added this as a query scope in my Model and then call it from my corresponding Controller. When I try to return the data though I am getting this error:
Object of class Illuminate\Database\Eloquent\Builder could not be converted to string
Here is the query scope:
public function scopeCrosstab($wellID)
{
return static::select('sampleDate', \DB::raw("
max(if(chemID=1, pfcLevel, ' ')) as 'PFOA', max(if(chemID=1, noteAbr, ' ')) as 'PFOANote'
"))
->leftJoin('SampleNote', 'WellSample.noteID', '=', 'SampleNote.noteID')
->where('wellID', '=', $wellID)
->groupBy('sampleDate');
}
Here is the Controller code:
public function smith()
{
$wellSamples = WellSample::crosstab(2);
return $wellSamples->get();
//return view('pages.wellsample', compact('wellSamples'));
}
I have tried many different permutations of the code with quotes, with double quotes etc. If I hard code the value in the query scope it works, but I need to be able to make it dynamic.
Scope methods take at least one parameter, the first of which must be $query. You then build off of the query variable that is passed to your scope method. Like this:
public function scopeCrosstab($query, $wellID)
{
return $query->select('sampleDate', \DB::raw("
max(if(chemID=1, pfcLevel, ' ')) as 'PFOA', max(if(chemID=1, noteAbr, ' ')) as 'PFOANote'
"))
->leftJoin('SampleNote', 'WellSample.noteID', '=', 'SampleNote.noteID')
->where('wellID', '=', $wellID)
->groupBy('sampleDate');
}
Sorry if my title is confusing, not sure how to explain this within a line. Let's say I have a table with some columns and I have this
$model = Document::where('systemName', '=', $systemName)->where('ticketNumber', '=', ($nextTicketNumber))->get(); ticketNumber is unique where as there are quite a few systemNames
The above will get exactly what I want but I want more. I want an another array which will store all the rows under the same systemName. I know I can do this by doing
$allSystemNameModel = Document::where('systemName', '=', $systemName)
But is there a possible way to not having two variables and be easier?
No, you can't get both collections into one variable with one statement, however, you can create an array and store your results there:
$both = [];
$both['model'] = ...
$both['all'] = ...
UPDATE:
To avoid querying the database twice, you can use a first method that laravel provides us with.
$allSystemNameModel = Document::where('systemName', '=', $systemName);
$model = $allSystemNameModel->first(function ($doc) use ($nextTicketNumber) {
return $doc->ticketNumber == $nextTicketNumber;
});
$both['model'] = $model;
$both['all'] = $allSystemNameModel->all();
Note: Be sure to use use when working with php closures since $nextTicketNumber will be undefined otherwise.
I have a search query that needs to be done. However, a search doesn't always have all values set, like in this case.
$aEvents = DB::table('events')
->where('client_id', '=', $client_id);
The question is, how can I make this where statement depend on the value of $client_id. So if the value is empty I don't want the Where statement to occur.
Also, I do not want to write several complete queries with if statements in PHP. To many variables. Ideally I'd like something like this:
$aEvents = DB::table('events')
->(($client_id != "") ? where('client_id', '=', $client_id) : "");
Using eloquent is (really!) nice and save, but I'm not yet up to speed with if statements in std Class objects I guess. Any help is appreciated.
You may try something like this:
$query = DB::table('events');
if(!empty($client_id)) {
$query->where('client_id', $client_id);
}
$aEvents = $query->get(); // Call this at last to get the result
If you are passing client_id to the server via a form/query string(user input) then you may try something like this:
if($client_id = Input::get('client_id')) {
$query->where('client_id', $client_id);
}
Update: For pagination try this:
$aEvents = $query->paginate(10); // For 10 per page
So you may call links() method in your view if you pass it like this:
return View::make('viewName')->with('aEvents', $aEvents);
In the view for pagination links:
$aEvents->links()
You can also use query scopes in the model for this purpose. Scopes allow you to easily re-use query logic in your models. In the model Event, you can add the following query scope:
public function scopeClientID($query, $client_id)
{
if ($client_id != '') {
return $query->where('client_id', '=', $client_id);
} else {
return $query;
}
}
Then from your controller or wherever you're calling it from, you can do the following:
$aEvents = Event::clientID($client_id);
If you want to get all the results, then you can do:
$aEvents = Event::clientID($client_id)->get();
Or if you want pagination, you can do:
$aEvents = Event::clientID($client_id)->paginate();
You can also chain it with other methods like you'd do in a eloquent query.
You can read more about model query scopes at http://laravel.com/docs/eloquent#query-scopes