Laravel 8 - Save multiple checkbox selections with separate field to pivot table - php

Background:
Laravel 8 + Bootstrap 5
I'm pulling a list of licence categories from database to the form.
In the form user is asked to tick which licence to assign to the user. (up to that point I'm OK)
Target
I'd like licence expiry date to be assigned to every category selected.
Code
blade.php
<div class="mb-1"><strong>Assign user's driving licence categories:</strong></div>
#foreach($categories as $category)
<div class="input-group mb-3">
<div class="input-group-text" style="width: 6ch !important;">{{$category->name}}</div>
<div class="input-group-text">
<input class="form-check-input" type="checkbox" name="categories[]" value="{{$category->id}}">
</div>
<div class="input-group-text">Expiry date</div>
<input class="form-control" type="date" name="expiry_date[]">
</div>
#endforeach
Form screenshot
pivot table migration
public function up()
{
Schema::create('driving_licence_category_user', function (Blueprint $table) {
$table->id();
$table->string('driving_licence_category_id');
$table->string('user_id');
$table->string('expiry_date')->nullable();
$table->timestamps();
});
}
models
User
public function drivingLicenceCategory()
{
return $this->belongsToMany('App\Models\DrivingLicenceCategory')
->withPivot('expiry_date')
->withTimestamps();
}
Licence
public function userHasDrivingLicenceCategory()
{
return $this->belongsToMany('App\Models\User');
}
UserController
public function store(Request $request)
{
$request->validate([
'first_name' => 'required',
'last_name' => 'required',
'email' => 'required',
'roles' => 'required',
'categories' => 'required',
'expiry_date' => 'required'
]);
$user = User::create($request->except(['roles', 'categories', 'expiry_date']))
->syncRoles($request->roles)
->drivingLicenceCategory()->sync($request->only('categories'));
//missing code to store the expiry_date information
return redirect()->route('users.index')->with('success', 'User added successfully.');
}
Thank you for spending time on this post :)

Related

Laravel : How to Create Dropdown to Select FOREIGN KEY from Other Table?

i want to ask you how to select FOREIGN KEY (from "doa_id in "doas" table) when user create a new data (to the "notes table) in a form. This is my code :
NoteController.php
public function create()
{
return view('note/create');
}
public function store(Request $request)
{
$userId = Auth::user()->id;
Note::create([
'title' => $request->title,
'detail' => $request->detail,
'user_id' => $userId,
'mood_id' => $request->mood_id,
'doa_id' => $request->doa_id,
]);
return redirect('notes');
}
2021_05_28_020438_create_notes_table.php migration
class CreateNotesTable extends Migration
{
public function up()
{
Schema::create('notes', function (Blueprint $table) {
$table->id('note_id');
$table->string('title');
$table->date('created_at');
$table->date('updated_at');
$table->text('detail');
$table->unsignedBigInteger('user_id');
$table->foreign('user_id')->references('id')->on('users');
//mood FK
$table->unsignedBigInteger('mood_id');
$table->foreign('mood_id')->references('mood_id')->on('moods');
//doa FK
$table->unsignedBigInteger('doa_id');
$table->foreign('doa_id')->references('doa_id')->on('doas');
});
}
public function down()
{
Schema::dropIfExists('notes');
}
}
and this is my dropdown html :
<div class="container">
<label class="form-label text-white" style="font-weight: bold;" for="doa">Doa terkait</label>
<select class="form-select" style="color: #41A7A5" aria-label="Default select example">
<option selected>Pilih doa</option>
</select>
</div>
In Dropdown option, I want to show "doa_name" based on it's "doa_id"
Thank you :)
You can put the logic in the NoteController and the view. For example, to get a collection of all options for the foreign key, pass the collection to the view.
public function create()
{
$doas = Doas::all();
return view('note/create', compact('doas'));
}
Then on the view, you can perform a foreach loop using the select HTML tag.
<div class="container">
<label class="form-label text-white" style="font-weight: bold;" for="doa">Doa terkait</label>
<select class="form-select" style="color: #41A7A5" aria-label="Default select example">
#foreach ($doas as $doa)
<option value="{{$doa-id>}}">{{$doa->name}}</option>
#endforeach
</select>
</div>
After this, it's just using the input in your store() method.

Method Illuminate\Database\Eloquent\Collection::books does not exist.(laravel)

