How to get specific columns in CodeIgniter 4? - php

I wanna select specific columns from table. Not all columns.
$this->userModel->where($where)->first();
I'm using this but it returns all data.

According to the CI4 query builder documentation you can use select() in this way:
$db = \Config\Database::connect();
$builder = $db->table('mytablename'); // 'mytablename' is the name of your table
$builder->select('userid, username'); // names of your columns, single string, separated by a comma
$builder->where('userid', 5); // where clause
$query = $builder->get();
return $query;
where() could be possible to use in 4 ways, you can choose.
This stuff should be placed in Model file, method of which would return $query set of DB data.

(Tested under CI 4.2.7)
There is also a select method in the model, which accepts an array of columns:
$userModel->select(['id','name'])->where('id', 1)->first();

Related

how to convert this SQL query to eloquent in Laravel

I am trying to convert this SQL query to Eloquent in Laravel
Convert SQL code to Eloquent
SELECT
session_id,
SUM(points) AS total_points
FROM
(
SELECT
session_id,
spent_points AS points
FROM
session_details
WHERE
session_id IN
(
" - Meagevy6y9ukbmFXvB7",
" - Meak6dG9iqvHWfAGQvy"
)
UNION ALL
SELECT
session_id,
price_points
FROM
template_sales
WHERE
session_id IN
(
" - Meagevy6y9ukbmFXvB7",
" - Meak6dG9iqvHWfAGQvy"
)
)
t
GROUP BY
session_id
my code in Laravel but not working
$ids = ["-Meagevy6y9ukbmFXvB7","-Meak6dG9iqvHWfAGQvy"];
$query = DB::table('session_details')
->select('session_id',DB::raw('SUM(points) AS total_points FROM ( SELECT session_id, spent_points AS points FROM session_details
WHERE session_id IN ("'.$ids.'") UNION ALL SELECT session_id,price_points FROM template_sales WHERE session_id IN ("'.$ids.'") ) t GROUP BY session_id'))
->get();
I'd advise you to use Eloquent models & Eloquent relationships to make the query more readable.
Execute the following in your terminal to create a new model:
php artisan make:model SessionDetail
Open the file that Laravel has generated for you in /app/Models (or whatever folders your models are in), and set the table in the model by putting the following property into the model class: public $table = "session_details";
If your model does not use or have Laravel timestamps which are usually created_at & updated_at, you can also use this property to disable them in the model: public $timestamps = false;
After that, create generate another model by execute the following command in your terminal:
php artisan make:model TemplateSale
Follow the same instructions again but this time change the table name to template_sales
After you have done that, head into your SessionDetail model and make a relationship to the TemplateSale model using the following code (this must be in the model class beneath the properties):
public function template_sales() {
return $this->hasMany(TemplateSale::class);
}
After that, you can replace your query with this line of code:
$query = \App\Models\SessionDetail::select("session_id", "SUM(points) as total_points")->whereIn("session_id", $ids)->get();
To get the template sales from that query, you have to use $query->template_sales;
If I got anything wrong, please tell me & I'll fix it ASAP
There is documentation available for all the operations in your query.
For selected columns use select('column1', 'column2', ...)
For selected aggregate columns use selectRaw('sum(column) as column')
For WHERE column IN (...) use whereIn('column', $array)
For subquery tables, use Closures or Builder classes (DB::table(fn($q) => ... , alias) or DB::table($builder, alias))
For UNION ALL use unionAll() with the same syntax as subquery tables.
Option 1: Closures
$ids = ["-Meagevy6y9ukbmFXvB7","-Meak6dG9iqvHWfAGQvy"];
$query = DB::table(function ($sub) use ($ids) {
$sub->select('session_id', 'spent_points as points')
->from('session_details')
->whereIn('session_id', [1,2])
->unionAll(function ($union) use ($ids) {
$union->select('session_id', 'price_points')
->from('template_sales')
->whereIn('session_id', $ids);
});
}), 't')
->select('session_id')
->selectRaw('sum(points) as total_points')
->groupBy('session_id')
->get();
Option 2: Builder (or translating the subqueries from the inside-out)
$ids = ["-Meagevy6y9ukbmFXvB7","-Meak6dG9iqvHWfAGQvy"];
$union = DB::table('template_sales')
->select('session_id', 'price_points')
->whereIn('session_id', $ids);
$sub = DB::table('session_details')
->select('session_id', 'spent_points as points')
->whereIn('session_id', $ids)
->unionAll($union);
$query = DB::table($sub, 't')
->select('session_id')
->selectRaw('sum(points) as total_points')
->groupBy('session_id')
->get();
Pick whichever you prefer. Both evaluate to the same query you posted.

getting all the data from pivot table in laravel

