How to make query in model with 2 parameters - codeigniter

I need make a query with 2 parameters in model on codeigniter 4.
Is this possible?
This is the model:
public function obtenerProyectoId($id_user,$id_project)
{
$proyectos = $this->db->query(" SELECT * FROM proyectos INNER JOIN empresa ON proyectos.id_usuario=$id_user and proyectos.id_proyecto=id_project");
return $proyectos->getResultArray();
}
in mysql this query is correct, but in CI4 it shows an error:
Too few arguments to function App\Models\Proyectos::obtenerProyecto(),
1 passed in
C:\xampp\htdocs\plataformaknowmad\app\Controllers\verProyectos.php on
line 25 and exactly 2 expected

Yes, it is possible to make a query with multiple params.
//if second param is optional
public function obtenerProyectoId($id_user,$id_project="")
In query $ is missing from id_project
$this->db->query("SELECT * FROM proyectos INNER JOIN empresa ON proyectos.id_usuario=$id_user and proyectos.id_proyecto=$id_project");
May be you did not pass second parameter($id_project) in controller:
verProyectos.php on line 25 and exactly 2 expected

Related

How to bind value sql query in laravel?

I have a query. Query is include sql function. So I want to directly. But I need parameter.
$parameters = DB::select("SELECT GetFlowPropertyValue(flow.id, 'PCommonLineDataNumber') subscriberNumber, (SELECT Id FROM ConfigurationItem WHERE FlowId = flow.id ORDER BY Id DESC Limit 1) ConfigurationItemId, GetObjectTypeRelationParentObjectValue(6, 1, flow.id) CustomerId, GetFlowPropertyValue(flow.id, 'MainOfferingName') MainOfferingName, GetFlowPropertyValue(flow.Id, 'CampaignName') CampaignName FROM akislar flow WHERE id ='$query->id'");
As you can see, Final parameter come foreach but doesnt run. I use dd and I write query.
I see $query->id is look like empty. It is not defined.
How can I bind $query->id ?

How to convert query with many joins and inner select to Laravel ORM

Hi guys please help solve this problem.
Need to convert this query to Laravel ORM.
$user = Auth::user();
$datas = DB::select('select * from kvits k
left join (select o.kvit_id, sum(o.amount * o.price) as sum from operations o
group by o.kvit_id) s on k.id = s.kvit_id
left join users u on k.user_id = u.id
left join users h on k.hamkor_id = h.id
left join stores s2 on k.store_id = s2.id
where k.user_id = ' $user->id ');
Main problem is how to convert this query to Larave ORM.
Basically this part
left join (select o.kvit_id, sum(o.amount * o.price) as sum from operations o
group by o.kvit_id) s on k.id = s.kvit_id
Second problem is:
Why Laravel getting the last join id in the column without taking all the ids (e.g. k.id, ****, u.id, ***, s.id on this query). And does not display data from all other joined columns.
How to get them.
I want to get data all joined tables also, like k.id, k.date, ... u.id, u.name, .... s.id, s.name, s.notes . Like belowed table.
First, Why Laravel getting the last join id in the column without taking all the ids (e.g. k.id, ****, u.id, ***, s.id on this query)., Laravel uses PDO to fetch data from the database, and PDO fetches the data by the column name and not by the table_name.column_name index.
Basically what you have to do is create your Model (the model that will contain all this data together) like that (it is a model example):
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class MyUserModel extends Model {
public function addresses() {
// query all addresses of this user and returns it
}
public function phone () {
// query User's phone from database and returns it
}
// ...
}
and then when you want to use some value, for example, you want to get the User's phone ID, you just use $user->phone->id and Laravel will run the phone() method from MyUserModel class. To learn more about go to Laravel Eloquent Relationships Queries Documentation
if you want to always load these data together whenever a query with this model is made, you can use the protected $with model variable to can fetch all data. see more on Laravel Documentation.
CAUTION: If you want to customize the method query from outside the method you must call the method as a Function, for example $user->phone()->where('active', 1), and not as a Dynamic Property like $user->phone->where('active', 1).

How to write subquery like this using active records