I am beginner of laravel, I want to store a book to books database, but after click button, it shows "Method Illuminate\Database\Eloquent\Collection::books does not exist." What am I missing?
here are my codes.
BookController
public function create()
{
return view('books.create');
}
public function store(Request $request)
{
$this->validate($request, [
'book' => 'required|max:255',
'category' => 'required',
'quantity' => 'required|numeric',
'price'=>'required|numeric',
'info'=>'required'
]);
//$request->user()->member()->books()->create([
$member=auth()->user()->member()->get();
$member->books()->create([
'book' => $request->book,
'category' => $request->category,
'quantity' => $request->quantity,
'price'=>$request->price,
'info'=>$request->info
]);
return redirect('shops')->with('success', 'successful');
}
books.create
<form action="{{route('books.store')}}" method="POST" role="form">
#csrf
#method('POST')
<div class="form-group">
<label for="book">name:</label>
<input id="book" name="book" class="form-control" placeholder="enter book name">
</div>
<div class="form-group">
<label for="category">category:</label>
<input id="category" name="category" class="form-control" placeholder="enter category">
</div>
<div class="form-group">
<label for="quantity">quantity:</label>
<input id="quantity" name="quantity" class="form-control" placeholder="enter quantity">
</div>
<div class="form-group">
<label for="price">price:</label>
<input id="price" name="price" class="form-control" placeholder="enter price">
</div>
<div class="form-group">
<label for="info">info:</label>
<textarea id="info" name="info" class="form-control" rows="10" placeholder="enter info"></textarea>
</div>
<button type="submit" class="btn-sm btn-primary">create</button>
</form>
User and Member is one to one relation, and Book belongs to one Member
Book Model
public function member()
{
return $this->belongsTo(Member::class);
}
protected $fillable = ['book','category','quantity','price','info'];
Member Model
public function books()
{
return $this->hasMany(Book::class);
}
public function user()
{
return $this->belongsTo(User::class);
}
User Model
public function member()
{
return $this->hasOne(Member::class);
}
books,user and member migration
books migration
public function up()
{
Schema::create('books', function (Blueprint $table) {
$table->increments('id');
$table->unsignedInteger('member_id');
$table->foreign('member_id')->references('id')->on('members')->onDelete('cascade');
$table->string('name');
$table->integer('quantity');
$table->integer('price');
$table->string('path');
$table->string('info');
$table->string('category');
$table->timestamps();
});
}
member migration
public function up()
{
Schema::create('members', function (Blueprint $table) {
$table->increments('id');
$table->unsignedbigInteger('user_id');
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->string('sex');
$table->string('email');
$table->string('address');
$table->string('tel');
$table->timestamps();
});
}
user migration
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->foreignId('current_team_id')->nullable();
$table->text('profile_photo_path')->nullable();
$table->timestamps();
});
}
You are receiving a Collection from this chain of calls:
$member = auth()->user()->member()->get();
get is going to always return a Collection when called on a relationship method. If you want a single model you can call first instead:
$member = auth()->user()->member()->first();
Though first could return null so you may need to check that.
Another method to access the result of this relationship would be to use the dynamic property for the relationship member:
$member = auth()->user()->member;
Since that relationship is defined as a HasOne it knows to load it for a single result or null.
Assuming $member isn't null at this point you should be fine with the rest how it is.
$member=auth()->user()->member()->get(); returns a collection not an object of Member class. Use $member=auth()->user()->member()->first(); or $member=auth()->user()->member;
Try this
public function store(Request $request)
{
$this->validate($request, [
'book' => 'required|max:255',
'category' => 'required',
'quantity' => 'required|numeric',
'price'=>'required|numeric',
'info'=>'required'
]);
$member=auth()->user()->member;
if($member){
$member->books()->create([
'book' => $request->book,
'category' => $request->category,
'quantity' => $request->quantity,
'price'=>$request->price,
'info'=>$request->info
]);
return redirect('shops')->with('success', 'successful');
}
//Member is not found, return with error
return redirect()->back()->with('error', 'Member not found');
}
That error is due to the fact that this call $member=auth()->user()->member()->get();. It's supposed to return a Collection of Member.
So when you try to call books on a collection hold by the variable member It' won't succeed as Illuminate\Support\Collection Class doesn't define a method books you have to loop trought that collection by using a foreach loop or a each or map method from Collection.
$member->each(function($member){
$member->books()->create([
//
]);
});
Or has you have already define in User Model that user will always have a single Member by using hasOne method.
So you can use auth()->user()->member()->first(); which return a single instance of type Member on which you call books method but with that you have to be sure that the Authenticated use has already one member which is attached to him to avoid any error. even though that is the case you can always check if variable $member is not null with an if statement
$member = auth()->user()->member()->first();
if($member){
// here you can have access to `books`
$member->books()->create([
//...
]);
}

