Active Record and queries with CodeIgniter - codeigniter

I am using codeigniter for my application and i am a bit confused, I wrote some queries like that:
public function checkemail($email) {
$this->db->select('email')->from('user')->where('email', $email);
}
But in the manual of codeigniter ( http://codeigniter.com/user_guide/database/active_record.html ) they talk about $this->db->get();
Should I add it after the $this->db->select query?
My function works fine...
When should I use get() ?
Thanks you!

Yes, you'll need to run get() after the other methods. select(), from() and where() add their respective statements to the query, and get() actually runs the query and returns the result as an object.
In this case, you could just add it on to the end of the chain.
public function checkemail($email) {
$this->db
->select('email')
->from('user')
->where('email', $email)
->get();
}
If you want to work with the result afterwards, make sure that you are assigning it to a variable.
$user = $this->db
->select('email')
->from('user')
->where('email', $email)
->get();

If you use get("table_name") then you don't need to use from("table_name"). It's just an alternative syntax it seems.
From the user guide, all the way at the bottom it says: As shown earlier, the FROM portion of your query can be specified in the $this->db->get() function, so use whichever method you prefer.

Related

Laravel 7 Query with() and using Where()

Hey guys I have a query that looks like this
$query = Transaction::with(['customer', 'merchant', 'batch'])
->select(sprintf('%s.*', (new Transaction)->table));
I need to filter the transaction based on the iso_id that belons to the current user logged in.
$query = Transaction::with(['customer', 'merchant', 'batch'])
->select(sprintf('%s.*', (new Transaction)->table))
->where('merchant.iso_id', '=', auth()->user()->isIso());
The iso_id I need to compare to, is inside the merchant table
auth()->user()->isIso() returns the correct iso_id if true or sends false if not
So my first try at this was to use where('merchant.iso_id', '=', auth()->user()->isIso())
But that returns that the column does not exist because for some reason, it's not switching from the transaction model to the merchant one.
I am not sure how to use the stuff inside with() as a selector for my where()
Any help would be appreciated!
Try using whereHas to add the constraint:
$query = Transaction::with(['customer', 'batch'])
->whereHas('merchant', function ($q) {
$q->where('iso_id', auth()->user()->isIso());
})
->select(sprintf('%s.*', (new Transaction)->table))
->get();

Best way to query model relationship in Eloquent

I am working within a controller in a Laravel application. I am returning a table to the view. The table is based on my PlanSubmission model. I am receiving parameters through a GET request and using those parameters to return a filtered set of rows to my view.
The first part of my controller looks like this and is working fine:
public function index()
{
//Used for filter. The request is received in the URL
if (request()->has('status')) {
$plans = PlanSubmission::where('status', request('status'))->paginate(25)->appends('status', request('status'));
}
elseif (request('employer_name')) {
$plans = PlanSubmission::where('employer_name', request('employer_name'))->paginate(25)->appends('employer_name', request('employer_name'));
}
I have run into a problem because now I need to use a model relationship in the controller. I am receiving 'advisor_name' from the request. The 'advisor_id" column is the foreign key on the PlanSubmission model. The 'advisor_name' column exists in the Advisor model. I have a function on my PlanSubmission model that looks like this:
public function advisor()
{
return $this->belongsTo(Advisor::class);
}
Initially, I thought there was a way I could do this easily with something like:
$plans = PlanSubmission::where(advisor->name, request('advisor_name'))->paginate(25)->appends('advisor_name', request('advisor_name'));
Of course, this will not work because I cannot enter a relationship into the first parameter in the Where Clause.
I do not know where to go from here. My other thought is to return all the advisors first from the Advisor model like this:
$advisors = Advisor::where('name', request('advisor_name'));
Then, I imagine I would have to somehow loop through that and get the id (primary key) for each of the objects in $advisors and somehow get that into the PlanSubmission where clause. I'm totally lost.
Like Victor mentions in his answer you can use whereHas like so:
PlanSubmission::whereHas('advisor', function ($query) {
$query->where('name', request('advisor_name'));
});
You didn't asked this directly, but I noticed that you use conditionals to make different queries. Eloquent provides a few way to make this a bit nicer to deal with.
The first which is kind of obvious is that that whatever method you call a builder (query) is returned that you can just add on to. It could be there were some common restrictions in your two cases:
public function index()
{
$query = PlanSubmission::where('something', 42);
if (request()->has('status')) {
$query = $query->where('status', request('status'));
} elseif (..) {
...
}
return $query->paginate(25);
}
Another way to do conditional queries in Laravel is using when. E.g. for status:
$query = $query->when(request->has('status'), function ($query) {
// note that you don't have to return the query
$query->where('status', request('status'));
});
// or PlanSubmission::>when(..)
In your example you cannot both filter by status AND advisor_name, but lets assume that would be okay, then you can combine everything like so:
public function index()
{
return PlanSubmission::query()
//->where('something', 42)
->when(request->has('status'), function ($query) {
$query->where('status', request('status'));
})
->when(request->has('advisor_name'), function ($query) {
$query->whereHas('advisor', function ($query) {
$query->where('name', request('advisor_name'));
});
})->paginate(25);
}
This approach may seem verbose for simple queries and then it is fine to use if conditions, but for complex queries when can be useful. Also the idea of "building up a query" also works nice in those situation. You can pass the query builder around and continuously build it up.
You can use whereHas for that
docs

How can I get the laravel join method without using foreach command?

How can I get the laravel join method without using foreach command? How can I solve it without using the Foreach command
{{$app->name}} I used to this type. But I'm constantly getting error.
Controller.php file content
public function show($id)
{
$show = Duty::where('duty_id', '=', $id)->count();
if ($show!=0){
$app = DB::table('users')
->join('duties', 'duties.appointed_user_id', '=', 'users.id')
->select('users.name', 'duties.*')
->get();
$data = Duty::where('duty_id', '=', $id)->get();
return view('duty.show', compact('data', 'app'));
}
else
{
return redirect()->back()->with('status', 'Sorun oluştu');
}
}
Property [name] does not exist on this collection instance. (View: D:\xampp\htdocs\personality\resources\views\duty\show.blade.php)
You have a list (collection) of users, not a single user. That is why you can't get just the name from it, because it doesn't know which one to get the name of. This problem has nothing to do with using the join method.
If you only expect to get one result from your query, you could change from ->get() to ->first(). This would allow you to call {{$app->name}} without breaking. But only do this if you expect a single result and use first.
If you expect more than one user, there is no way to display the names without looping in some way.
That's what relationships are for. In that case you could do User::with(:duties'). Or in your case the other way around would probably work better Duty::find($id)->with('user')

laravel: odd behavior when query is empty

I have a model
I call it this way:
Sight::filter(['type'=>'menu']);
and in model:
public function scopeFilter($query,$params)
{
return $query
->wherePublish(1)
->whereIn_special(1)
->latest()
->first();
}
when there is one or more records, it works normally.
but when database is empty I get an odd behavior:
with dd(Sight::filter(['type'=>'menu']))
or
$query
->wherePublish(1)
->whereIn_special(1)
->latest()
->first();
dd($query);
I got this result:
But with
dd(
$query
->wherePublish(1)
->whereIn_special(1)
->latest()
->first();
)
I got Null so it is right!
how can I return Null? what is my wrong?
You shouldn't be calling first() inside of a scope - you are only meant to adjust the query by constraining it. You should call first() in your chain after applying the filter() scope. If you want to use the same syntax rather than chaining like that you would be best to define a custom static method.
public static function filter($params)
{
return self::wherePublish(1)
->whereIn_special(1)
->latest()
->first();
]
Also note that in your example your scope accepts an argument (and you pass it one) but it isn't actually used in your code.

Laravel 5 Eager Loading with parameters

I'm working on a project with a bit of a complex model that has joins in its relations and also requires a parameter. It all works pretty well, except for when I need to eager load the relationship, as I couldn't figure out if there is a way to pass a parameter/variable to it.
The Controller
$template = Template::find($request->input('id'));
$this->output = $template->zones()->with('widgets_with_selected')->get();
The Model
public function widgets_with_selected($banner_id)
{
return $this->belongsToMany('App\Models\Widget', 'zone_has_widgets')
->leftJoin('banner_has_widgets', function($join) use($banner_id) {
$join->on('widgets.id', '=', 'banner_has_widgets.widget_id')
->where('banner_has_widgets.banner_id', '=', $banner_id);
})
->select('widgets.*', 'banner_has_widgets.banner_id');
}
This is returning a Missing argument error as the variable is not being passed.
I have resolved the issue by moving the logic to the controller, but I want to know if there is a way to keep the relationship in the model and just call it with a parameter.
Looking at the laravel code I dont think this is possible as you'd like to do it. You simply cant pass parameters to a with() call.
A possible workaround is to have an attribute on your model for $banner_id.
$template = Template::find($request->input('id'));
$template->banner_id = 1;
$this->output = $template->zones()->with('widgets_with_selected')->get();
Then change your relationship
public function widgets_with_selected()
{
return $this>belongsToMany('App\Models\Widget','zone_has_widgets')
->leftJoin('banner_has_widgets', function($join) use($this->banner_id) {
$join->on('widgets.id', '=', 'banner_has_widgets.widget_id')
->where('banner_has_widgets.banner_id', '=', $banner_id);
})
->select('widgets.*', 'banner_has_widgets.banner_id');
}
You could perhaps alter it a bit by passing the banner_id through a method. Sortof like this in your model:
public function setBanner($id) {
$this->banner_id = $id;
return $this;
}
Then you can do:
$template->setBanner($banner_id)->zones()->with('widgets_with_selected')->get();
Not sure if this works, and it's not really a clean solution but a hack.

Resources