Why are some of my request parameters sent as `null` to my controller? - php

I'm developing a LiveWire/Laravel project and in my product.blade.php, the category_id is sent as null to the store function. Apparently there is no problem in my input and my model and category_id is defineded in my component.
I used some artisan comands related to clearing the cache and config and even I created another component with different name but I met same bug
dd:
array:8 [▼
"title" => "تراکت"
"en_title" => "tracket"
"category_id" => null
"description" => "nothing"
"status" => 1
"img" => null
"price" => "48000"
"keywords" => "tracket"
]
Livewire Product Blade:
<div class="form-group">
<label class="form-label">دسته بندی محصول</label>
<select wire:model="category_id" id="select-countries" class="form-control custom-select">
#foreach($categories as $category)
<option value="{{$category->id}}">{{$category->title}}</option>
#if(count($category->childrenRecursive) >0)
#include('Admin.category.partials',['categories'=>$category->childrenRecursive,'level'=>1,'create'=>1])
#endif
#endforeach
</select>
</div>
Livewire Component :
<?php
class Index extends Component
{
public $title,$en_title,$category_id,$description,$status=1,$img=null,$price,$keywords;
public function store(){
$keywords=serialize(explode(",",$this->keywords));
Product::create([
'title'=>$this->title,
'en_title'=>$this->en_title,
'category_id'=>$this->category_id,
'description'=>$this->description,
'status'=>$this->status,
'price'=>$this->price,
'image'=>$this->img,
'keywords'=>$keywords,
]);
$this->reset(['title','en_title','category_id','description','price']);
session()->flash('add_product','محصول شما با موفقیت اضافه شد');
}
public function render()
{
$categories=Category::with('childrenRecursive')->where('parent_id',null)->get();
$products=Product::latest()->paginate(8);
return view('livewire.admin.product.index',compact('categories','products'))->extends('layouts.admin')->section('content');
}
}

Your syntax appears correct and I suspect you're sometimes seeing null because you're not setting an initial value for $category_id. Therefore, if you don't select an option from your select element and submit your form, the value of $category_id will be null.
You can perform some component initialization in the mount method where I suggest you set an initial value for your public properties:
public $categories, $products;
public $category_id;
public function mount()
{
$this->categories = Category::with('childrenRecursive')
->where('parent_id', null)
->get();
$this->products = Product::latest()->paginate(8);
$this->category_id = $this->categories->first()->id;
}
public function render()
{
return view(
'livewire.admin.product.index',
compact('categories','products')
)
->extends('layouts.admin')
->section('content');
}

Related