i'm trying to get all the lead_id inside my pivot table but i can't make it work.
controller:
$levels = Level::all();
$levels->lead()->attach('lead_id');
return $levels;
Model Level:
public function lead(){
return $this->belongsToMany(Lead::class, 'level_students')->withPivot('level_id', 'lead_id');
}
Model Lead:
public function level(){
return $this->belongsToMany(Level::class, 'level_students')->withPivot( 'lead_id', 'level_id');
}
If you mean all lead_id of a Level, then you can use pluck().
$level->lead->pluck('lead_id');
I'm not really sure what you are trying to achieve because it seems that you want to retrieve all lead_id associated with any Level. But if that is the case, then you can create a model for the pivot table (e.g. LevelLead) and use distinct() or with Query Builder:
$leadIds = DB::table('level_students')->select('lead_id')->distinct()->get();
If you want to get the referenced table's column (e.g. leads table's name column) then you can use JOIN. Check Laravel's doc for more options. For example, assuming the table name for Lead is leads, then:
$leads = DB::table('level_students')->join('leads', 'level_students.lead_id', '=', 'leads.lead_id')->select('level_students.lead_id', 'leads.name')->distinct()->get();

Why getQuery ignores soft deletes?

In Laravel, when I use getQuery function to modify my query result based on model, I'm getting all values including softdeleted. It literally forgets to include and stock.deleted_at is null in the query. Why? How can I make it filter out deleted records.
Model
class Stock extends Model
{
use SoftDeletes;
protected $dates = ['issue_date', 'expiry_date'];
...
Query (getting stock grouped by expiry_date)
$query = Stock::where('product_id', $id);
$query = $query->getQuery();
$query
->select(DB::raw(
'count(*) as total,
DATE_FORMAT(IFNULL(`expiry_date`, "0000-00-00"),"%d-%m-%Y") AS expiry_date '
))
->groupBy('expiry_date');
$result = $query->get();
I had an idea of not using getQuery(), but in this case 'issue_date' will give me an error message saying "laravel Data missing".
Use $query->toBase() instead of $query->getQuery().
$results = Stock::where('product_id', $id)->toBase()->selectRaw('
count(*) as total,
DATE_FORMAT(IFNULL(`expiry_date`, "0000-00-00"),"%d-%m-%Y") AS expiry_date
')->groupBy('expiry_date')->get();
The getQuery method simply returns the underlying query, whereas toBase first applies all global scopes (soft deletes is implemented as a global scope).
BTW, you can call select and groupBy directly on the Eloquent query itself:
$results = Stock::where('product_id', $id)->selectRaw('
count(*) as total,
DATE_FORMAT(IFNULL(`expiry_date`, "0000-00-00"),"%d-%m-%Y") AS expiry_date
')->groupBy('expiry_date')->get();
...though that would return partial Eloquent models, which is not always a great idea.

Select a table based on select result from another table

I have a table Registrationrequests where I have course_id and user_id and some other field.
$users_id = Registrationrequest::where('course_id', $query_course_user)->where('registered', 1)->get();
From the above query it gives me an array of result. But I need to take the details of these user_id from another table Users. I'm using Laravel. Table models are Registrationrequest and User
How can I get the user details from the above select result? I'm not that good in Joins. Any advice?
Use Eloquent's whereHas method:
$courseId = Request::get('course_id');
$users = User::whereHas('registrationRequests', function($query) use ($courseId)
{
$query->where('course_id', $courseId)->where('registered', 1);
});
This assumes you have set up the proper relationship in your User model. If not, add this method to your user model:
public function registrationRequests()
{
return $this->hasMany('Registrationrequest');
}

Zend selects all columns

In the following code:
$selectColumns= array('user_id.user_email', // inner join the data from user_id and user_details
'user_details.first_name',
'user_details.last_name');
$result = $handle->select()->from('user_id', $selectColumns)
->where('user_id.uid=?', $uid)
->join('user_details', 'user_id.uid = user_details.uid')
->query(ZEND_DB::FETCH_OBJ);
Zend selects all the columns in the table, not just the requested ones.
How can I select only some?
The problem is in your join() method call:
->join('user_details', 'user_id.uid = user_details.uid')
The optional third argument is columns from this table. If the argument is absent, it defaults to user_details.*.
Note that you added qualified columns from both tables in the from() table, but this has no effect on the default of user_details.*. Sorry, but Zend_Db_Select just isn't smart enough to keep track of all that.
You can make the join() call add no columns by passing an empty array:
->join('user_details', 'user_id.uid = user_details.uid', array())
The qualified columns you added in the from() call should still be there. To verify this yourself, print the SQL:
print $result . "\n"; // calls __toString() method on Zend_Db_Select object
Add another parameter to your join at the end -- an empty array. That will tell it to select no columns from the join. With the code you have now, you are selecting all columns from the joined table.
->join('user_details', 'user_id.uid = user_details.uid', array())

Categories