Problem with passing id via GET in Laravel - laravel

Laravel framework 6.9 + XAMP
I need advise from someone with experience in Laravel as I have some strange issue I cannot explain.
Blade template has a button that should add an item to the cart via product id:
<div class="buy d-flex justify-content-between align-items-center">
<div class="price text-success"><h5 class="mt-4">$ {{$product->price}}</h5></div>
<i class="fas fa-shopping-cart"></i> Add to Cart
</div>
However nothing happens when the button is clicked. No product id is passed, just #.
This is web.php route that I call:
Route::get('add-to-cart/{id}', [
'uses' => 'ProductController#getAddToCart',
'as' => 'product.addToCart'
]);
Also tried:
//Route::get('add-to-cart/{id}', 'ProductController#getAddToCart')->name('product.addToCart');
Which also doesn't work.
This is Cart model:
<?php
namespace App;
class Cart
{
public $items = null;
public $totalQty = 0;
public $totalPrice = 0;
public function __construct($oldCart)
{
if ($oldCart) {
$this->items = $oldCart->items;
$this->totalQty = $oldCart->totalQty;
$this->totalPrice = $oldCart->totalPrice;
}
}
public function add($item, $id) {
$storedItem = ['qty' => 0, 'price' => $item->price, 'item'=> $item];
if ($this->items) {
if (array_key_exists($id, $this->items)) {
$storedItem = $this->items[$id];
}
}
$storedItem['qty']++;
$storedItem['price'] = $item->price * $storedItem['qty'];
$this->items[$id] = $storedItem;
$this->totalQty++;
$this->totalPrice += $item->price;
}
}
This is Product controller:
namespace App\Http\Controllers;
use App\Product;
use Illuminate\Http\Request;
use App\Cart;
use Session;
class ProductController extends Controller
{
public function index()
{
$products = Product::all();
return view('shop.index', ['products' => $products]);
}
public function getAddToCart(Request $request, $id) {
$product = Product::find($id);
$oldCart = Session::has('cart') ? Session::get('cart') : null;
$cart = new Cart($oldCart);
$cart->add($product, $product->id);
$request->session()->put('cart', $cart);
//dd($request->session()->get('cart'));
return redirect()->route('index');
}
}
If I just pass in URL: /add-to-cart/{prod id} and Enter, it works - I get to see dd() of the 'cart' with the product details, so the route works. Only the button doesn't!
Drives me nuts. What am I doing wrong? Is there some 'feature' in Laravel I don't know about?
dd($product)
App\Product {#279 ▼
#fillable: array:3 [▼
0 => "title"
1 => "description"
2 => "price"
]
#connection: "mysql"
#table: "products"
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
#perPage: 15
+exists: true
+wasRecentlyCreated: false
#attributes: array:7 [▼
"id" => 2
"created_at" => "2019-12-22 18:05:40"
"updated_at" => "2019-12-22 18:05:40"
"imagePath" => "https://s3.eu-central-1.amazonaws.com/bootstrapbaymisc/blog/24_days_bootstrap/vans.png"
"title" => "Neque quia sit facere."
"description" => "Seven flung down his cheeks, he went on growing, and, as the door opened inwards, and Alice's elbow was pressed hard against it, that attempt proved a failure. ▶"
"price" => 29
]
#original: array:7 [▶]
#changes: []
#casts: []
#dates: []
#dateFormat: null
#appends: []
#dispatchesEvents: []
#observables: []
#relations: []
#touches: []
+timestamps: true
#hidden: []
#visible: []
#guarded: array:1 [▶]
}
The cart gets filled with product.

From what I'm seeing it seems that your route is not redirecting correctly. In your controller, the actions is defined as
public function getAddToCart(Request $request, $id)
but in your button you are only passing the id parameter.
Try redefining your method in your controller to
public function getAddToCart($id)
that should do the trick.

Related

Illuminate\Foundation\Auth\User returning keyType: int

