I'm getting this error however using dd($followings); in the home controller, the date is displayed, but when I try to foreach the view, I get this error.
Does anyone have an idea what I'm doing wrong?
Undefined variable $followings
HomeController
public function userFollow($username)
{
$user = User::where('username', $username)->firstOrFail();
$posts = Post::where('user_id', $user->id)->simplePaginate(3);
$user = User::find($user->id);
$followings = $user->followings()->with('followable')->get();
dd($followings);
return view('/#', compact('user'), compact('posts'), compact('followings'));
}
view #.blade.php
#foreach($followings as $following)
{{$following->id}}
#endforeach
dd($followings); returns
#attributes: array:7 [▼
"id" => 60
"user_id" => 5
"followable_type" => "App\Models\User"
"followable_id" => 9
"accepted_at" => "2022-12-20 20:36:49"
"created_at" => "2022-12-20 20:36:49"
"updated_at" => "2022-12-20 20:36:49"
Use compact() like this
return view('/#', compact('user', 'posts', 'followings'));
Or use with()
return view('/#')->with(['user' => $user, 'posts' => $posts, 'followings' => $followings]);
Related
I'm using PHP8.1 and Laravel 9 for a project in which I've got the following enum:
enum OrderStatuses : string
{
case New = 'new';
case Pending = 'pending';
case Canceled = 'canceled';
case Paid = 'paid';
case PaymentFailed = 'payment-failed';
public function createOrderStatus(Order $order) : OrderStatus
{
return match($this) {
OrderStatuses::Pending => new PendingOrderStatus($order),
OrderStatuses::Canceled => new CanceledOrderStatus($order),
OrderStatuses::Paid => new PaidOrderStatus($order),
OrderStatuses::PaymentFailed => new PaymentFailedOrderStatus($order),
default => new NewOrderStatus($order)
};
}
one of the classes listed in the enum looks like this:
abstract class OrderStatus
{
public function __construct(protected Order $order)
{
}
/**
* Determines whether an order can transition from one status into another
*
* #return bool
*/
abstract public function canBeChanged() : bool;
}
class PaidOrderStatus extends OrderStatus
{
public function canBeChanged(): bool
{
return false;
}
}
all others are basically the same, they just differ on the implementation of the canBeChanged method.
Now, I've got the following resource:
class OrdersResource extends JsonResource
{
public function toArray($request): array
{
return [
'id' => (string)$this->id,
'type' => 'orders',
'attributes' => [
'status' => $this->status,
'payment_type' => $this->payment_type,
'payment_transaction_no' => $this->payment_transaction_no,
'subtotal' => $this->subtotal,
'taxes' => $this->taxes,
'total' => $this->total,
'items' => OrderItemsResource::collection($this->whenLoaded('orderItems')),
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
]
];
}
}
which is called from my controller like this:
return (new OrdersResource($order))
->response()->setStatusCode(ResponseAlias::HTTP_OK);
Before implementing the enum my resource was working correctly, it returned the expected data. But after the enum, it's returning [] for the status field.
A sample return is currently looking like this:
"id" => "86b4e2da-76d4-4e66-8016-88a251513050"
"type" => "orders"
"attributes" => array:8 [
"status" => []
"payment_type" => "card"
"payment_transaction_no" => "3kaL92f5UwOG"
"subtotal" => 3005.76
"taxes" => 0
"total" => 3005.76
"created_at" => "2022-08-31T12:47:55.000000Z"
"updated_at" => "2022-08-31T12:47:55.000000Z"
]
]
notice again the value for status.
I've got a casting and a attribute in my Order's model:
protected $casts = [
'status' => OrderStatuses::class,
];
protected function status(): Attribute
{
return new Attribute(
get: fn(string $value) =>
OrderStatuses::from($value)->createOrderStatus($this),
);
}
Furthermore, if I dd the type of $this->status in the toArray method from OrdersResource it says that it is of type Domain\Order\Enums\PaidOrderStatus which is correct.
I tried adding __toString() to PaidOrderStatus class but had no luck. What am I missing?
Update
I've added a test() method to PaidOrderStatus:
class PaidOrderStatus extends OrderStatus
{
public function canBeChanged(): bool
{
return false;
}
public function test() : string
{
return OrderStatuses::Paid->value;
}
}
and then did:
public function toArray($request): array
{
return [
'id' => (string)$this->id,
'type' => 'orders',
'attributes' => [
'status' => ($this->status)->test(),
'payment_type' => $this->payment_type,
'payment_transaction_no' => $this->payment_transaction_no,
'subtotal' => $this->subtotal,
'taxes' => $this->taxes,
'total' => $this->total,
'items' => OrderItemsResource::collection($this->whenLoaded('orderItems')),
'created_at' => $this->created_at,
'updated_at' => $this->updated_at,
]
];
}
and that gave me:
[
"id" => "8a2d6024-a63f-44ba-a145-cede2ecf3aaa"
"type" => "orders"
"attributes" => array:8 [
"status" => "paid"
"payment_type" => "card"
"payment_transaction_no" => "kC9upaoGb2Nd"
"subtotal" => 657.26
"taxes" => 0
"total" => 657.26
"created_at" => "2022-08-31T13:17:25.000000Z"
"updated_at" => "2022-08-31T13:17:25.000000Z"
]
and that worked. But it's a very hacky solution and I'd like to do better.
I'm sure you've already solved this as it's been months ago, but first you don't need the Attribute mutator as you have already defined the cast which will correctly map the string value to the right enum case.
Then in the resource, you just get the value from the enum like so.
'status' => $this->status->value,
I have a resource in this resource I have collection , now I want to show the pagination links of that collection, how can I do it?
This is my resource
public function toArray($request)
{
return [
"name" => $this->name ,
"slug" => $this->slug ,
"bg_image" => imageGenerate("sections" , $this->bg_image) ,
"bg_color" => $this->bg_color ,
"items" => new ItemCollection($this->items()->paginate(20)) ,
];
}
this is my collection
public function toArray($request)
{
return $this->collection->map(function ($item) {
return [
"id" => $item->id ,
"name" => $item->name ,
"slug" => $item->slug ,
"image" => imageGenerate("items" , $item->image) ,
"code" => $item->code ,
"category" => $item->category->name??""
];
});
}
According to Laravel 8.x documentation, you may pass in the data that you want paginate to newly created Collection instance. Here is an example:
use App\Http\Resources\UserCollection;
use App\Models\User;
Route::get('/users', function () {
return new UserCollection(User::paginate());
});
Also see this
I have select options in my form where it has first row when page loads and users can add more rows by AJAX and store all rows data at once.
The problem is that my first row (which is visible when page loads) does not save the data while all other added rows will be saved.
Here is a screenshot of my select options when page loads:
And here it is when user adds new rows:
Here is my sample data that those rows have sent to controller (screenshot #2):
array:2 [▼
0 => array:3 [▼
"name" => "ali"
"username" => "alireza"
"action" => "delete"
]
1 => array:3 [▼
"name" => "eraty"
"username" => "aery"
"action" => "optional"
]
]
As I explained in my screenshots, object 0 data will not be store in the database, not sure why.
Here is my controller:
public function update(Request $request, $id)
{
$this->validate($request, [
'note' => 'required|string',
]);
$post = Post::where('id', $id)
->where('user_id', Auth::id())
->first();
$post->user_id = Auth::id();
$post->note = $request->input('note');
if ($post->save()) {
// social media (add new)
$socialHeir = $request->input('social_media_heir');
$socialAction = $request->input('social_media_action');
$socialNames = $request->input('social_media_name');
$socialUsernames = $request->input('social_media_username');
if (!empty($socialNames)) {
$result_array = [];
foreach ($socialNames as $key => $val) {
$result_array[$key] = [
'name' => $socialNames[$key],
'username' => $socialUsernames[$key],
'action' => $socialAction[$key]
];
}
// dd($result_array); <-- result of this line I shared above (after screenshot 2)
foreach ($result_array as $key => $merge) {
if (!empty($key) && !empty($merge)) {
SocialMedia::create([
'owner_id' => Auth::id(),
'heir_id' => $socialHeir,
'post_id' => $post->id,
'name' => $merge['name'],
'username' => $merge['username'],
'what_to_do' => $merge['action'],
]);
}
}
}
}
return redirect()->route('posts.index');
}
Update
SocialMedia model:
protected $fillable = [
'owner_id',
'heir_id',
'post_id',
'name',
'username',
'what_to_do',
];
public function post()
{
return $this->belongsTo(Post::class);
}
Post model
protected $fillable = [
'user_id',
'note',
];
public function socialMedias()
{
return $this->hasMany(SocialMedia::class);
}
Solved
The issue was in $key in my foreach after removing it, it saves all rows now.
foreach($result_array as $merge) {
if(!empty($merge)) {
SocialMedia::create([
'owner_id' => Auth::id(),
'heir_id' => $socialHeir,
'post_id' => $will->id,
'name' => $merge['name'],
'username' => $merge['username'],
'what_to_do' => $merge['action'],
]);
}
}
How can I hide records from my controller? i need to hide the records if the column 'retiro' is not null.
Controller:
public function retiro (Request $request){
$data = [
'category_name' => 'datatable',
'page_name' => 'miscellaneous',
'has_scrollspy' => 0,
'scrollspy_offset' => '',
];
$records = Registro::where('retiro', '<>', 'on')->get();
return view('retiro',compact('records'))->with($data);
}
if 'retiro' == 'on' should hide the record
the problem is that when printing the records it does not show anything.
help pls
You can pass all the variables as the second parameter on the view() using compact instead of doing it separately using the function with.
public function retiro (Request $request){
$data = [
'category_name' => 'datatable',
'page_name' => 'miscellaneous',
'has_scrollspy' => 0,
'scrollspy_offset' => '',
];
$records = Registro::whereNotNull('retiro')
->where('retiro','=','on')
->get();
return view('retiro',compact('records','data'));
}
I am working on adding the product values into the cart and i am using darryldecode Laravel shopping cart.
When I try to get the image and total price from the attribute array, I get the error Undefined property: stdClass::$total.
Here is my Controller:
public function cart(Request $request , $id)
{
// return $request;
$cart = Cart::add([
'id' => $request->id,
"name" => $request->name,
"crm" => $request->sku,
"quantity" => $request->qty,
"price" => $request->price,
"attributes" => array(["image" => $request->image] , "total" => $request->price * $request->qty)
]);
if($cart)
{
return redirect()->route('cart');
}
}
Here is the Cart Controller
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Cart;
class CartController extends Controller
{
public function index()
{
// return Cart::getContent();
return View('demo', [ 'cart' => Cart::getContent()]);
}
}
Here is the view where I try to print the image and total
#foreach($cart as $product)
Name:<td>{{ $product->name}}</td>
Price:<td>{{ $product->price}}</td>
Quantity:<td>{{ $product->qty}}</td>
Attributes:<td>{{ $product->attributes}}</td>
#foreach(json_decode($product->attributes) as $details)
Image:<td>{{ $details->image}}</td>
Total:<td>{{ $details->total}}</td>
{{ $details}}
#endforeach
#endforeach
You have a typo in this line:
"attributes" => array(["image" => $request->image] , "total" => $request->price * $request->qty)
Rather do this:
"attributes" => ["image" => $request->image, "total" => $request->price * $request->qty]
You have to add both attributes into one array when you want get into view (blade) file.
Use below code:
$cart = Cart::add([
'id' => $request->id,
"name" => $request->name,
"crm" => $request->sku,
"quantity" => $request->qty,
"price" => $request->price,
"attributes" => array(["image" => $request->image, "total" => $request->price * $request->qty])
]);