Model Category:
public function product()
{
return $this->hasMany(products::class);
}
Model product:
public function category()
{
return $this->belongsTo(Category::class);
}
I handle in controller:
$result = Category::select(['id', 'name'])
->with(['product:category_id, status'])
->where('order', 1)
->get();
Result when I print out raw data :
[
'id' => 1,
'name' => 'Hot'
'product' => [
'status' => 1,
'category_id' => 1
]
]
[
'id' => 2,
'name' => 'New'
'product' => [
'status' => 2,
'category_id' => 2
]
]
..........
I got the list of category id and name, and got the product data array based on relationship. In my product table, There is a status column with values equal to 1,2,3.
Now I want to count how many status = 1 and how many status = [2, 3] through the product array I get using that relationship?
you can use withCount for counting related data. lets say, you want total products, status1 products and status23 products.
$result = Category::select(['id', 'name'])
->with(['product:category_id, status'])
->withCount([
'product',
'product as status_one_product' => function ($query) {
$query->where('status', 1);
},
'product as status_other_product' => function ($query) {
$query->whereIn('status', [2, 3]);
}
])
->where('order', 1)
->get();
now you can get counted data like
echo $result[0]->product_count; // total product
echo $result[0]->status_one_product; // total product with status 1
echo $result[0]->status_other_product; // total product with status 2 and 3
Related
I have a small response from db model, and i colud rebase it and response in route, but i see error.
My Controller:
class PostController extends Controller {
public function getLastRecord() {
$lastRec = Post::latest('created_at')->first();
$res = [];
$res = collect($lastRec)->map(function($record) {
return [
'id' => $record->post_id,
'rec_name' => $record->post_name,
'user' => $record->user_id,
];
})->toArray();
return $res;
}
}
I want that response will be array
['id': 1, 'rec_name': 'test_name', 'user': 1]
instead names from db
['post_id': 1, 'post_name': 'test_name', 'user_id': 1]
Error:
Attempt to read property "post_id" on int
When you collect() a single Record, then call ->map() (or other iterative methods), it loops over your Model's columns, not multiple Post records. You can solve this by wrapping $lastRec in an array, or using ->get() instead of ->first():
$lastRec = Post::latest('created_at')->first();
return collect([$lastRec])->map(function($record) {
return [
'id' => $record->post_id,
'rec_name' => $record->post_name,
'user' => $record->user_id,
];
})->toArray();
// OR
$lastRecs = Post::latest('created_at')->get();
return $lastRecs->map(function ($record) {
return [
'id' => $record->post_id,
'rec_name' => $record->post_name,
'user' => $record->user_id,
];
})->toArray();
Or, since this is a single record (using ->first() only ever returns 1 record), you don't need to collect() or map() at all:
$lastRec = Post::latest('created_at')->first();
return [
'id' => $lastRec->post_id,
'rec_name' => $lastRec->post_name,
'user' => $lastRec->user_id
];
I sending an array of object of multiple products by Axios. Here is my confirmPurchases() method, by this method I'm sending an array to laravel controller.
confirmPurchases()
{
axios
.post(`/sells/sellProduct/`, this.bags)
.then( res => {
console.log(res.data);
} );
}
My sending array is looking like this
[
{ product_id: 1 , product_name: "product 1" , quantity: 1 },
{ product_id: 2 , product_name: "product 3" , quantity: 1 },
{ product_id: 3 , product_name: "product 2" , quantity: 1 }
]
When I was about to try to create multiple time by Eloquent Model by foreach , I get horrible errors
public function sellProduct(Request $request)
{
foreach( $request as $product ){
Sell::create([
'product_id' => $product->product_id,
'sell_price' => $product->sell_price,
'quantity' => $product->quantity
]);
}
}
Can you suggest me a good way to do this?
$request variable is not an actual array, so you can't iterate this trough foreach in php.
As, at-first $request need to make an array then do your business as your wish :)
public function sellProduct(Request $request)
{
$products = json_decode($request->getContent() , true);
foreach( $products as $product )
{
Sell::create([
'product_id' => $product['product_id'],
'sell_price' => $product['sell_price'],
'quantity' => $product['quantity']
]);
}
}
You are foreaching the request object instead of actuall array. What you could do:
Assuming your sending array matches the Seller attributes.
$data = request()->get('params');
$data = json_decode($data, true);
Seller::insert($data);
insert() its used to insert multiple eloquent data at one time
For example i have "id, name, wage, sex, age" columns.
1, John, 3, M, 30
2, Angela, 5, F, 26
If i have 50 rows like this. And if i want to save name, wage into table1 & sex and age into table2. In laravel docs queries/insert, they told us make an array and put values on it. But how should i put some of the values into table1 and other values into table2 in same foreach.
foreach($test as $tests)
{
$data[] =[
'name' => $tests->name,
'wage' => $tests->wage,
'sex' => $tests->sex,
'age' => $tests->age
];
}
Products::insert($data);
Is this the right ways to do it? I cant figure out the correct way to do.
If these tables are not related, you can do it with just 2 queries:
foreach ($tests as $test) {
$products[] = [
'name' => $tests->name,
'wage' => $tests->wage
];
$otherData[] = [
'sex' => $tests->sex,
'age' => $tests->age
];
}
Products::insert($products);
OtherModel::insert($otherData);
In case if these models are related, you'll need to create 51 query instead of 2 (still better than 100 queries):
foreach ($tests as $test) {
$productId = Products::insertGetId([
'name' => $tests->name,
'wage' => $tests->wage,
]);
$otherData[] = [
'sex' => $tests->sex,
'age' => $tests->age,
'product_id' => $productId
];
}
OtherModel::insert($otherData);
If these models are related and you still want to do this with just a few queries, you could use transactions:
DB::transaction(function () {
$productId = (int)DB::table('products')->orderBy('id', 'desc')->value('id');
foreach ($tests as $test) {
$productId++;
$products[] = [
'name' => $tests->name,
'wage' => $tests->wage
];
$otherData[] = [
'sex' => $tests->sex,
'age' => $tests->age,
'product_id' => $productId
];
}
Products::insert($products);
OtherModel::insert($otherData);
});
you could loop trough data and insert into DB table.
foreach($test as $tests)
{
$product = new Products();
$product->name = $tests->name;
$product->name = $tests->name;
$product->save();
$another = new AnotherTableModel();
$another->sex= $tests->sex;
$another->age= $tests->age;
$another->save();
}
CakePHP Version 3.5.5
My end goal is to provide the user the functionality to change the amount of results displayed via a select list on the index view. Also I need the initial page load to be sorted by area_name asc.
// WHAT I'VE DONE
I changed where I was stipulated the limit parameter which can be seen below.
// AREAS CONTROLLER
public $paginate = [
'sortWhitelist' => [
'Areas.area_name', 'Users.first_name', 'Users.last_name'
]
//'limit' => 1, // REMOVED FROM HERE
//'order' => [ // REMOVED FROM HERE
//'Areas.area_name' => 'asc'
//]
];
public function index()
{
$query = $this->Areas->find('all')
->contain([
'Users'
])
->where(['Areas.status' => 1]);
$limit = 1;
$this->paginate = [
'order' => ['Areas.area_name' => 'asc'], // ADDED HERE
'limit' => $limit // ADDED HERE
];
$this->set('areas', $this->paginate($query));
}
And I declare the pagination sort links like:
// AREAS INDEX VIEW
<?= $this->Paginator->sort('Areas.area_name', __('Area Name')) ?>
<?= $this->Paginator->sort('Users.first_name', __('First Name')) ?>
<?= $this->Paginator->sort('Users.last_name', __('Last Name')) ?>
// RESULT
The above code works on all index methods within the application that don't use contain but when I implemented this solution here everything worked except I cannot sort on the associated data - IE: Users first and last name?
=========================================================================
WHAT I'VE TRIED
// Attempt 1
I added an initialize method above the public $paginate class like:
public function initialize()
{
$limit = 1;
}
public $paginate = [
'sortWhitelist' => [
'Areas.area_name', 'Users.first_name', 'Users.last_name'
]
'limit' => $limit,
'order' => [
'Areas.area_name' => 'asc'
]
];
public function index()
{
$query = $this->Areas->find('all')
->contain([
'Users'
])
->where(['Areas.status' => 1]);
$this->set('areas', $this->paginate($query));
}
And the view I left the same.
// Result for Attempt 1
syntax error, unexpected ''limit'' (T_CONSTANT_ENCAPSED_STRING), expecting ']' on line 36 which is 'limit' => $limit,
=========================================================================
// Attempt 2
I tried to add the limit parameter and order array to the query like:
public function index()
{
$limit = 1;
$query = $this->Areas->find('all')
->contain([
'Users'
])
->where(['Areas.status' => 1])
->order(['Areas.area_name' => 'asc'])
->limit($limit);
$this->set('areas', $this->paginate($query));
}
// Result for Attempt 2
The result set was not ordered by the area_name and not limited to 1 result.
=========================================================================
// Attempt 3
I then changed the query and tried the following just to see if I could get a dynamic limit working:
$limit = 1;
$query = $this->Areas->find('all')
->contain('Users', function ($q) {
return $q
//->order('Areas.area_name' => 'asc'),
->limit($limit);
})
->where(['Areas.status' => 1]);
$this->set('areas', $this->paginate($query));
// Result for Attempt 3
The result set was not limited to 1 result.
=========================================================================
ADDITIONAL INFORMATION
// USERS TABLE
$this->hasOne('Areas', [
'foreignKey' => 'user_id'
]);
// AREAS TABLE
$this->belongsTo('Users', [
'foreignKey' => 'user_id',
'joinType' => 'INNER'
]);
I searched through the following cookbook sections (Pagination, Query Builder, Retrieving Data & Result Sets and Associations - Linking Tables Together) but I can't find a way to get this working so any help would be much appreciated.
Many thanks. Z.
You are overwriting the $paginate property in your index() method, so your settings including the whitelist are being lost.
Set the keys directly instead:
$this->paginate['order'] = ['Areas.area_name' => 'asc'];
$this->paginate['limit'] = $limit;
This is my action:
public function index()
{
$this->paginate = [
'page' => 1,
'limit' => 12,
'maxLimit' => 12
];
$suppliers =$this->Suppliers->find('all')
->order(['Suppliers.description'=>'asc']);
$suppliers = $this->paginate($suppliers);
$this->set(compact('suppliers'));
$this->set('_serialize', ['suppliers']);
}
No matters value I put on limit, max limit.. he always give me all record from my database...