I am using the following trait to generate UUID's for my user model. I have setup a listener to the following event: Illuminate\Auth\Events\Login. This works when you just normally sign-in to the app (using Laravel Breeze). But when I manually do auth()->user($user) I get back an instance of Illuminate\Foundation\Auth\User where the keyType is an integer and incrementing is set to true, although my trait does otherwise.
Anyone knows how to fix this?
<?php
namespace App\Traits;
use Ramsey\Uuid\Uuid;
trait Uuidable
{
/**
* Cast the primary key type as a string
*/
public function initializeUuidable()
{
$this->setKeyType('string');
}
/**
* Set the model to none incrementing
*
* #return bool
*/
public function getIncrementing()
{
return false;
}
/**
* Set the key of the model
*
* #return void
*/
public static function bootUuidable()
{
static::creating(function ($model) {
if (!isset($model->attributes[$model->getKeyName()])) {
$model->incrementing = false;
$uuid = Uuid::uuid4();
$model->attributes[$model->getKeyName()] = $uuid->toString();
}
}, 0);
}
}
Illuminate\Foundation\Auth\User {#1494 ▼
#connection: "mysql"
#table: "users"
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
+preventsLazyLoading: false
#perPage: 15
+exists: true
+wasRecentlyCreated: false
#attributes: array:13 [▶
"id" => "31f12e1a-964c-4580-8a20-263c8bb7bf95"
"first_name" => "test"
"last_name" => "user"
"email" => "test#mrpackage.com"
"email_verified_at" => null
"password" => "$2y$10$vTAYxvC4s95PpF5BmzC0p..ZiQfcn3WARxXalgmd1kVZn5X1S/F02"
"last_login_id" => null
"remember_token" => null
"welcome_valid_until" => null
"printer_id" => null
"created_at" => "2021-09-15 14:38:00"
"updated_at" => "2021-09-15 14:38:20"
"deleted_at" => null
]
#original: array:13 [▶
"id" => "31f12e1a-964c-4580-8a20-263c8bb7bf95"
"first_name" => "test"
"last_name" => "user"
"email" => "test#mrpackage.com"
"email_verified_at" => null
"password" => "$2y$10$vTAYxvC4s95PpF5BmzC0p..ZiQfcn3WARxXalgmd1kVZn5X1S/F02"
"last_login_id" => null
"remember_token" => null
"welcome_valid_until" => null
"printer_id" => null
"created_at" => "2021-09-15 14:38:00"
"updated_at" => "2021-09-15 14:38:20"
"deleted_at" => null
]
#changes: array:3 [▶
"password" => "$2y$10$vTAYxvC4s95PpF5BmzC0p..ZiQfcn3WARxXalgmd1kVZn5X1S/F02"
"welcome_valid_until" => null
"updated_at" => "2021-09-15 14:38:20"
]
#casts: []
#classCastCache: []
#dates: []
#dateFormat: null
#appends: []
#dispatchesEvents: []
#observables: []
#relations: []
#touches: []
+timestamps: true
#hidden: []
#visible: []
#fillable: []
#guarded: array:1 [▶
0 => "*"
]
#rememberTokenName: "remember_token"
}

Laravel mass assignment ignore guarded