Hello friends I wanna write this query in codeigniter using active record,
public function getHallServices($city,$receiption_capacity,$booked_date){
$sql="select hi.*,hf.* FROM hall_info hi, hall_feature hf WHERE
hf.hall_info_id=hi.id and hi.city=? and hf.receiption_capacity<=? and hi.id not IN
(select hall_info_id FROM events
WHERE event_date = ?
GROUP BY hall_info_id
)";
$query=$this->db->query($sql,array('city'=>$city,'receiption_capacity'=>$receiption_capacity,'event_date'=>$booked_date));
return $query->result_array();
}
This query is not working as expected in codeigniter but works fine in postresql. I am not getting how to pass arguments to inner query. Please help me to correct or can give active record query for same.
Modify your codes to be like this:
public function getHallServices($city,$receiption_capacity,$booked_date){
$sql="select hi.*,hf.* FROM hall_info hi, hall_feature hf WHERE
hf.hall_info_id=hi.id and hi.city=? and hf.receiption_capacity<=? and hi.id not IN
(select hall_info_id FROM events
WHERE event_date = ?
GROUP BY hall_info_id
)";
$query=$this->db->query($sql,array($city,$receiption_capacity,$booked_date));
return $query->result_array();
}
Tell me if it works.

How to Join same table in laravel