Resolving "Integrity constraint violation: 19 NOT NULL", what's the most proper solution?

Trying to write a function to create a new "profile" in my profiles table and get the following error:
"SQLSTATE[23000]: Integrity constraint violation: 19 NOT NULL constraint failed: profiles.about (SQL: insert into "profiles" ("dateofbirth", "state", "zipcode", "profilepic", "user_id", "updated_at", "created_at") values (2020-04-15, FL, 12345, /tmp/phpTT6CZr, 1, 2020-04-30 00:48:23, 2020-04-30 00:48:23))"
I've been reading answers to similar questions for the past few hours. Tried several different things, no luck so far. Hoping to see a solution that works in my code, and also get a better understanding of where exactly the error begins. The error message leads me to believe it's something to do with my "about" section in table. But unsure. I thought adding " protected $guarded = []; " to controller would solve but that gave the same result.
Here is what I'm working with:
Migration File:
public function up()
{
Schema::create('profiles', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('user_id'); //foreign key
$table->text('about')->nullable;
$table->text('profilepic')->nullable;
$table->date('dateofbirth')->nullable;
$table->unsignedinteger('zipcode')->nullable;
$table->string('state')->nullable;
$table->timestamps();
$table->index('user_id'); //index for foreign key
});
}
Profile Model:
class profile extends Model {
protected $guarded = [];
public function user()
{
return $this->belongsTo(User::class);
} }
I have also tried changing the profile model like below:
class profile extends Model {
public function user()
{
return $this->belongsTo(User::class);
}
/**
* The attributes that should be cast to native types.
*
* #var array
*/
protected $casts = [
'dateofbirth' => 'datetime',
'zipcode' => 'unsignedinteger'
];
/*
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'about','profilepic','state', 'user_id', 'updated_at', 'created_at'
]; }
They both provide the same error message but with slightly different array values
Here is my controller store function:
public function store()
{
$data = request()->validate([
'dateofbirth' => 'required',
'state' => 'required',
'zipcode' => 'required',
'profilepic' => 'image'
]);
auth()->user()->profile()->create($data);
dd(request()->all());
}
Here is the view:
#extends('layouts.app')
#push('styles')
<link href="{{ asset('css/profile.css') }}" rel="stylesheet">
#endpush
#section('content')
{{-- This needs to present a create profile form --}}
<div class="row">
<h1 class="pl-4">CREATE YOUR PROFILE</h1>
</div>
<form action="/profile" class="pl-4" enctype="multipart/form-data" method="post">
#csrf
<div class="form-group row">
<label for="profilepic"
class="col-md-4 ocl-form-label"
>Upload a Profile Picture</label>
<input type="file"
class="form-control-file"
id="profilepic"
name="profilepic">
</div>
<div class="form-group">
<label for="about">Write your "About" Section here. What do you want us to know about you?</label>
<textarea type="text" class="form-control" id="about" name="about" rows="3"></textarea>
</div>
<div class="form-group">
<label for="dateofbirth">Date of Birth</label>
<input type="date"
id="dateofbirth"
name="dateofbirth">
</div>
<div class="form-group">
<label for="zipcode">Zipcode</label>
<input type="text" id="zipcode" name="zipcode">
</div>
<div class="form-group">
<label for="State">State</label>
<input type="text" id="state" name="state">
</div>
<div class="form-group row pt-4">
<button class="btn btn-primary">Submit</button>
</div>
</form> #endsection
That error means you're trying to set a foreign key column as null which is unacceptable, in this case, user_id on profiles table. Try to modify your code as such:
In your Profile model, add mass assignment columns:
protected $fillable = ['dateofbirth', 'state', 'zipcode', 'profilepic'];
In your controller store method:
//assuming the route method is authenticated such that there's always a logged in user
$user = auth()->user();
$data['user_id'] = $user->id;
$profile = Profile::create($data);
I'll add in also, I have since gotten this resolved with implementing #djunehor's answer. But one thing that helped get the problem resolved was adding in this to the controller:
public function store(Request $request)
At first I was not passing the request in and saving it to a variable like this, but this step seems to have made a big difference for the errors I was running into.
At first I was just doing this:
public function store()

No Message error when submitting a post request

I'm trying to post data to a database using a post request. I'm also using data from an Input in a previous page.
I.e
User visits profile & adds info into a form
The form data is posted to a controller and then create view returned with input data
The form in the create view is pre-populated by the previous data (from controller)
the user should be able to submit the form, but it throws no message error
I've noticed the URL is /prebook opposed to /booking/create (this is due to the profile page passing data into a controller and it outputting.
Any ideas?
Profile Controller
public function prebook() {
$date = Input::get('query', '01/01/2010');
$guests = Input::get('guests', '2');
$restaurant = Input::get('restaurantID', '2');
$restaurantName = Input::get('restaurantName', '2');
$time = Input::get('timeFrom', '2');
return view('userbookings.create')->with('date', $date)
->with('guests', $guests)
->with('restaurant', $restaurant)
->with('restaurantName', $restaurantName)
->with('time', $time);
}
Post form code
{!! Form::open(array('route' => 'user.bookings.store','method'=>'POST')) !!}
#include('userbookings.form')
{!! Form::close() !!}
Create Form (example input field)
<div class="row">
<div class="col-md-3">
<p>Party Size:</p>
</div>
<div class="col-md-9">
<div class="form-group">
<input required type="number" class="form-control" value="{{$guests}}" id='partySize' name='PartySize'>
</div>
</div>
</div>
Store Method in Controller
public function store(Request $request)
{
request()->validate([
'date' => 'required',
'timeFrom' => 'required',
'timeTo' => 'required',
'partySize' => 'required',
'status' => 'required',
'comments' => 'required',
]);
Booking::create($request->all());
return redirect()->route('user.bookings.index')
->with('success','Booking created successfully');
}
Migration Code:
Schema::create('bookings', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users');
**$table->string('date');**
**$table->string('timeFrom');**
$table->string('timeTo');
**$table->string('partySize');**
$table->string('status');
$table->text('comments');
**$table->text('businessID');**
$table->timestamps();
});

Save a File To mysql Database From a form using laravel

Good day Everyone, I'm less than 1 week old in laravel. I'm trying to save a Register CV page to MySQL database. Although my Form contains an upload file. While saving it to the database only the name of the file is saved the file itself isnt there.
My code goes thus.
RegisterController.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\candidate;
use App\Http\Requests;
class RegisterController extends Controller
{
public function register(Request $request) {
$this->validate($request, [
'surname' => 'required',
'other_name' => 'required',
'email' => 'required',
'phone' => 'required',
'gender' => 'required',
'field' => 'required',
'qualification' => 'required',
'resume' => 'required'
]);
$candidates = new Candidate;
$candidates->surname = $request->input('surname');
$candidates->other_name = $request->input('other_name');
$candidates->email = $request->input('email');
$candidates->phone = $request->input('phone');
$candidates->gender = $request->input('gender');
$candidates->field = $request->input('field');
$candidates->qualification = $request->input('qualification');
$candidates->resume = $request->input('resume');
$candidates->save();
return redirect('/career')->with('response', 'Registered Successfully');
}
}
2018_03_28_152114_create_candidates_table.php
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateCandidatesTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('candidates', function (Blueprint $table) {
$table->increments('id');
$table->string('surname');
$table->string('other_name');
$table->string('email');
$table->string('phone');
$table->string('gender');
$table->string('field');
$table->string('qualification');
$table->string('resume');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('candidates');
}
}
then the form
<form class="form-horizontal pv-20" action="/career/test-apply" method="POST" role="form">
<input type="hidden" name="_token" value="{{ csrf_token() }}">
.........
........
<div class="form-group">
<label class="col-sm-2" for="resume">Upload Resume</label>
<div class="col-sm-10">
<input class="form-control" type="file" name="resume" id="resume" accept="application/pdf">
</div>
</div>
<div class="form-group">
<label class="col-sm-6" for="resume"></label>
<div class="col-sm-6">
<button type="submit" class="btn btn-default btn-curve btn-animated pull-right">Submit <i class="fa fa-play"></i></button>
</div>
</div>
</form>
You can save the file in the Public directory of your project. Then, you can just save the name of the file in MySQL database.

Categories