I have a simple Laravel Eloquest Model with some fileable attributes and relations. This model is connected to DB, and worked good two months ago. After updating a table and adding a new column status, something become broken. Here is my model:
class Good extends Model
{
protected $table = 'product_goods';
public $incrementing = false;
protected $fillable = ['sku', 'status'];
/**
* #return BelongsTo
* #noinspection PhpUnused
*/
public function product() {
return $this->belongsTo(Product::class);
}
/**
* #return BelongsTo
* #noinspection PhpUnused
*/
public function color() {
return $this->belongsTo(Color::class);
}
/**
* #return BelongsToMany
*/
public function sizes() {
return $this->belongsToMany(Size::class, 'product_good_size');
}
/**
* #return BelongsTo
* #noinspection PhpUnused
*/
public function sizeStandard() {
return $this->belongsTo(SizeStandard::class);
}
/**
* #return MorphMany
* #noinspection PhpUnused
*/
public function files() {
return $this->morphMany(File::class, 'fileable')
->orderBy('show_priority');
}
/**
* #return HasMany
* #noinspection PhpUnused
*/
public function prices() {
return $this->hasMany(Price::class);
}
}
Then i'm trying to make() this model like this:
$goodData = [
'prices' => [
'RUB' => 788,
'UAH' => 499,
],
'color_id' => Color::first()->id,
'size_standard_id' => $sizeStandard->id,
'sizes' => $sizeIds,
'sku' => $faker->uuid,
'files' => [
['file' => UploadedFile::fake(),],
['file' => UploadedFile::fake(),],
['file' => UploadedFile::fake(),],
['file' => UploadedFile::fake(),],
],
];
$good = Good::make($goodData);
Then i got illegal attributes, which I dont want to see. I need only fillable attributes, but i see whole data, which is wrong.
App\Models\Product\Good^ {#1207
#table: "product_goods"
+incrementing: false
#fillable: array:2 [
0 => "sku"
1 => "status"
]
#connection: "mysql"
#primaryKey: "id"
#keyType: "int"
#with: []
#withCount: []
#perPage: 15
+exists: false
+wasRecentlyCreated: false
#attributes: array:7 [
"prices" => array:2 [
"RUB" => 788
"UAH" => 499
]
"color_id" => "6922c4e9-462f-4ce8-8028-36116845f0ea"
"size_standard_id" => "5f367199-c28a-4dc7-a979-d46f019eb2ac"
"sizes" => array:6 [
0 => array:1 [
"id" => "275c9efd-f5b6-437c-b0f1-a05c278404bd"
]
1 => array:1 [
"id" => "3090beb1-7fd3-4f79-9977-1d78abf83d09"
]
2 => array:1 [
"id" => "3121d205-101e-4cf1-8130-1bd94a2c255d"
]
3 => array:1 [
"id" => "b903d4c0-d33d-4191-8fb5-9b625b06ef7f"
]
4 => array:1 [
"id" => "deddbd28-4e72-46bc-b317-8ab8a68c2ed7"
]
5 => array:1 [
"id" => "f4139b5a-b703-4cd0-a29a-44f66aae18fc"
]
]
"sku" => "62471d6b-04c6-3b88-a9af-2960f96b78a9"
"files" => array:4 [
0 => array:1 [
"file" => Illuminate\Http\Testing\FileFactory^ {#1162}
]
1 => array:1 [
"file" => Illuminate\Http\Testing\FileFactory^ {#1187}
]
2 => array:1 [
"file" => Illuminate\Http\Testing\FileFactory^ {#1164}
]
3 => array:1 [
"file" => Illuminate\Http\Testing\FileFactory^ {#1157}
]
]
"status" => "active"
]
#original: []
#changes: []
#casts: []
#dates: []
#dateFormat: null
#appends: []
#dispatchesEvents: []
#observables: []
#relations: []
#touches: []
+timestamps: true
#hidden: []
#visible: []
#guarded: array:1 [
0 => "*"
]
}
What do I do wrong?
Since you are using $faker->uuid I am assuming you are trying to call make() while seeding.
Mass Assignment restrictions are turned off during seeding. If you would like your model to respect Mass Assignment restrictions, you can use:
Good::reguard();
Good::make($goodData);

Model binding doesn't retrieve model data

I have this route:
Route::delete('product/{product}/attachments/{attachment}', 'AttachmentsController#destroy');
public function destroy(Product $product, Attachment $attachment)
{
dd($product);
}
and dd shows:
App\Models\Product^ {#1059
#fillable: array:3 [
0 => "title"
1 => "section_id"
2 => "sortOrder"
]
#attributes: []
#original: []
... etc
}
I can't access model data such as $product->title it will return null, so I tried to change destory method to:
public function destroy($product, Attachment $attachment)
{
$product = Product::whereId($product)->firstOrFail();
dd($product);
}
and now I can access/see the model data:
"section_id" => 18
"title" => "test product"
"sortOrder" => 217645360
"created_at" => "2020-05-05 13:34:54"
"updated_at" => "2020-05-05 13:34:54"
]
#original: array:8 [
"id" => 18
"section_id" => 18
"title" => "test product"
"sortOrder" => 217645360
"created_at" => "2020-05-05 13:34:54"
"updated_at" => "2020-05-05 13:34:54"
]
Why doesn't the model binding work? I even tried to add
public function boot()
{
parent::boot();
Route::model('product', App\Models\Product::class);
}
I tried also to do: cache:clear route:clearand composer dumpautoload I cant find why the model binding doesn't work?

How to update alias column in Laravel

