Laravel8 attribute or appends in query where - laravel

I want to reach the record
if in model User
class User extends Model {
protected $fillable = ['last_name','first_name'];
protected $appends = [
'full_name',
];
public function getFullNameAttribute(): string
{
return $this->first_name . ' ' . $this->last_name;
}
}
in request
full_name = 'John Johans';
How to get database record if
User::query()->where('full_name',$request->full_name)
If I use this record the answer will be an error that full_name does not exist in the database
I would like to use "where" for "appends"
User::query()->where(**MY ATTRIBUTE**,$request)->first()
it is possible ?

2 Options:
Use CONCAT in your WHERE clause
User::query()
->whereRaw('CONCAT(first_name, " ", last_name) = "?"', [$request->full_name])
->get();
Get all the users and then filter in the resulting Collection.
User::cursor()
->filter(function ($user) use ($request) {
return $user->full_name == $request->full_name;
})
->collect();
User::cursor()
->filter(fn($user) => $user->full_name == $request->full_name)
->collect();
Letting SQL do the filtering (Option 1) is probably the better choice.

Related

eloquent with() in multiple where() clouse

I am trying to filter results of relationship table.
public function read_projects_by_coords(Request $request)
{
$from_lat = $request->get("from_lat");
$to_lat = $request->get('to_lat');
$from_lng = $request->get('from_lng');
$to_lng = $request->get('to_lng');
$projects = Project::with(["details" => function($query) use ($from_lat, $from_lng, $to_lat, $to_lng){
return $query->where("details.lat", ">", $from_lat)
->where("details.lat", "<", $to_lat)
->where("details.lng", ">", $from_lng)
->where("details.lng", "<", $to_lng);
}])->get();
return response()->json($projects);
}
But when I run the above details(child) coming with a empty/null result and parent/Project table not filtered. I returns all...
For example $projects = Project::with(["details"])->get(); this is works without a problem. But when I try to filter Project Model with the where inside the with() I can't get the detail object records, and parent is not filtered.
to anyone who wants to see the models parent and child
class Project extends Model
{
protected $table = "projects";
protected $guarded = [];
protected $with = ["details"];
public function details(){
return $this->hasOne("App\Models\Detail");
}
}
class Detail extends Model
{
protected $table = "details";
protected $guarded = [];
public function project(){
return $this->belongsTo("App\Models\Project");
}
}
What am I am missing?
To filter the Project table to only select the ones with some Details matching your parameters, you need to use whereHas. You need to keep your with clause too in order to have the details property correctly populated.
I would use a callback to not repeat the same conditions
$callback = function($query) use ($from_lat, $from_lng, $to_lat, $to_lng) {
$query->where("lat", ">", $from_lat)
->where("lat", "<", $to_lat)
->where("lng", ">", $from_lng)
->where("lng", "<", $to_lng);
}
$projects = Project::with(['details' => $callback])
->whereHas('details', $callback)
->get();
return response()->json($projects);

Why doesn't "where AND" work using EloquentFilter?

I'm using EloquentFilter in my laravel project.
I have a table have with columns First_name, Mid_name, Las_name, Type, Status.
Below are the sample values:
And these are my filters:
public function name($name){
return $this->orWhere('first_name', 'LIKE', "%$name%")
->orWhere('mid_name', 'LIKE', "%$name%")
->orWhere('las_name', 'LIKE', "%$name%");
}
public function isAvailable(){
return $this->where('status', 1);
}
public function thisType(){
return $this->where('type', 2);
}
public function setup(){
$this->thisType();
$this->isAvailable();
}
Here's the model:
<?php
namespace App;
use App\ModelFilters\AdminFilters\UserFilter;
use EloquentFilter\Filterable;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
use Filterable;
protected $table = 'users';
protected $fillable = [
'id',
'first_name',
'mid_name',
'las_name',
'type',
'status'
];
# Other
public function modelFilter()
{
return $this->provideFilter(UserFilter::class);
}
}
So if I use, User:filter(Input::all())->get();, automatically 2 results will be returned, because of the fixed value(2) of type column.
But my problem is when I search for "a" then 5 results are returned. Why does it return 5 results when they don't all have a 2 value in the type column?
I suspect its functioning as ->orWhere when it returns 5 results. Can anyone help me figure out this problem?
I found that you are using this package:
https://github.com/Tucker-Eric/EloquentFilter
So what you are doing with the setup() method is correct.
But the orWhere() makes is it so that the type either has to be 2 or any of the names have to contain ana and since all the names match this it will return 6 records everytime.
The fix is quite easy, you just need to wrap your orWhere() queries inside a where():
public function name($name){
return $this->where(function ($query) use ($name) {
return $query->orWhere('first_name', 'LIKE', "%$name%")
->orWhere('mid_name', 'LIKE', "%$name%")
->orWhere('las_name', 'LIKE', "%$name%");
});
}
This will tell that you want the type to be 2 AND the either of the names to contain an a
Hope this solves you issue!