Unable to resolve dependency [Parameter #0 [ <required> $task ]]

I have a main Blade where I call the modal that is in another Blade, but I need to pass the information of each task to it. The modal is inside a foreach loop foreach($tasks as $task), then comes the taskmodal component, then a card with the information to open the modal.
I'm trying to pass a parameter from a blade to a modal on another blade
Add component to tasks.blade.php
#foreach ($tasks as $task)
#livewire('componentes.taskmodal',['task'=>$task])
#endforeach
then on the Taskmodal component
<?php
namespace App\Http\Livewire\Componentes;
use Livewire\Component;
class Taskmodal extends Component
{
public $columnTask;
public $modalviews;
public $active;
public $task;
public function updateView($view){
$this->modalviews = $view;
}
public function mount($task){
$this->columnTask = [1=>'Texto',2=>'Fecha'];
$this->modalviews = [[1,'Descripcion'],[1,'Subtareas'], [1,'Comentarios']];
$this->active = '2';
$this->task = $task;
}
public function add($item){
array_push($this->columnTask, $item);
}
public function changeActive($item){
if($this->active != $item){
$this->active = $item;
}
}
public function render()
{
return view('livewire.componentes.taskmodal');
}
}
if i debug with dd($task['Titulo']) on the taskmodal blade it works
<div class="modal-top">
<h3 class="modal-title px-5" id="exampleModalLabel">#php dd($task['Titulo']); #endphp</h3>
</div>
but when
<div class="modal-top">
<h3 class="modal-title px-5" id="exampleModalLabel">{{$task['Titulo']}}</h3>
</div>
The error is Unable to resolve dependency [Parameter #0 [ $task ]]
Component $task
array:4 [▼
"id" => 1
"Hecho" => 1
"Titulo" => "Titulo 1"
"Info" => array:2 [▶]
]
"I did my best to write it in English, but it's not my primary language. I hope someone can help me
I've tried changing the names of the parameters, using a differents ways to pass de parameter.

How can I fix Laravel comments policy not working?

I am using inertia JS.
I created a forum where you can manage your posts and comments (CRUD).
Normally, the one who can modify or delete his post or comment is the one who created it and the administrator.
I was able to set up a policy for the post but for the comment it does not work. I need your help to fix this.
This is my show function for post and comments
public function show(Post $post, Comment $comment)
{
usleep(500000);
$post->incrementReadCount();
$updateableCommentIds = $post->comments
->map(function ($comment) {
if (Auth::user()->can('update', $comment)) {
return $comment->id;
}
})
->filter();
return Inertia::render('Frontend/Forum/Helpers/PostDetails', [
'post' => PostResource::make(
$post->load('user')->loadCount('comments')
),
'comments' => CommentResource::collection(
Comment::where('post_id', $post->id)
->with('user')
->paginate(10)
->withQueryString()
),
'categories' => Category::all(),
'can' => [
'edit' => Auth::check() && Auth::user()->can('edit', $post),
'commentEdit' => $updateableCommentIds
]
]);
}
This's my comment policy
class CommentPolicy
{
use HandlesAuthorization;
public function update(User $user, Comment $comment): bool
{
return $user->is_admin || $user->id === (int) $comment->user_id;
}
}
This's my vue file
<div
v-if="can.commentEdit.includes(comment.id)"
>
//show me this if im the auther of this comment
</div>
I already tried but it doesn't work either
public function show(Post $post)
{
$canUpdateComments = $post->comments->every(function ($comment) {
return Auth::user()->can('update', $comment);
});
// Return the view with the ability to update the comments
return view('posts.show', compact('post', 'canUpdateComments'));
}
I just noticed that I had a commentResource and just with that I found the solution instead of checking each time on the post not directly on the comment...
class CommentResource extends JsonResource
{
public function toArray($request)
{
return [
...
'can' => [
'edit' => Auth::user()->can('update', $this->resource)
]
];
}
}

Laravel Model binding many to many realtionship does not populate data

I have two tables with a many to many relation (Project and Center, the pivot table is ProjectCenter).
These are my models:
Project:
class Project extends Model {
public function centers()
{
return $this->belongsToMany('App\Models\Center', 'ProjectCenter', 'IDProject', 'IDCenter');
}
public function getCenterListAttribute()
{
return $this->centers->lists('IDCenter')->all();
}
}
Center:
class Center extends Model {
public function projects()
{
return $this->belongsToMany('App\Models\Project', 'ProjectCenter', 'IDCenter', 'IDProject');
}
}
Controller -> edit:
public function edit($id)
{
$project = Project::find($id);
$centerList = Center::lists('Name', 'IDCenter')->toArray();
return view('project/add', array('centerList' => $centerList))->with('project', $project);
}
And the view:
{!! Form::label('centers_list', 'Center*') !!}
{!! Form::select('centers_list[]',
$centerList,
null,
array(
'class' => 'form-control ',
'required' => 'required',
'multiple' => true,
'data-placeholder' =>
'Select a center'
)
) !!}
But I can not select the data already stored previously.
For example: the project 8 (IDProject) has two centers (1 and 2) but the data is not populated in the multiple select:
What am I doing wrong?
You all time get same result $centerList = Center::lists('Name', 'IDCenter')->toArray(); but you must be get product centers using query with model.
$project = Project::with("centers:Name,IDCenter")->find($id);
$centerList = $project->centers->pluck('Name', 'IDCenter')->toArray();
I already solve the problem using a foreach to select the related centers:
<select multiple="multiple" name="centers[]" id="centers" class="form-control select2" required="required" data-placeholder="Select a center">
#if($centerList)
#foreach($centerList as $key => $center)
<option value="{{$key}}" {{ (collect($selectedCenters)->contains($key)) ? "selected='selected'" : '' }} >{{$center}}</option>
#endforeach
#endif
</select>

Undefined variable issue Laravel 5.4

I've got stuck with this error so if ever pls forgive me because I'm still new at laravel. I got this error
Undefined variable: clientTransactions (View:
C:\xampp\htdocs\dcgwapo\resources\views\service_details\create.blade.php)
but I have a right code but I still wondering why it is still undefined variable given I define it in my controller.
create.blade.php in service details code
<div class="form-group">
<label for="client_transaction_id">Client Trans ID: </label>
<select class="form-control" name="client_transaction_id">
#foreach ($clientTransactions as $clientTransaction)
<option value= "{{ $clientTransaction->id }}">
{{ $clientTransaction->id }}
</option>
#endforeach
</select>
</div>
ServiceDetailsController code
public function create()
{
$users = User::pluck('fname', 'lname', 'id');
$services = Service::pluck('name', 'id');
$clientTransactions = ClientTransaction::all();
return view('service_details.create', ['users' => User::all()], ['services' => Service::all()], ['clientTransactions' => ClientTransaction::all()]);
}
ServiceDetail.php model code
public function clientTransaction()
{
return $this->belongsTo(ClientTransaction::class);
}
I hope you can help me. Thanks!
You're sending variables to your view the wrong way. The seconds argument should be an array with all your variables. As of now your adding a new parameter to the view function for each variable.
view('view', [...], [...], [...])
It should be like this:
view('view', [...1, ...2, ...3])
So what you need to change is the return statement to this:
return view('service_details.create', ['users' => User::all(), 'services' => Service::all(), 'clientTransactions' => ClientTransaction::all()]);
Second parameter to view function accepts an associative array of data, you are passing an indexedArray of arrays, Just use this return statement and you are good to go. ;)
return view('service_details.create', [
'users' => User::all(),
'services' => Service::all(),
'clientTransactions' => ClientTransaction::all()
]);
You can use compact to pass data from controller to view:
public function create()
{
$users = User::pluck('fname', 'lname', 'id');
$services = Service::pluck('name', 'id');
$clientTransactions = ClientTransaction::all();
return view('service_details.create',compact('users','services','clientTransactions');
}

Laravel update makes new table rule instead of updating

I have a company table and an attributes table with all sorts of value in it.
One company hasMany attributes and an attribute belongsTo a company.
Now I have a value inside the attributes table with a 'account_nr_start' (for example, when a new user is added to a company its account_id starts counting up from 1000).
Controller:
public function __construct(Company $company, User $user)
{
if(Auth::user()->usertype_id == 7)
{
$this->company = $company;
}
else
{
$this->company_id = Auth::user()->company_id;
$this->company = $company->Where(function($query)
{
$query->where('id', '=', $this->company_id )
->orWhere('parent_id','=', $this->company_id);
}) ;
}
$this->user = $user;
$this->middleware('auth');
}
public function edit(Company $company, CompaniesController $companies)
{
$companies = $companies->getCompaniesName(Auth::user()->company_id);
$attributes = $company->attributes('company')
->where('attribute', '=', 'account_nr_start')
->get();
foreach ($attributes as $k => $v) {
$nr_start[] = $v->value;
}
return view('company.edit', ['company' => $company, 'id' => 'edit', 'companies' => $companies, 'nr_start' => $nr_start]);
}
public function update(UpdateCompanyRequest $request, $company, Attribute $attributes)
{
$company->fill($request->input())->save();
$attributes->fill($request->only('company_id', 'attribute_nr', 'value'))->save();
return redirect('company');
}
HTML/Blade:
<div class="form-group {{ $errors->has('_nr_') ? 'has-error' : '' }}">
{!! HTML::decode (Form::label('account_nr_start', trans('common.account_nr_start').'<span class="asterisk"> *</span>', ['class' => 'form-label col-sm-3 control-label text-capitalize'])) !!}
<div class="col-sm-6">
{!! Form::text('value', $nr_start[0], ["class"=>"form-control text-uppercase"]) !!}
{!! $errors->first('account_nr_start', '<span class="help-block">:message</span>') !!}
</div>
</div>
When I update a company now, it will upload like the last input here: :
So it makes a new rule, while it needs to edit the current attribute rule instead of making a new rule with an empty company_id/attribute.
If I understand what you are trying to do, I think this will fix your problem. The issue you have is the Attribute model is a new instance of the model rather than retrieving the model you need.
before running fill() from the attributes method try this
$new_attribute = $attributes->where('company_id', '=', $company->id)->where('attribute', '=', 'account_nr_start')->first();
Then run the fill()
$new_attribute->fill($request->only('company_id', 'attribute_nr', 'value'))->save();

Categories