Laravel: query a model with count - php

how can query in laravel with model method ?
i have a counter method in city model and i want to use this in my select query in response
how can i write this ?
my City model
public function mobile()
{
return $this->hasMany(Mobile::class);
}
public function mobile_count()
{
return $this->mobile()->count();
}
my query
public function findCityWithID($id)
{
$subgroup = City::select('id', 'name', 'state_id')->where('state_id', $id)->orderBy('name')->get();
return response()->json($subgroup);
}
i want have in $subgroup each City mobile counts

The Model:
public function mobiles()
{
return $this->hasMany(Mobile::class);
}
The Query:
$cities = City::withCount('mobiles')->where('state_id', $id)->get();
$response[];
foreach ($cities as $city) {
response[
'id' => $city->id;
'name' => $city->state;
'state_id' => $city->state_id;
'mobile_count' => $city->mobile_count;
];
}
return response()->json($response);

Related

Laravel Eloquent map in query

I have a problem with mapping objects in a Laravel eloquent query.
How to map relations in a query builder.
How to connect two separate collections.
For example. Having models:
class CartProduct extends Model
{
protected $fillable = [
'quantity',
'cart_id',
'product_id',
'unit_price',
'product_code'
];
function product(){
return $this->belongsTo(Product::class);
}
function cart(){
return $this->belongsTo(Cart::class);
}
}
class Cart extends Model
{
function productsInCart()
{
return $this->hasMany(CartProduct::class);
}
public function products()
{
return $this->belongsToMany(
Product::class,
'cart_products',
'cart_id',
"product_id");
}
}
class Product extends Model
{
protected $fillable = [
'name',
'code',
'description',
'price',
];
}
The tasks are:
Get a set of products that are in the same cart (doesn't matter which one) as $product_id (excluding $product_id)
Get a set of products that were in any cart together with $product_id (excluding $product_id, without duplications)
I would solve it like this:
1.
public function task_one($product_id)
{
return $products = CartProduct::where('product_id', $product_id)->first()->cart->products
->filter(function (Product $p) use ($product_id) {
return $p->id !== $product_id;
});
}
public function task_two($product_id)
{
$cartProducts = CartProduct::where('product_id', $product_id)->get();
$products = collect(new Product);
foreach ($cartProducts as $cartProduct) {
$productsInCart = $cartProduct->cart->products
->filter(function (Product $p) use ($product_id) {
return $p->id !== $product_id;
});
$products = $products->merge($productsInCart);
}
return $products->unique();
}
However, the 2nd function seems to be awful. How can I do this properly, to achieve fast execution and a good style of code?
Is there any method to "map" the whole collection to related model objects? For example by
$carts = CartProduct::getByProductId($product_id)->"mapByRelationship('cart)";
//The result should be a collection od Carts
$products = CartProduct::getByProductId($product_id)->"mapByRelationship('cart)"->"mapByRelationship('products')"->unique();
//The result should be the same as task_two($product_id);
Thank you in advance
I think I have done this Controller-Model Relationship.
Controller:
class MakeAWishController extends Controller
{
public function getMakeAWishes(Request $request)
{
$limit = (int) ($request->limit ?? 1);
$offset = (int) ($limit * (($request->page ?? 1) - 1));
$wishes = MakeAWish::with('product')
->offset($offset)->limit($limit)->where('product_quantity', '>' , '0')->get()
->map(function ($wish) {
$wish->children_image = asset(Storage::url($wish->children_image));
if(!empty($variant = $wish->product->variant())) {
$wish->product->variant_id = $variant->variant_id;
$wish->product->variant_price = $variant->variant_price ?? "0.00";
$wish->product->variant_compare_at_price = $variant->variant_compare_at_price ?? "0.00";
}
return $wish;
});
$response = [
'status' => 200,
'data' => $wishes
];
return response()->json($response);
}
}
Model:
class MakeAWish extends Model
{
protected $collection = 'make_a_wishes';
protected $fillable = [
'children_name',
'children_name_for_isis',
'age',
'country',
'children_image',
'product_id',
'quantity'
];
protected $casts = [
'product_id' => 'string'
];
public function product()
{
return $this->hasOne(Product::class, 'product_id', 'product_id');
}
public function orders()
{
return $this->hasMany(OrderHistory::class, 'type_id', '_id');
}
public function orderCount()
{
return $this->orders()->where('type', 'M')->count();
}
}

Property [id] does not exist on the Eloquent builder instance in Laravel 8 and Livewire 2.7

My users can create multiple usercar's when selecting from a database of car's. I need to grab the selected car values, but when I dd the values, I get a Property [id] does not exist on the Eloquent builder instance. error. wire:model="car_id" is the select input value used in the code below.
AddUserCar.php
...
class AddUserCar extends Component
{
public $showAnotherModel = false;
// Steps
public $totalSteps = 8;
public $step = 1;
// User
public $super;
public $first_name;
public $last_name;
public $email;
public $status = 1;
public $role = 'Driver';
// Usercar
public $car_id;
public $calc_date;
public $year;
public $model;
// Form Function
public $car_year;
//public $cars;
//public $modelId;
...
public function moveAhead()
{
if($this->step == 1) {
$newCar = Car::where('id', '=', $this->car_id)->get();
dd($newCar->id); // This is where I get error
$this->usercarCreated = Usercar::create([
'year' => $newCar->start_year,
'model' => $newCar->model,
'car_id' => $this->car_id,
'user_id' => Auth::user()->id,
'tenant_id' => Auth::user()->tenant_id,
'calc_date' => now()->format('m-d-Y'),
]);
$this->resetErrorBag();
$this->resetValidation();
}
...
public function render()
{
return view('livewire.add-user-car',
['pageTitle' => 'Add Driver Car']);
}
}
Use ->get() to retrieving all rows from a table :
$cars = Car::where('id', '=', $this->car_id)->get();
foreach($cars as $car){
echo $car->id;
}
// ERROR, because $cars isn't a single row
dd($cars->id);
Use ->first() to retrieving a single row / column from a table.
$car = Car::where('id', '=', $this->car_id)->first();
// or
$car = Car::find($this->car_id);
// WORK
dd($car->id);
$newCar = Car::where('id', '=', $this->car_id)->get();
This statement does not find any data, so $newcar is empty, and an empty object has no ID

Laravel find() does not get data from the DB

I have a resource Controller with this index method like this:
public function index()
{
$args = [];
$args = array_merge($args, $this->data_creator(35, 12, 'book'));
$args = array_merge($args, $this->data_creator(37, 12, 'kit'));
$args = array_merge($args, $this->data_creator(38, 12, 'game'));
$args['menu_links'] = [
'books' => route('shopping-products.category', Category::find(25)->slug),
'videos' => route('shopping-products.category', Category::find(24)->slug),
'kits' => route('shopping-products.category', Category::find(23)->slug),
'games' => route('shopping-products.category', Category::find(22)->slug),
];
return view('frontend.shop.products.index', $args);
}
But it returns this error:
Trying to get property 'slug' of non-object
And when I dd(Category::find(25), Category::find(24), Category::find(23), Category::find(22)); I get NULL results.
Meaning that it can not find data with specified ids.
However there are 25 records stored at the categories table:
So what is going wrong here? How can I fix this issue?
I would really appreciate any idea or suggestion from you guys...
Thanks in advance.
Here is Category.php Model:
class Category extends Model
{
use Sluggable, SoftDeletes;
protected $table = 'categories';
protected $primaryKey = 'cat_id';
protected $guarded = [];
/**
* Return the sluggable configuration array for this model.
*
* #return array
*/
public function sluggable()
{
return [
'slug' => [
'source' => 'cat_name'
]
];
}
public function path()
{
return "/products/categories/$this->slug";
}
public function children()
{
return $this->hasMany(Category::class, 'cat_parent_id', 'cat_id');
}
public function parents()
{
return $this->hasMany(Category::class, 'cat_id', 'cat_parent_id');
}
public function products()
{
return $this->belongsToMany(Product::class, 'category_products', 'ctp_cat_id', 'ctp_prd_id');
}
public function news()
{
return $this->belongsToMany(News::class, 'category_news', 'ctn_cat_id', 'ctn_nws_id');
}
public function galleries()
{
return $this->belongsToMany(Gallery::class, 'category_galleries', 'ctg_cat_id', 'ctg_gly_id');
}
public function uploaded()
{
return $this->hasMany(UploadedFile::class, 'upf_object_id', 'cat_id')->where('upf_object_type_id', '=', '107');
}
public function articles()
{
return $this->belongsToMany(Article::class, 'article_category', 'act_cat_id', 'act_art_id');
}
public function olympiadExam()
{
return $this->belongsToMany(OlympiadExam::class, 'olympiads_exams_categories', 'oec_ole_id', 'oec_cat_id');
}
public function olympiadExamQuestion()
{
return $this->belongsToMany(OlympiadExamQuestion::class, 'olympiads_exams_questions_categories', 'oes_cat_id', 'oes_oeq_id')->orderBy('oeq_number', 'asc');
}
public function attr_attributes()
{
return $this->hasMany(CategoryAttribute::class, 'category_id', 'cat_id');
} //
public function attr_product()
{
return $this->hasMany(Product::class, 'prd_cat_att_id', 'cat_id');
} //
public function couponRelation()
{
return $this->hasMany(couponRelation::class, 'object_id', 'cat_id')->where('object_type', 'product_category');
}
public function magazines()
{
return $this->belongsToMany(Magazine::class, 'category_magazine', 'category_id', 'magazine_id');
}
}
And when I do: dd(Category::where('cat_id', 25), Category::where('cat_id', 24), Category::where('cat_id', 23), Category::where('cat_id', 22)); I get this as result:
The problem is because you are using SoftDeletes so soft deleted models will automatically be excluded from query results. In your case, look like Category with id 22, 23, 24, 25 are soft deleted. To get it, you need to use withTrashed() as mentioned in the doc. For example:
Category::withTrashed()->find(22)->slug
per an answer above: if you are using soft deletes you need to add
Category::withTrashed()
However, you can wrap the command in an optional() helper function.
optional(Category::find(22))->slug
// if you are using soft delete
optional( Category::withTrashed()->find(22) )->slug
this will return null if 22 does not exist instead of throwing an exception error.

How to use insert_batch to insert data in db

how to use insert_batch to add multiple data in database by using for loop please help me as i am very new to codeigniter.
My controller
class Student extends CI_Controller {
public function _construct()
{
parent::_construct();
//call model
$this->load->model("StudentModel","m");
}
function index()
{
$this->load->view("index");
}
function savedata()
{
$data = array(
array(
'studentname' => 'Reddy' ,
'gender' => 'Male' ,
'phone' => '456879'
),
array(
'studentname' => 'Yalla' ,
'gender' => 'Female' ,
'phone' => '12345678'
)
);
//mean that insert into database table name tblstudent
$this->db->insert_batch('tblstudent',$data);
//mean that when insert already it will go to page index
redirect("Student/index");
}
function edit($id)
{
$row=$this->m->getonerow($id);
$data['r']=$row;
$this->load->view('edit',$data);
}
function update($id)
{
$id=$this->input->post('id');
$data=array(
'studentname' => $this->input->post('studentname'),
'gender' => $this->input->post('gender'),
'phone' => $this->input->post('phone')
);
$this->db->where('id',$id);
$this->db->update('tblstudent',$data);
redirect("Student/index");
}
function delete($id)
{
$id=$this->db->where('id',$id);
$this->db->delete('tblstudent');
redirect("Student/index");
}
}
Model
class StudentModel extends CI_Model{
function _construct()
{
parent::_construct();
}
function gettable()
{
$query=$this->db->get('tblstudent');
return $query->result();
}
function getonerow($id)
{
$this->db->where('id',$id);
$query = $this->db->get('tblstudent');
return $query->row();
}
}
First of all you don't have to add direct access to database in controller. For all database access code you have to create model.
in your above code you added database access code in direct controller,which is logically wrong as per MVC architecture.
Below is code as per MVC and all database access code resides in Model.
Your main question for batch insert is in function insert()
of model.Please go through it.
<?php
class Student extends CI_Controller {
public function _construct()
{
parent::_construct();
//call model
$this->load->model("StudentModel","m");
}
function index()
{
$this->load->view("index");
}
function savedata()
{
$stdarray = array();
$stdarray[] = array('studentname' => 'Reddy' ,'gender' => 'Male' ,'phone' => '456879');
$stdarray[] = array('studentname' => 'Yalla' ,'gender' => 'Female' ,'phone' => '12345678');
//mean that insert into database table name tblstudent
$this->db->insert_batch('tblstudent',$data);
$this->m->insert($stdarray);
//mean that when insert already it will go to page index
redirect("Student/index");
}
function edit($id)
{
$row=$this->m->getonerow($id);
$data['r']=$row;
$this->load->view('edit',$data);
}
function update($id)
{
$updateArray = array();
$updateArray['studentname'] = $this->input->post('studentname');
$updateArray['gender'] = $this->input->post('gender');
$updateArray['phone'] = $this->input->post('phone');
$whereArray = array();
$whereArray['id'] = $id;
$this->m->updateRow($updateArray,$whereArray);
redirect("Student/index");
}
function delete($id)
{
$whereArray = array();
$whereArray['id'] = $id;
$this->m->deleteRow($whereArray);
redirect("Student/index");
}
}
?>
Model:
class StudentModel extends CI_Model{
function _construct()
{
parent::_construct();
}
function gettable()
{
$query=$this->db->get('tblstudent');
return $query->result();
}
function getonerow($id)
{
$this->db->where('id',$id);
$query = $this->db->get('tblstudent');
return $query->row();
}
function insert($insrtArray)
{
$success = $this->db->insert_batch('tblstudent', $insrtArray);
}
function updateRow($updateArray,$whereArray)
{
if(!empty($whereArray))
{
foreach ($whereArray as $key => $value) {
$this->db->where($key,$value);
}
}
$this->db->update('tblstudent',$updateArray);
}
function deleteRow($whereArray)
{
if(!empty($whereArray))
{
foreach ($whereArray as $key => $value) {
$this->db->where($key,$value);
}
}
$this->db->delete('tblstudent');
}
}
?>
Important: morever you have to use escape function for all inputa which are direct send to database for maintain security from SQL injection.

How to avoid ambiguous field while reusing query shorthand in Yii2?

I have table like below.
CREATE TABLE A (
id INT,
relationId INT,
status INT
)
CREATE TABLE B (
id INT,
status INT
)
The class file is like below
class A extends \yii\db\ActiveRecord {
public function getB() {
return $this->hasOne(B::class, ['id' => 'relationId']);
}
public function find() {
return new AQuery(__CLASS__);
}
}
class AQuery extends \yii\db\Query {
public function isActive() {
return $this->andWhere(['status' => 1]);
}
public function isNotActive() {
return $this->andWhere(['status' => 0]);
}
}
class B extends \yii\db\ActiveRecord {
public function find() {
return new BQuery(__CLASS__);
}
}
class BQuery extends \yii\db\Query {
public function isActive() {
return $this->andWhere(['status' => 1]);
}
public function isNotActive() {
return $this->andWhere(['status' => 0]);
}
}
I'm doing something like this
$model = A::find()
->joinWith([
'b' => function(BQuery $query) {
$query->isNotActive();
}
])
->isActive()
->one();
This will produce error
Column 'status' in where clause is ambiguous"
The only way I know is to manually add alias to $query->from and rewrite the $query->andWhere. But is there any easier way to reuse the query shorthand?
Use ActiveRecord::tableName() instead of aliasing (which doesn't seem to be an active record feature in Yii2). The tableName() can be accessed through the modelClass property of \yii\db\ActiveQuery.
public function isActive() {
$modelClass = $this->modelClass;
return $this->andWhere([$modelClass::tableName().'.status' => 1]);
}
You can enhance your isActive() method to accept aliases with an optionnal parameter. You can try something like this:
class AQuery extends \yii\db\Query {
protected function getAlias($alias = null) {
return $alias !== null ? $alias : A::tableName();
}
public function isActive($alias = null) {
$alias = $this->getAlias($alias);
return $this->andWhere(["{$alias}.status" => 1]);
}
public function isNotActive($alias = null) {
$alias = $this->getAlias($alias);
return $this->andWhere(["{$alias}.status" => 0]);
}
}

Categories