Search records in muliple tables from a single search form

I have these two tables named posts and events, both tables are not related at all and I want users to be able to search from these two tables using a single search form. Here is what I've got so far :
public function search(Request $request) {
$input = trim($request->input('q'));
$keywords = strtolower($input);
$keywordArr = explode(' ', $keywords);
if (!empty($keywords)) {
foreach($keywordArr as $key) {
$posts = Post::where('title', 'LIKE', '%' . $key . '%')->get();
$events = Event::where('title', 'LIKE', '%' . $key . '%')->get();
}
return view('search/results', compact('posts','events','keywords'));
}
return redirect()->back();
}
That method doesn't work as expected. If both tables has records that match users keywords this method will only return result from events table. How do I solve this ? that's all and thanks!
If you are using laravel searchable package,try this method.
Controller file.
public function searchFunction(Request $request)
{
$result= ModelName::search($search)->get();
}
Model file.
class ModelName extends Model
{
use SearchableTrait;
protected $searchable = [
'columns' => [
'posts.title' => 10,
'events.title' => 9
]
];
}
You should consider using Laravel Scout: https://laravel.com/docs/5.5/scout
It would help making your search much faster and way more relevant compare to a LIKE query with MySQL.

Laravel pluck but combining first name + last name for select

Using select2 with a Laravel / Vue project and need to return JSON in the following format:
[
{ id: 0, text: 'enhancement' },
{ id: 1, text: 'bug' }
]
In Laravel I know I can use pluck to create my list data e.g. for customers:
$customers = Customer::pluck('id', 'first_name');
But Want to return the id and first name + last name as a single name.
How can I do this?
Have you tried using Accessors?
https://laravel.com/docs/5.4/eloquent-mutators#defining-an-accessor
I have not tested it but this could work:
add this to your Customer Eloquent Model:
public function getFullNameAttribute()
{
return ucfirst($this->first_name) . ' ' . ucfirst($this->last_name);
}
and then try:
UPDATED pluck on accessor will only work on a collection. If you try Customer::pluck('id', 'full_name') it will not work since there is no db column named full_name, therefore you must use Customer::all()->pluck('full_name', 'id')
$customers = Customer::all()->pluck('full_name', 'id');
as a side note, for performance it is probably better to do Customer::all(['id', 'first_name', 'last_name'])->pluck(...) so that we don't pull unnecessary columns from the db.
Hope this helps.
Updated Date:- 26th Aug, 2021
If we use computed Attribute accessor functionality, then mind it one important thing...
Laravel Accessor functionality works after the Data fetched from DataBase. So we have to declare "pluck(accessorName)" at the end of Query....
For Example:-
Wrong Methods:-
$data = Model::pluck('full_name','id)->get();
$data = Model::pluck('full_name','id)->all();
in above two queries if you does not have full_name field in DataTable you will get Unknown column error
Right Methods:-
$data = Model::get()->pluck('full_name','id');
$data = Model::all()->pluck('full_name','id');
in above two queries it will works perfectly even if you doesn't have full_name field in DataTable
You can do it like this,
$customers = DB::table('customers')->select("id", "CONCAT(firstname,' ',lastname) as fullname")->get();
or you also do like this,
$customers = DB::table('customers')->select(DB::raw('CONCAT(firstname,' ',lastname) as fullname, id'))->get();
or with PHP way,
$fullname = $customers->firstname. " " .$customers->lastname;
Set this in the User model
public function getFullNameAttribute()
{
return $this->first_name . ' ' . $this->last_name;
}
Then make sure you add this too
protected $appends = ['full_name'];
For me it worked
\DB::table("admin as c")->select(\DB::raw("CONCAT(FirstName, ' ', LastName) AS FIRSTNAME"),"c.AdminID")->pluck("FIRSTNAME","AdminID");
Use this code. Hope it will work. And I solve this problem using this code
User::select(DB::raw("CONCAT(first_name, ' ', last_name) AS full_name"),"id")->pluck("full_name","id");
User Model :
public function getFullNameAttribute()
{
return "{$this->first_name} {$this->last_name}";
}
Get query will result in collection :
$agents = User::whereId($agent->id)->get()->pluck('full_name', 'id');
Inorder to convert variable from objects to array :
$agents = json_decode(json_encode($agents), true);
It worked for me.Enjoy.
/**
* Get the full name of the user.
*
* #return string
*/
public function getFullNameAttribute()
{
return "{$this->first_name} {$this->last_name}";
}
and use this pluck
User::all()->sortBy('id')->pluck('full_name', 'id')
like this
public static function list()
{
return Cache::tags('usersCustomers')->rememberForever(md5('usersCustomers.list:' . locale()), function () {
return self::all()->sortBy('id')->pluck('full_name', 'id');
});
}
** Use this code. Hope it will work. And I solve this problem using this code**
User::select(DB::raw("CONCAT(first_name, ' ', last_name) AS
full_name"),"id")->pluck("full_name","id");

Laravel: get data from variouos tables based on optional conditions

I want to write a query based on optional condition that will fetch data from different tables. My schema looks like
myboxes Table
id,
type_id --> foreign key to box_type table
postal_code
po_box
created_at
updated_at
mybox_access table
id
mybox_id -> foreign key to myboxes table
email
box_type table
id
type_name
And here are my models
MyBox.php
class MyBox extends Model {
public function type() {
return this->hasOne(BoxType::class, 'id', 'type_id');
}
public function access() id
return this->hasOne(MyBoxAccess::class, 'mybox_id', 'type_id');
}
}
MyBoxType.php has following relation ship
public function mybox() {
return this->hasOne(MyBox::class, 'id', 'type_id');
}
And MyBoxAccess.php has following relationship
public function vbox() {
return $this->belongsTo(MyBox::class, 'id', 'mybox_id');
}
Now I want to get based on following condition
I have email as required param and postal_code and po_box as optional params (but one of them will be must and both can also be present).
So I want to get data of all my_boxes that have type_id 3 OR all myboxes whoes id matches to email in mybox_access table AND postal_code or po_box matches to params in myboxes table
For simple match of params postal code and po_box I can write some thing like
$result = new MyBox();
if(!empty($request['postal_code'])) {
$result->where('postal_code', like, '%'.$request['postal_code']);
}
if(!empty($request['po_box'])) {
$result->where('po_box', like, '%'.$request['po_box']);
}
$result = $result->get();
But I don't know how to get data for above mentioned condition. When I try to do using with() like
MyBox::with(['access' => function(Builder $query) use ($request){
$query->where('mybox_id',$request['id']);
}])->get();
I get
`Argument 1 Passed to {closure} () must be an instance of Illuminat\Database\Query\Builder, instance of Illuminate\Databaase\Eloquent\Relation\HasOne given`
Can any body please let me know how can I get data based on above mentioned condition
$query is a relationship, not a builder instance.
So this should not throw any Exception.
MyBox::with(['access' => function ($query) {
$query->where('mybox_id', $request['id']);
}])->get();
But I don't think it'd resole your issue because your Box <=> Access relationship is not right. It should be HasMany.
// MyBox.php
public function type()
{
return $this->hasOne(BoxType::class, 'id', 'type_id');
}
public function access()
{
return $this->hasMany(MyBoxAccess::class, 'mybox_id', 'id');
}
Then in your Controller you could do this.
// $results where type_id is 3
$results = MyBox::where('type_id', 3)->get();
// List of boxes accessible by email
$results = MyBox::whereHas('access', function ($query) {
$query->where('email', request()->input('email'));
})->get();
// Results where postal_code and po_box matches the request
$results = MyBox::with('access')->where(function ($query) {
if (request()->has('postal_code')) {
$query->where('postal_code', 'like', '%' . request()->input('postal_code'));
}
if (request()->has('po_box')) {
$query->where('po_box', 'like', '%' . request()->input('po_box'));
}
})->get();
And if you want to merge all conditions:
$results = MyBox::where(function ($query) {
if (request()->has('type_id')) {
$query->where('type_id', request()->input('type_id'));
}
if (request()->has('email')) {
$query->whereHas('access', function ($query) {
$query->where('email', request()->input('email'));
});
}
if (request()->has('postal_code')) {
$query->where('postal_code', 'like', '%' . request()->input('postal_code'));
}
if (request()->has('po_box')) {
$query->where('po_box', 'like', '%' . request()->input('po_box'));
}
})->get();
I always use the request() facade when using in closures, it feels cleaner to me.
Try this query:
MyBox::with('access')->get();

Resources