I am working with Laravel 5.6 with MySql database in My web app.
and I have following function method to add order,
public function addOrder()
{
$input = Input::all();
$subscribed= false;
if(isset($input['subscribed']))
{
$subscribed= true;
}
and In My system I have table name as vehicles as following,
**vehicles table**
id name number adtype
1 car 123 0
2 van 159 0
3 car 258 0
4 lorry 147 0
5 van 298 0
etc..
Now I need update above table adtype values from 0 to 1 when click submit button regarding to above addorder function. then how can write code to update code in side above function????
My url as following....
http://localhost:8000/myads/1/edit/payment
route is,
Route::post('add-order', 'PaymentController#addOrder');
If you are using a model then try the following code:
public function addOrder()
{
$input = Input::all();
$subscribed= false;
if(isset($input['subscribed'])){
$subscribed= true;
}
$vehicle= App\Vehicles::find($input[id]);
$vehicle->adtype = $subscribed;
$vehicle->save();
}
If you are using Query Builder (add use DB;)
public function addOrder()
{
$input = Input::all();
$subscribed= false;
if(isset($input['subscribed'])){
$subscribed= true;
}
DB::table('vehicles')
->where('id', $input[id])
->update(['adtype' => $subscribed]);
}
You must pass the id of a table row to edit each of them(this is must for any method).
Related
I have case sum of data
actual result: return 0
Expected result not return 0.
I have table like
Transaction
id
user_id
amount_load
status
1f
3edf
100000
1
Log Transaction
id
trx_id
amount_pay
status
32f
1f
10000
1
23d
1f
50000
1
12e
1f
1000
3
info about status:
ID
Meaning
0
not paid
1
paid not full
2
paided
3
refunded
My code on controller
$data = Transaction::select('user_id')->groupBy(‘user_id’)
->with([LogTransaction => function ($query) {
$query->sumRefund();
}]);
Model Transaction.php
public function scopeSelectDefault($q) {
return $q->selectRaw(‘id, user_id, amount_load, status’);
}
//RELATION
public function logTransaction()
{
return $this->hasMany('App\Models\LogTransaction', 'trx_id', 'id');
}
Model LogTransaction.php
public function scopeSumRefund($q) {
return $q->selectRaw(‘coalesce(SUM(amount_pay) FILTER (WHERE status = '3'),0) AS total_refund’);
}
// RELATION
public function transaction($query, $order)
{
return $this->belongsTo('App\Models\Transaction', 'id');
}
expected result: total_refund on relation resulting 1000 base status = 3
other information:
laravel ^6.0
postgres 12.0
please help
Firstly you can use the Laravel custom attribute option and you can define it in your Transactions Model like so
public function getTotalRefundAttribute() {
return $this->logTransaction ? $this->logTransaction->where('status', 3)->sum('amount_pay') : null;
}
And now when you get any Transaction instance it will have an extra attribute called total_refund where you can see the total amount. But make sure you actually have eloquent relations setup between Transaction and LogTransactions models
Hi i'm just started to learn laravel and i have 2 database tables that i want to modify, the first one is the main table which is products and the other table is upsells which will connect two entity from products table:
products
id
name
price
1
Bag
300
2
Belt
100
3
ring
120
4
Hat
250
5
Scarf
125
upsells
id
product_id_1
product_id_2
1
2
1
2
2
4
3
2
5
4
5
4
5
5
1
the idea is product enitty can be connected to the one or more product using the upsells table. the product_id_1 will be the main product that will point to the product_id_2
Currently i'm using this method to retrieve the relationship:
public function getUpsells($mainProductId){
$upsells = Upsell::where('product_id_1', $mainProductId);
$results = array();
foreach($upsells as $upsell){
$results[] = $upsell->product_id_2;
}
return $results;
}
$mainProductId = 5;
$relatedProducts = array(2,3);
public function updateUpsells($mainProductId,$relatedProducts){
foreach($relatedProducts as $relatedProduct){
//create if not exists
$upsell = Upsell::where('product_id_1', $mainProductId)->
where('product_id_2', $relatedProduct)->first();
if(empty($upsell->id)){
$upsell = new Upsell;
$upsell->product_id_1 = $mainProductId;
$upsell->product_id_2 = $relatedProduct;
}
}
//delete if not in the array input
Upsell::where('product_id_1', $mainProductId)->
whereNotIn('product_id_2', $relatedProducts)->delete();
}
Is there any simplified method or any method that i'm missing based on laravel best practice ?
You can use eloquent relationships. Based on your code I think you have these relationships between your models:
Products hasMany upSells,
so in your Products.php you will have to add relation like this:
public function upSells(){
return $this->hasMany(UpSells::class, 'product_id_1', 'id');
}
This way you can fetch upsells from products like this:
$products = Product::with('upSells')->find(1);
The same thing you can do with your other relationships. You just have to define which will be the parent and which will be the child in the relationship.
For more information, you can go through this.
CURRENT SOLUTION WHICH IS NOT RECOMMENDED
public function getUpsells($mainProductId)
{
return Upsell::where('product_id_1', $mainProductId)->pluck('product_id_2'); //This will give you array of product_id_2.
}
$mainProductId = 5;
$relatedProducts = [2, 3];
public function updateUpsells($mainProductId, $relatedProducts)
{
Upsell::where('product_id_1', $mainProductId)->delete();
foreach($relatedProducts as $relatedProduct){
$upsells = [
[
'product_id_1' => $mainProductId,
'product_id_2' => $relatedProduct
]
];
}
Upsell::insert($upsells);
}
RECOMMENDED SOLUTION
Important docs,
https://laravel.com/docs/8.x/eloquent-relationships
https://laravel.com/docs/8.x/migrations
You have to make a relation in the product model make migration of pivot table.
public function upsells()
{
return $this->hasMany(Upsell::class, 'product_id_1', 'id')
}
then getUpsells() and updateUpsells() be like,
public function getUpsells($mainProductId)
{
$products = Product::with('upsells')->findOrFail($mainProductId);
return $products->upsells->product_id_2;
}
$mainProductId = 5;
$relatedProducts = [2, 3];
public function updateUpsells($mainProductId, $relatedProducts)
{
$product = Product::findOrFail($mainProductId);
$product->upsells()->sync($relatedProducts);
}
I have a form. Type field is a drop-down and has only two possible values. Second field is bcode.
E.g.
if table has data like-
ID TYPE BCODE
1 1 2
2 1 3
3 2 2
4 1 4
5 2 2
Now I am making a popup form to insert record in this table. So if type is entered 1 and bcode is entered 2,3 or 4 its already in table so it will be invalid but any other numeric value will be valid. Similarly if type is entered 2 then bcode can't be anything other than 2,3 or 4. All other values will be invalid.
I read the Laravel docs here-
https://laravel.com/docs/6.x/validation#custom-validation-rules
But did not find anything.
Anyone tried something similar?
Assuming your table structure is like in your example and its called type_bcode, I'm offering the following solution:
Create custom rule by running php artisan make:rule TypeBcode
It should look like this:
private $type;
public function __construct($type)
{
$this->type = $type;
}
public function passes($attribute, $value)
{
$type_bcode = DB::table('type_bcode')
->where('type', $this->type)
->get()
->pluck('bcode')
->toArray();
return in_array($value, $type_bcode);
}
public function message()
{
return 'The validation error message.';
}
In your controllers store function do this:
public function store(Request $request)
{
$validator = Validator::make($request->all(), [
'type' => 'required',
'bcode' => ['required', new TypeBcode($request->type)],
]);
if ($validator->fails()) {
//some action
}
//some action
}
Hope this will help
Laravel 5.7. I have 2 Eloquent models: Owner, Cat.
Owner model:
public function cats()
{
return $this->belongsToMany('App\Cat')->withPivot('borrowed');
}
Cat model:
public function owners()
{
return $this->belongsToMany('App\Owner')->withPivot('borrowed');
}
The cat_owner pivot table has these fields:
id | cat_id | owner_id | borrowed
---------------------------------
1 | 3 | 2 | 1
I want my API to return a list of all cats, and if the logged-in user has borrowed this cat, I want the borrowed field to be set to true. This is what I have so far:
Controller:
public function index()
{
return CatResource::collection(Cat::all());
}
CatResource:
public function toArray()
{
$data = ['id' => $this->id, 'borrowed' => false];
$owner = auth()->user();
$ownerCat = $owner->cats()->where('cat_id', $this->id)->first();
if ($ownerCat) {
$data['borrowed'] = $ownerCat->pivot->borrowed == 1 ? true : false;
}
return $data;
}
This works, but it seems wasteful to request the $owner for every cat, e.g. if there's 5000 cats in the database. Is there a more efficient way to do this? I can think of 2 possible ways:
Pass the $owner to the CatResource (requires overriding existing collection resource).
Get this information in the controller first, before passing to the CatResource.
I prefer the second way, but can't see how to do it.
Try Conditional Relationship.
public function toArray($request)
{
return [
'id' => $this->id,
'borrowed' => false,
'borrowed' => $this->whenPivotLoaded('cat_owner', function () {
return $this->owner_id === auth()->id() && $this->pivot->borrowed == 1 ? true : false;
})
];
}
then call return CatResource::collection(Cat::with('owners')->get());
You are right, this does a lot of extra loading. I think you are running into the limitation that you can't know which record form cat_owner you want until you know both the records you're using from the cat and owner table.
For anyone still interested, my solution would be to make a resource that gives you just the pivot values
Since the following returns a collection you canNOT go to the pivot table on it:
/*
* returns a collection
*/
$data['borrowed'] = $this->owners
/*
* So this doesNOT work. Since you can’t get the pivot
* data on a collection, only on a single record
*/
$data['borrowed'] = $this->owners->pivot
You should receive the collection and then you can read the pivot data in the Resource of the owner Record. If this resource is only for the pivot data I would call it something like attributes.
create a new resourse for the attributes, something like:
class CatOwnerAttributeResource extends JsonResource
{
public function toArray($request)
{
return [
'borrowed' => $this->pivot->borrowed,
];
}
}
Then receive the collection like so:
$data = ['id' => $this->id, 'borrowed' => false];
/*
* Get the collection of attributes and grab the first (and only) record.
* NOTE: the filtering is done in the collection, not in the DBM. If there
* is a possibility that the collection of owners who own this cat gets really
* big this is not the way to go!
*/
if ($attributes =
CatOwnerAttributeResource::collection(
$this->owner
->where(‘id’ = $auth->user()->id)
->first()
) {
$data[‘borrowed’] = $attributes->borrowed == 1 ? true : false;
}
return $data;
Couldn’t run this code so please point errors out if you try it and it gives you any, I will adjust.
I have the following tables:
User:
userID
...
Lesson:
lessonID
...
Users_Lessons_Status (which acts as a pivot table and holds other information):
userID references User.userID
lessonID references Lessons.lessonID
latestSectionID
percentComplete
What I want to do is, for each user, for each lesson, there should be a row in the pivot table that tells how much the user has completed in that lesson and what their latest section ID was. That is, there should be a unique pair with userID and lessonID (primary keys?).
I have set up my models like so:
<?php
class User extends Eloquent implements UserInterface, RemindableInterface {
...
public function lessonStatuses()
{
return $this->belongsToMany('Lesson', 'users_lessons_status', 'lessonID', 'userID')->withPivot('latestSectionID', 'percentComplete');
}
}
<?
class Lesson extends Eloquent {
protected $table = 'lessons';
protected $primaryKey = 'lessonID';
public function userStatuses()
{
return $this->belongsToMany('User', 'users_lessons_status', 'userID', 'lessonID');
}
}
?>
My current route looks like this:
Route::post('dbm/users/setLatestSectionID', function() {
if(Auth::check()) {
$user = User::find(Input::get('userID'));
$lesson = Lesson::find(Input::get('lessonID'));
$us = $user->lessonStatuses();
$us->attach($lesson->lessonID,
["latestSectionID" => Input::get('latestSectionID'), "percentComplete" => Input::get('percentComplete')] );
}
});
This works, however, it creates a new row every time I update it for the same userID and lessonID, so the pair is no longer unique. Which methods should I use for this purpose? I tried both save(), attach() and push() in the documentation but I'm not sure which one to use here.
Edit: to clarify, the resulting table should look something like this:
id|userID|lessonID|latestSectionID|percentComplete
1 1 1 X Y
2 1 2
3 1 3
4 2 1
5 3 1
6 3 2
....
Edit 2: Fixed the User->belongsToMany() method and added the withPivot call.
It seems like a bug, nevertheless you can do this:
...->sync([$id], false); // detaching set to false, so it will only insert new rows, skip existing and won't detach anything
edit:
As said in comment - it will not work for you, as you want to set pivot data.
So basically there is no method to do this at the moment, but something like this should do:
// belongsToMany.php
public function attachOrUpdate($id, array $attributes = array(), $touch = true)
{
if ($id instanceof Model) $id = $id->getKey();
if ( ! $this->allRelatedIds()->contains($id)) // getRelatedIds() in prior to v5.4
{
return $this->attach($id, $attributes, $touch);
}
else if ( ! empty($attributes))
{
return $this->updateExistingPivot($id, $attributes, $touch);
}
}
I'm gonna test it and if it passes, send a pull request to 4.1
I faced this recently and fixed it in this way:
Use updateExistingPivot first and check the result , if result is 1 it means there were row with the same userID and lessonID and it's been updated successfully, otherwise, if result is 0 it means there were no rows with this userID and lessonID, so you can attach it in order to create new row
$update_result = $us->updateExistingPivot($lesson->lessonID,
["latestSectionID" => Input::get('latestSectionID'), "percentComplete" => Input::get('percentComplete')] );
if($update_result == 0) {
$us->attach($lesson->lessonID,
["latestSectionID" => Input::get('latestSectionID'), "percentComplete" => Input::get('percentComplete')] );
}
You should be using updateExistingPivot().
Update your code to use
$us->updateExistingPivot($lesson->lessonID,
["latestSectionID" => Input::get('latestSectionID'), "percentComplete" => Input::get('percentComplete')], true );
The last parameter will update the timestamps for all related models. If not, you can remove or set to false.
If you want to attach only when a record doesn't exist, you could do something like this...
Route::post('dbm/users/setLatestSectionID', function() {
if(Auth::check()) {
$user = User::find(Input::get('userID'));
$lesson = [
"latestSectionID" => Input::get('latestSectionID'),
"percentComplete" => Input::get('percentComplete')
];
$num_lessons = $user->lessonStatuses()->where('id', Input::get('lessonID'))->count();
if($num_lessons == 0) {
$user->attach($lesson->lessonID, $lesson);
} else {
$user->updateExistingPivot($lesson->lessonID, $lesson);
}
}
});