I want to update records in Postgresql DB and Laravel.
The problem is that alias columns are not in relation with the table, but I made them in first place:
message: "SQLSTATE[42703]: Undefined column: 7 ERROR: column "nivo600" of relation "meas_kanal" does not exist↵LINE 1: update "meas_kanal" set "recordtime" = $1, "nivo600" = $2, "...↵
The function in controller:
$student = Stamboliiski::where('recordtime', $request->get('kanal_id'))
->selectRaw('recordtime')
->selectRaw('max(formattedvalue) filter (where fullname = \'text 1\') as nivo600')
->selectRaw('max(formattedvalue) filter (where fullname = \'text 2\') as razhod600')
->update([
'recordtime' => $request->input('recordtime'),
'nivo600' => $request->input('formattedvalueN'),
'razhod600' => $request->input('formattedvalueR'),
])
->where(function ($query) {
$query->where('fullname', 'like', "text 1")
->orWhere('fullname', 'like', "text 2");
})
->groupBy('recordtime')
->orderBy('recordtime')
->first();
$success_output = '<div class="alert alert-success">The record is updated!</div>';
Model:
class Stamboliiski extends Model
{
protected $connection = 'stamboliiski';
protected $table = 'meas_kanal';
protected $fillable = ['fullname','formattedvalue','recordtime','qualitydesc','statedesc','author','id'];
}
Why?
EDIT 1 after comment of #Dimitri Mostrey:
$student = Stamboliiski::where('recordtime', $request->get('kanal_id'))
->selectRaw('recordtime')
->selectRaw('max(formattedvalue) filter (where fullname = \'text 1\') as nivo600')
->selectRaw('max(formattedvalue) filter (where fullname = \'text 2\') as razhod600')
->where(function ($query) {
$query->where('fullname', 'like', "text 1")
->orWhere('fullname', 'like', "text 2");
})
->groupBy('recordtime')
->orderBy('recordtime')
->first();
$student->recordtime = $request->get('recordtime');
$student->nivo600 = $request->get('formattedvalueN');
$student->razhod600 = $request->get('formattedvalueR');
$student->author = Auth::user()->name;
$student->save();
The error now is this:
message: "SQLSTATE[42703]: Undefined column: 7 ERROR: column "nivo600" of relation "meas_kanal" does not exist↵LINE 1: update "meas_kanal" set "nivo600" = $1, "razhod600" = $2, "a...↵ ^ (SQL: update "meas_kanal" set "nivo600" = 1.86, "razhod600" = 9.76, "author" = John Doe, "updated_at" = 2020-04-30 10:22:28 where "id" is null)"
In this method it uses id column that I don't want, and even I don't know why it used instead using the timestamp.
EDIT 2 on reply of #Uzair Riaz
Unforchantly the problem is still here. After change the controller and model is getting success message, but nothing changes. For example if I want to change value of nivo600 to 1 in recordtime 2020-04-17 00:00:00. After I echo $student in dd:
App\StamboliiskiMeasCanal {#530
#connection: "stamboliiski"
#table: "meas_kanal"
#fillable: array:8 [
0 => "fullname"
1 => "formattedvalue"
2 => "recordtime"
3 => "qualitydesc"
4 => "statedesc"
5 => "author"
6 => "id"
7 => "updated_at"
]
#mapping: array:2 [
"nivo600" => "formattedvalue"
"razhod600" => "formattedvalue"
]
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
#perPage: 15
+exists: true
+wasRecentlyCreated: false
#attributes: array:6 [
"recordtime" => "2020-04-17 00:00:00"
"nivo600" => "1.86"
"razhod600" => "9.76"
"author" => "Христиан Йорданов"
"formattedvalue" => "9.76"
"updated_at" => "2020-05-05 06:47:26"
]
#original: array:6 [
"recordtime" => "2020-04-17 00:00:00"
"nivo600" => "1.86"
"razhod600" => "9.76"
"author" => "Христиан Йорданов"
"formattedvalue" => "9.76"
"updated_at" => "2020-05-05 06:47:26"
]
#changes: array:4 [
"recordtime" => "2020-04-17 00:00:00"
"author" => "Христиан Йорданов"
"formattedvalue" => "9.76"
"updated_at" => "2020-05-05 06:47:26"
]
#casts: []
#dates: []
#dateFormat: null
#appends: []
#dispatchesEvents: []
#observables: []
#relations: []
#touches: []
+timestamps: true
#hidden: []
#visible: []
#guarded: array:1 [
0 => "*"
]
}
It seems that no update is maded...
If those are the only two aliases you are going to use, I suggest overriding the ->fill() method in your model. Map your aliases to the $fillable like so:
class Stamboliiski extends Model
{
protected $fillable = ['fullname', 'formattedvalue', 'recordtime', 'qualitydesc', 'statedesc', 'author', 'id'];
protected $mapping = [
'nivo600' => 'formattedvalue',
'razhod600' => 'formattedvalue'
];
public function fill(array $attributes)
{
foreach ($attributes as $key => $value) {
if (isset($this->mapping[$key])) {
$attributes[$this->mapping[$key]] = $value;
unset($attributes[$key]);
}
}
return parent::fill($attributes);
}
}
Then you can update like so:
$student->update([
'recordtime' => $request->get('recordtime'),
'nivo600' => $request->get('formattedvalueN'),
'razhod600' => $request->get('formattedvalueR'),
'author' => Auth::user()->name
]);

laravel Property [address] does not exist on this collection instance