I wan to wirte a join query to connect same table, and without ON, but when i write it in laravel without on it is showing error
$key = DB::table('api_keys as ak')
->join('api_keys as bk','')
->where('ak.api_key', $api_key)->where('ak.user_id',0)
->pluck('api_key');
want to build the below query,
SELECT * FROM `api_keys` as ak
JOIN `api_keys` as bk
WHERE ak.`api_key`=$akey
and ak.`user_id`=$auser
and bk.`user_id`=$bsuer
and bk.`api_key`=$bkey
You must provide an ON clause for the join. More about where ON clauses are required can be found in this answer.
You can view the generated query using toSql() on a QueryBuilder object:
echo $key = DB::table('api_keys as ak')
->join('api_keys as bk','')
->where('ak.api_key', $api_key)->where('ak.user_id',0)
->toSql();
Which in your case returns:
select * from `api_keys` as `ak` inner join `api_keys` as `bk`
on `` `` where `ak`.`api_key` = ? and `ak`.`user_id` = ?
In your case it isn't totally clear what you are trying to achieve, but you might consider joining on api_key or the primary key of the api_keys table, if that is different:
$key = DB::table('api_keys as ak')
->join('api_keys as bk','ak.api_key', '=', bk.api_key)
->where('ak.api_key', $api_key)->where('ak.user_id',0)
->pluck('api_key');
DB::table('registerusers as a')
->join('registerusers as b', 'a.id', 'b.refer_id')
->where('a.username', 'b.username')
->where('b.id', 'a.refer_id')
->value('b.id');
without using on clause in laravel query builder you can use following
$key = DB::table(DB::raw('api_keys as ak, api_keys as bk'))
->where('ak.api_key', '=', $api_key)
->where('ak.user_id','=',0)
->where('ak.PK','=','bk.PK')
->pluck('ak.api_key')
where PK references to your table's primary key.
result will in your case.
select * from api_keys as ak, api_keys as bk where ak.api_key= 'api_key_value' and ak.user_id = 0 and ak.PK = bk.PK
I solved this by creating my own class and starting out with a base query which I modify to apply the join (using Laravel's joinSub function) as follows:
public function __construct()
{
$this->query = DB::table('question_responses as BASE');
}
public function applyFilter($questionId, $questionValue) {
$filterTableStr = 'filter_table_'.$questionId;
$filterIdStr = 'filter_id_'.$questionId;
$filterQuery = DB::table('question_responses AS '.$filterTableStr)
->select('survey_response_id AS '.$filterIdStr)
->where($filterTableStr.'.question_short_name', $questionId)
->where($filterTableStr.'.value', $questionValue);
$resultTableStr = 'result_table_'.$questionId;
$this->query = $this->query
->joinSub($filterQuery, $resultTableStr, function($join) use ($resultTableStr, $filterIdStr) {
$join->on('BASE.survey_response_id', '=', $resultTableStr.'.'.$filterIdStr);
});
}
After applying my required filters I can just call $this->query->get() as normal to obtain the result.
The important part was to make sure that each resulting table and join fields has unique names.
With this method I can apply unlimited filters to my base query.

How can I unscope a model on create in laravel

I have a Has and Belongs To Many relationship between leads and statuses. A Lead is a prospective customer. The statuses can be active, on hold, unsubscribed, etc. I have the following tables:
| Leads | Lead_Status | Statuses |
|---------|--------------|----------|
| - id | - lead_id | - id |
| - name | - status_id | - name |
We have multiple statuses for each lead because we need to keep track of the status history for analytics. This is all working great. It is common to apply a global scope as opposed to query scope to a model if the scope is used in most of the queries. My scope does something ugly to retrieve the current status of the lead and make it easily accessible with something like $lead->status that same way we get $lead->name. Here is the scoping process using newQuery to add query info to the initial query when getting the Lead:::
public function newQuery() {
return parent::newQuery()->select(DB::raw('leads.*, status.status_id AS status'))->from(DB::raw(' leads
LEFT OUTER JOIN (
SELECT ls.status_id, ls.lead_id
FROM (
SELECT lead_id, max(created_at) AS max_created_at
FROM lead_status GROUP BY lead_id
) AS ls2 INNER JOIN lead_status AS ls ON ls.lead_id = ls2.lead_id AND ls.created_at = ls2.max_created_at
) AS status ON leads.id = status.lead_id
'));
}
This works really well. It returns the lead with id, name and status.
Now for the problem:
When I try to create a new Lead I get an error:
SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near
'
LEFT OUTER JOIN (
SELECT ls.status_id, ls.lead_id
FROM (
' at line 2
(SQL:
insert into leads
LEFT OUTER JOIN (
SELECT ls.status_id, ls.lead_id
FROM (
SELECT lead_id, max(created_at) AS max_created_at
FROM lead_status GROUP BY lead_id
) AS ls2
INNER JOIN lead_status AS ls ON ls.lead_id = ls2.lead_id
AND ls.created_at = ls2.max_created_at
) AS status ON leads.id = status.lead_id
(`id`, `name`, `updated_at`, `created_at`) values (test5, Dustin Griffith, 2014-12-03 18:24:06, 2014-12-03 18:24:06)
)
It is obvious that the Lead is being scoped on Lead::create(). This is not what I want. I want it to scope only when we are selecting data from the leads table. So my main question is how do I tell this to only scope when it is a select statement?
I have also used the ScopeInterface method seen in the laravel docs under global scope which is more complex but favored in some situations. I can add that if we should be building off of that instead of the older newQuery method. I had the same results with that method.
I am not looking for a hacky solution. Any input will be greatly appreciated but I am searching for the correct way to handle these situations because I will be doing this time and time again in the future.
newQuery isn't the right method for this. What we want to use is Global Scope method mentioned in the question. This allows us to define the scoping used every time the query is called as well as how to remove the scoping when it isn't needed. Laravel is smart enough to remove the scoping when needed (create, update, delete). The Docs read:
If an Eloquent model uses a trait that has a method matching the bootNameOfTrait naming convention, that trait method will be called when the Eloquent model is booted, giving you an opportunity to register a global scope, or do anything else you want. A scope must implement ScopeInterface, which specifies two methods: apply and remove.
I skipped the trait part and placed the following in the model itself but for organization it would be wise to break this into its own Trait. I added the following to the model:
// Import the classes
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\ScopeInterface;
// Add the global scope
public static function boot() {
parent::boot();
static::addGlobalScope(new StatusColumnScope);
}
// Create the scope
class StatusColumnScope implements ScopeInterface {
// Create our apply method that will be called for every query on this model
public function apply(Builder $builder) {
$builder->select(DB::raw('leads.*, status.status_id AS status'))->from(DB::raw(' leads
LEFT OUTER JOIN (
SELECT ls.status_id, ls.lead_id
FROM (
SELECT lead_id, max(created_at) AS max_created_at
FROM lead_status GROUP BY lead_id
) AS ls2 INNER JOIN lead_status AS ls ON ls.lead_id = ls2.lead_id AND ls.created_at = ls2.max_created_at
) AS status ON leads.id = status.lead_id
'));
}
// Create the remove method that is called every time we need to unscope
public function remove(Builder $builder) {
$query = $builder->getQuery();
$query->selectRaw('select *')->from('leads');
}
}
The remove method above is called when we need to un-scope. This was confusing to me at first because I was thinking it should just not scope if we don't need to scope. This isn't how Laravel works though. This only became appearant after really digging in. I will show you what I saw. Let's look under the hood of Laravel at a few methods in Eloquent/Builder.php:
create:
public static function create(array $attributes) {
$model = new static($attributes);
$model->save();
return $model;
}
This calls save:
public function save(array $options = array()) {
$query = $this->newQueryWithoutScopes();
.......
}
and that calls newQueryWithoutScope:
public function newQueryWithoutScopes() {
return $this->removeGlobalScopes($this->newQuery());
}
and of course removeGlobalScopes:
public function removeGlobalScopes($builder) {
foreach ($this->getGlobalScopes() as $scope) {
$scope->remove($builder, $this);
}
return $builder;
}
$scope->remove() is the remove method that we setup in our StatusColumnScope class. This is called to reverse the scoping but in our case I just overrode the query completely, setting it back to it's original query.

Resources