I banged my head against the walls for 2 days now and I can't seem to shake this error.
I am receiving this error:
ErrorException (E_WARNING)
array_map(): Argument #2 should be an array
What I am trying to do: Each user can have a list of urls in the database. The same url can be in two or more user account, so it is a many to many relationship.
My UrlsController looks like this:
<?php
namespace App\Http\Controllers;
use App\User;
use App\Urls;
use Illuminate\Http\Request;
use Auth;
class UrlsController extends Controller
{
public function __construct() {
$this->middleware('auth');
}
public function index(User $user)
{
return view('editurl', compact('user'));
}
public function store(User $user) {
$user_id = Auth::user()->id;
$data = request()->validate([
'user_id' => $user_id,
'url' => 'required',
]);
auth()->user()->userurls()->create([
'user_id' => $data['user_id'],
'url' => $data['url'],
]);
return redirect("/url/" . auth()->user()->id);
}
}
My Urls model looks like this:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Urls extends Model
{
//protected $quarded = [];
protected $fillable = ['user_id','url'];
protected $table = 'userUrls';
public function user()
{
return $this->belongsToMany(User::class);
}
}
My blade file looks like this:
#extends('layouts.pagprincipala')
#section('content')
<section id="home" class="home pt-5 pb-5">
<div class="container mb-5">
<div class="row">
<div class="col-md-8">
<h1 class="h4">Adaugare url-uri</h1>
<hr class="bg-dark w-25 ml-0">
<p>
<form action="/url/{{$user->id}}" enctype="multipart/form-data" method="post">
#csrf
<div class="row">
<div class="col-8 offset-2">
<div class="form-group row">
<label for="url" class="col-md-12 col-form-label">Adaugare URL (doar emag si pcgarage)</label>
<input id="url"
type="text"
class="form-control{{$errors->has('url') ? 'is-invalid' : ''}}"
name="url"
autocomplete="url" autofocus>
#if($errors->has('url'))
<span class="invalid-feedback" role="alert">
<strong class="text-danger">Campul url este obligatoriu.</strong>
</span>
#endif
</div>
<div class="row pt-4">
<button class="btn btn-primary">Adaugare URL</button>
</div>
</div>
</div>
</form>
</p>
</div>
</div>
</div>
</section>
#endsection
Also, my routes look like this:
Route::get('/url/{user}', 'UrlsController#index')->name('editurl');
Route::post('/url/{user}', 'UrlsController#store')->name('updateurl');
Can you give me a suggestion on how to move forward from this ?!
The problem is in your validator:
$data = request()->validate([
'user_id' => $user_id,
'url' => 'required',
]);
You try to validate the user_id with a rule that is the user id. What you probably want to achieve is 'user_id' => 'integer', or you can drop this rule all together as you know who the user is because of Auth()->user(). This should do:
$data = request()->validate([
'url' => 'required|url', //checks if it is an URL
]);
What we don't know is how your User model is constructed. With a many to many you need a pivot table urls_users or user_urls_users with url_id and user_id which means you don't need a user_id in the userUrls table, just id and url. But that's another issue. If you want to make sure any user has any url only once, you can use the ->sync() methode.
Related
I am new developer, and I seem to be stuck on handling arrays in laravel. I am using Laravel 8, and I cant seem to solve this situation.
I am building an internal recruitment site, where once a manager posts a job, employees will be able to apply to those specific jobs. I have defined the table in the database to have the "applicants" as an array consisting of the user_id's. However, I seem to not be able to add more than one array to it.
Below is my Recruitment Model
class Recruitment extends Model
{
use HasFactory;
protected $fillable = [
'title',
'salary',
'term_start',
'term_end',
'deadline',
'details',
'status',
'applicants',
];
public function user(){
return $this->belongsTo("\App\Models\User");
}
protected $casts = [
'applicants' => 'array'
];
}
Next is my migration (I am using text format, because the DB on the server is older and does not support json)
public function up()
{
Schema::create('recruitments', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->decimal('salary', 10, 2);
$table->date('term_start');
$table->date('term_end');
$table->date('deadline');
$table->longText('details');
$table->string('status');
$table->text('applicants')->nullable();
$table->timestamps();
});
}
Here is my blade
<div class="container">
<div class="row">
<div class="card col-sm-12 py-3">
<div class="card-header border d-flex justify-content-between align-items-center">
<h3 class="w-75">{{ $job->title }}</h3>
<div class="w-25">
<p class="my-0 my-0">Created at: <span class="text-info">{{ $job->created_at }}</span></p>
<p class="my-0 my-0">Last updated at: <span class="text-primary">{{ $job->updated_at }}</span></p>
</div>
</div>
<div class="card-body">
// display job details here
<form action="{{ route('add-applicant', ['id' => $job->id ]) }}" method="POST" class="col-sm-12 d-flex justify-content-center align-items-center">
#csrf
<input type="text" name="user_id" id="user_id" value="{{ Auth::user()->id }}" hidden>
<button type="submit" class="btn btn-success w-25">Apply</button>
</form>
</div>
</div>
</div>
</div>
and lastly my controller
public function addApplicant($id, Request $reqst){
$job = Recruitment::find($id);
$user[] = $reqst->user_id;
$job->applicants = $user;
$job->save();
return redirect()->back();
}
While this controller will be able to save an array, it unfortunately overwrites the already existing one (let's say a second user applied). When I try to use an array_push, it does nothing, and I still end up with just one value in the array.
Sorry this was a bit of a read, but I appreciate any help I cen get with this. Thanks
Try in
public function addApplicant($id, Request $reqst){
$job = Recruitment::find($id);
$job->applicants = $reqst->user_id;
$job->save();
return redirect()->back();
}
and in Recruitment model should have
public function user()
{
return $this->belongsTo(User::class, 'applicants');
}
and migration file
$table->integer('applicants')->nullable();
I am using live wire and when I try to validate the form it say
Method Livewire\Redirector::withInput does not exist.
and this is my code
Posts.php
<?php
namespace App\Http\Livewire;
use Livewire\Component;
use App\Models\Post;
class Posts extends Component
{
public $title;
public $content;
public function hydrate(){
$this->validate([
'title' => 'required',
'content' => 'required'
]);
}
public function save(){
$data = [
'title' => $this->title,
'content' => $this->content,
'user_id' => Auth()->user()->id
];
Post::create($data);
$this->cleanVars();
}
private function cleanVars(){
$this->title = null;
$this->content = null;
}
public function render()
{
return view('livewire.posts');
}
}
livewire view
<div>
<label>Title</label>
<input wire:model="title" type="text" class="form-control" />
#error('title')
<p class="text-danger">{{ $message }}</p>
#enderror
<label>Content</label>
<textarea wire:model="content" type="text" class="form-control"></textarea>
#error('content')
<p class="text-danger">{{ $message }}</p>
#enderror
<br />
<button wire:click="save" class="btn btn-primary">Save</button>
</div>
also I putted this view in home.blade.php
#extends('layouts.app')
#section('content')
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">{{ __('Dashboard') }}</div>
<div class="card-body">
#livewire('posts')
</div>
</div>
</div>
</div>
</div>
#endsection
Really you need to fix the header of this question, is repeating the same and you're missing something there to the community. I see in your code this and I dislike this use
public function hydrate(){
$this->validate([
'title' => 'required',
'content' => 'required'
]);
}
I mean, this validation running on every hydration isn't a good approach of this. Instead, declare the rules
protected $rules = [// rules here];
//or
public function rules()
{
return [
//rules here
];
}
then you can validate the entries, for example on real-time validation using the validateOnly method inside the updated()
public function updated($propertyName)
{
$this->validateOnly($propertyName, $this->rules());
}
or just use it in the save method
public function save()
{
$this->validate(); // in the protected $rules property
// or
Post::create($this->validate());
}
I have a component called project-form and in that again I am calling another component called search-users. The problem is that I am unable to set the $members property in ProjectForm from nested component i.e search-users.
As I can understand $members must be looking to set in SearchUsers.php but I want that must be set in ProjectForm.php so I could save in db.
project-form.blade.php
<form wire:submit.prevent="submit">
<input wire:model="name"/>
<input wire:model="category"/>
<input wire:model="target_date"/>
#livewire('search-users')
</form>
ProjectForm.php
<?php
namespace App\Http\Livewire;
use App\Models\Project;
use Livewire\Component;
class ProjectForm extends Component
{
public string $name = '';
public string $category = '';
public string $target_date = '';
public array $members = [];
protected $rules = [
'name' => 'required',
'category' => 'required',
'target_date' => 'required',
];
public function submit(){
$validated = $this->validate();
Project::create($validated);
toastr()->success('Project Created Successfully');
}
public function render()
{
return view('livewire.project-form');
}
}
search-users.blade.php
#foreach($users as $user)
<label class="list-group-item ps-0 border-0 d-flex justify-content-between align-items-center">
<div class="d-flex align-items-center">
<img alt="{{ $user->name }}" src="{{ url('storage/'.$user->avatar) }}" width="35" class="me-3 rounded-circle mx-auto d-block">
{{ $user->name }}
</div>
<input class="form-check-input me-1" wire:model.defer="members" type="checkbox" value="{{ $user->id }}">
</label>
#endforeach
As already suggestes by #Qirel you should use Livewire events.
In your search components you could emit an event memebersFound and passing the members from your search as parameter (see Livewire Passing parameters in events) like this
$this->emit('membersFound', $membersFound);
Then, in your ProjectForm component you should listen for this event
protected $listeners = [
'membersFound' => 'addMembers'
];
public function addMembers(array $members)
{
$this->members = $members;
}
I am having issues returning the view on my website i keep getting this error
ErrorException
count(): Parameter must be an array or an object that implements Countable (View: C:\xampp\htdocs\cargo\resources\views\shipment\single.blade.php)
and this error points to a section in my blade file which is causing it, below is my blade file for the view
<div class="card" >
<div class="card-body ">
#if(count($shipment) >0)
#foreach($shipment as $shipment)
<div class="shipment-number">
<span class="title" style="display: block; font-size: 25px!important;">{{$shipment->tracking_code }}</span>
</div><!-- Track_Num -->
</div>
<br><br>
<div id="shipper-info" class="row" >
<div class="col-md-6 detail-section">
<p class="shipper details"><strong>Shipper's Information</strong></p>
<div class="shipper details">
<p><span class="label">Shipper Name : </span>{{$shipment->sender_name }}</p>
<p><span class="label">Phone Number : </span>{{$shipment->telephone }}</p>
<p><span class="label">Email : </span>{{$shipment->sender_email }}</p>
<p><span class="label">Address : </span>{{$shipment->sender_address }}</p>
</div>
</div>
<div class="col-md-6 detail-section">
<p class="shipper details"><strong>Receiver's Information</strong></p>
<div class="receiver details">
<p><span class="label">Receiver Name : </span>{{$shipment->receiver_name }}</p>
<p><span class="label">Phone Number : </span>{{$shipment->receiver_telephone }}</p>
<p><span class="label">Address : </span>{{$shipment->receiver_address }}</p>
<p><span class="label">Email : </span>{{$shipment->receiver_email }}</p>
</div>
</div>
<div class="clear-line"></div>
</div>
#endforeach
#esle
#endif
and the error points to this section
#if(count($shipment) >0)
#foreach($shipment as $shipment)
here is my controller
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Str;
use App\Shipment;
use Illuminate\Foundation\Auth\RegistersUsers;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Facades\Validator;
use App\Http\Controllers\Controller;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\MessageBag;
use Illuminate\Support\Facades\Gate;
class ShipmentController extends Controller
{
/**
* Create a new user instance after a valid registration.
*
* #param Request $request
* #return \App\Shipment
*/
protected function store(Request $request)
{
$shipment = new Shipment();
$data = $this->validate($request, [
'sender_name' => 'required|string|max:255',
'sender_email' => 'required|string|email|max:255',
'receiver_email' => 'required|string|email|max:255',
'sender_address' => 'required|string',
'estimated_Date' => 'required||date|after:today',
'shipment_type' => 'required|string|max:255',
'content' => 'required|string|max:255',
'receiver_name' => 'required|string|max:255',
'receiver_address' => 'required|string|max:255',
'sender_country' => 'required|string|max:255',
'sender_telephone' => 'required|string|max:255',
'comments' => 'required|string|max:255',
'receiver_telephone' => 'required|string|max:255',
'receiver_country' => 'required|string|max:255',
'package_weight' => 'required|string|max:255',
]);
$shipment->sender_name = $request->input('sender_name');
$shipment->receiver_email= $request->input('receiver_email');
$shipment->sender_email= $request->input('sender_email');
$shipment->sender_address= $request->input('sender_address');
$shipment->estimated_Date= $request->input('estimated_Date');
$shipment->shipment_type= $request->input('shipment_type');
$shipment->content= $request->input('content');
$shipment->receiver_name= $request->input('receiver_name');
$shipment->receiver_address= $request->input('receiver_address');
$shipment->sender_country= $request->input('sender_country');
$shipment->sender_telephone= $request->input('sender_telephone');
$shipment->comments= $request->input('comments');
$shipment->receiver_telephone= $request->input('receiver_telephone');
$shipment->receiver_country= $request->input('receiver_country');
$shipment->package_weight= $request->input('package_weight');
$shipment->tracking_code = strtoupper(Str::random(20));
$shipment->save();
return redirect('/index')->with('Success', 'Your Shipment has been created');
}
public function tracking(Request $request){
$this->validate($request,
[
'tracking_code' => 'required|max:25',
]);
$shipment = Shipment::where('tracking_code', $request->input('tracking_code'))->first();
if ( $shipment == null)
{
return redirect('/shipment/track')->with('error', 'Incorect Tracking Number');
}
else{
return view('shipment.single')->with('shipment', $shipment);
}
}
public function view(Shipment $shipment){
$page_title = "view shipment";
if (Gate::allows('isAdmin')) {
return view('shipment.single',compact('shipment'. title));
}
else {
return redirect('/home')->with('error', 'Unauthorized Page');
}
and my routes
Route::Post('/tracking', 'ShipmentController#tracking')->name('tacking');
Route::get('/shipment/view/{shipment}', 'ShipmentController#view')->name('shipment.view');
i cant get around this and have been on it for a while now , any help will be appriciated, i would like for the view to be shown along with all the data parsed for both the input(tracking function) and the single blade (view function)
you don't need to apply loop on single record as you can see it's single record.
<div class="card" >
<div class="card-body ">
<div class="shipment-number">
<span class="title" style="display: block; font-size: 25px!important;">{{$shipment->tracking_code }}</span>
</div><!-- Track_Num -->
</div>
<br><br>
<div id="shipper-info" class="row" >
<div class="col-md-6 detail-section">
<p class="shipper details"><strong>Shipper's Information</strong></p>
<div class="shipper details">
<p><span class="label">Shipper Name : </span>{{$shipment->sender_name }}</p>
<p><span class="label">Phone Number : </span>{{$shipment->telephone }}</p>
<p><span class="label">Email : </span>{{$shipment->sender_email }}</p>
<p><span class="label">Address : </span>{{$shipment->sender_address }}</p>
</div>
</div>
<div class="col-md-6 detail-section">
<p class="shipper details"><strong>Receiver's Information</strong></p>
<div class="receiver details">
<p><span class="label">Receiver Name : </span>{{$shipment->receiver_name }}</p>
<p><span class="label">Phone Number : </span>{{$shipment->receiver_telephone }}</p>
<p><span class="label">Address : </span>{{$shipment->receiver_address }}</p>
<p><span class="label">Email : </span>{{$shipment->receiver_email }}</p>
</div>
</div>
<div class="clear-line"></div>
</div>
Your calling ->first() which is going to return one shipment as opposed to a collection of shipments, you can use ->get() or ->paginate() to get a collection of the models back then iterate over them in your view.
Remove the ->first() when fetching data, use ->get() or ->paginate(x) instead so you can get a collection.
in your blade file, the foreach Loop you are using the same variable as collection and as single data
#foreach($shipment as $shipment)
i recomand you use $shipments for collection as variable and $shipment for the instance.
x just a number
I have two tables, Companies and Projects. A company hasMany projects and a project belongsTo a company.
Company.php model
protected $fillable = [
'id', 'name', 'description'
];
public function projects()
{
return $this->hasMany('App/Project');
}
Project.php model
protected $fillable = [
'name', 'description', 'company_id', 'days'
];
public function company()
{
return $this->belongsTo('App/Company');
}
From my index.blade.php, I list the companies only and I have made them clickable so that when a user clicks on a company listed, they are taken to show.blade.php where the name of the company and the projects that belong to that company are displayed like so.
<div class="jumbotron">
<h1>{{ $company->name }}</h1>
<p class="lead">{{ $company->description }}</p>
</div>
<div class="row">
#foreach($company->projects as $project)
<div class="col-lg-4">
<h2>{{ $project->name }}</h2>
<p class="text-danger">{{ $project->description }}</p>
<p><a class="btn btn-primary" href="/projects/{{ $project->id }}" role="button">View Projects »</a></p>
</div>
#endforeach
</div>
Now am getting an undefined variable $project error. So I decided to declare variable in my show() function of the CompaniesController.php like so
public function show(Company $company)
{
$company = Company::find($company->id);
$projects = Company::find(1)->projects;
return view('companies.show', ['company' => $company, 'projects' => $projects]);
}
And access variable in show.blade.php like so
<div class="jumbotron">
<h1>{{ $company->name }}</h1>
<p class="lead">{{ $company->description }}</p>
</div>
<div class="row">
#foreach($projects as $project)
<div class="col-lg-4">
<h2>{{ $project->name }}</h2>
<p class="text-danger">{{ $project->description }}</p>
<p><a class="btn btn-primary" href="/projects/{{ $project->id }}" role="button">View Projects »</a></p>
</div>
#endforeach
</div>
Now am getting a Class 'App/Project' not found error when I access show.blade.php. I am having a challenge passing company projects to the view. Any help will be appreciated. Here are my routes;
Route::get('/', function () {
return view('welcome');
});
Auth::routes();
Route::get('/home', 'HomeController#index')->name('home');
Route::resource('companies', 'CompaniesController');
Route::resource('projects', 'ProjectsController');
I would be hilarious if I am right....
In your models where defining relations replace App/Project with App\Project. Do the same for Company.... Replace "/" with "\".
You have to namespace Project class properly
Make sure file name is Project.php
Make sure inside Project.php namespace declaration is correct: namespace App;
Make sure class name inside Project.php is 'Project' : class Project extends Model { ...
Make sure you have imported it in controller. use App\Project
After all that done you will not get error:
Class 'App/Project' not found
You have correctly done passing variable in view but have a look here for another examples and methods passing about it:
https://laravel.com/docs/7.x/views
Hope this helps you
You're already using model binding. In your show method, you do not need to find. just return what you need
public function show(Company $company)
{
return view('companies.show', ['company' => $company];
}
In your view, you can then do:
#foreach($company->projects as $project)
...
#endforeach