I have a business table which is linked using eloquent with table addresses, location and gallery.
Output looks like this:
Collection {#266 ▼
#items: array:1 [▼
0 => Business {#260 ▼
#table: "businesses"
+timestamps: true
#connection: "mysql"
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
#perPage: 15
+exists: true
+wasRecentlyCreated: false
#attributes: array:14 [▶]
#original: array:14 [▶]
#casts: []
#dates: []
#dateFormat: null
#appends: []
#events: []
#observables: []
#relations: array:3 [▼
"addresses" => Collection {#261 ▼
#items: array:1 [▼
0 => Address {#263 ▼
#table: "addresses"
+timestamps: true
#connection: "mysql"
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
#perPage: 15
+exists: true
+wasRecentlyCreated: false
#attributes: array:9 [▼
"id" => 10
"firstline_address" => "96"
"secondline_address" => "Cambridge Street"
"town" => "p.wojtas26#gmail.com"
"city" => "p.wojtas26#gmail.com"
"postcode" => "SK15 1AU"
"telephone" => "7815522481"
"created_at" => "2017-06-26 08:05:32"
"updated_at" => "2017-06-26 08:05:32"
]
#original: array:11 [▶]
#casts: []
#dates: []
#dateFormat: null
#appends: []
#events: []
#observables: []
#relations: array:1 [▼
"pivot" => Pivot {#262 ▶}
]
#touches: []
#hidden: []
#visible: []
#fillable: []
#guarded: array:1 [▶]
}
]
}
"location" => Location {#279 ▶}
"gallery" => null
]
However the problem is that is says:
Property [addresses] does not exist on this collection instance. (View: C:\xampp\htdocs\laravel\resources\views\displayBusiness.blade.php)
here's my view:
#foreach($business->addresses as $address)
<p>{{$address->firstline_address}}</p>
<p>{{$address->secondline_address}}</p>
<p>{{$address->town}}</p>
<p>{{$address->city}}</p>
<p>{{$address->postcode}}</p>
<p>{{$address->telephone}}</p>
#endforeach
</div>
Model:
class Business extends Model
{
protected $table = 'businesses';
public $timestamps = true;
use Searchable;
public function addresses()
{
return $this->belongsToMany('App\Address', 'business_address', 'business_id', 'address_id');
}
public function gallery()
{
return $this->hasOne('App\Gallery', 'business_id');
}
public function film()
{
return $this->hasOne('App\Film', 'business_id');
}
public function location()
{
return $this->hasOne('App\Location', 'business_id');
}
public function user()
{
return $this->hasMany('App\User', 'user_business', 'business_id', 'user_id');
}
Another problem is that sometimes a field is empty so let's say sometimes $address->city = null how would I tell to ignore that field and carry on?
I can do #if($address->city == NULL) but I don't want to do it for each one as I cannot predict what will be empty.
//edit
Controller:
public function displayBusiness($id) {
$business = Business::where('id', $id)
->with('addresses')
->with('location')
->with('gallery')
->get();
//dd($business);
/*
$instagram = $business->instagram_business;
$twitter = $business->twitter_business;
$instagramItems=[];
$twitterItems=[];
if(!empty ($instagram)){
$client = new \GuzzleHttp\Client();
$url = sprintf('https://www.instagram.com/'.$instagram.'/media');
$response = $client->get($url);
$instagramItems = json_decode((string) $response->getBody(), true)['items'];
$twitterItems = Twitter::getUserTimeline(['screen_name' => $twitter, 'count' => 10, 'format' => 'array']);
*/
//$session = session()->put('key', $id);
//$gallery = Gallery::where('business_id', $id)->get();
//$location = Location::where('business_id', $id)->get();
//$review = Review::where('business_id', $id)->get();
return view('business.displayBusiness', compact('business', 'address', 'gallery', 'location', 'review', 'instagramItems', 'twitterItems'));
/*}
//edit2
It now says
Trying to get property of non-object (View: C:\xampp\htdocs\laravel\resources\views\business\displayBusiness.blade.php)
Which is:
#foreach ($business->location as $marker)
<script>
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 19,
center: {lat: {{$marker->latitude}}, lng: {{$marker->longitude}}}
});
It looks like you need to change
$business = Business::where('id', $id)
->with('addresses')
->with('location')
->with('gallery')
->get();
to
$business = Business::where('id', $id)
->with('addresses')
->with('location')
->with('gallery')
->first();
Your problem is that your query is returning a Collection rather than a single instance of Business, this is because your query is searching for multiple businesses and will generate a Collection of any businesses it finds, even if there is just one.
Better to use has()
$business = Business::where('id', $id)
->has('addresses')
->has('location')
->has('gallery')
->get();
Querying Relationship Existence
https://laravel.com/docs/5.7/eloquent-relationships#querying-relations

Resources