Multi-select dropdown with Many to many relation - laravel

In my laravel project I created three tables as employees, teams and employee_teams. There is many to many relationship in "employee_teams" tables, with the foreign keys of employee_id and team_id.
"employee_teams" table DB structure
id | employee_id | team_id
In the Employee form there is a multi-select dropdown which helps to assign multiple teams for the particular employee.
<select name="namedropdown[]" id="namedropdown" class="selectpicker" multiple data-live-search="true">
<option value="" disabled selected>Nothing selected</option>
#foreach ($tdropdown as $key => $tdrop)
<option value="{{$key}}">{{$tdrop}}</option>
#endforeach
</select>
What I want is to save "team_id" and "employee_id", to the "employee_teams" table.
Here is employee model
class employee extends Model
{
public function teams()
{
return $this->belongsToMany(team::class, 'employee_teams');
}
}
Here is team model
class team extends Model
{
public function employees()
{
return $this->belongsToMany(employee::class, 'employee_teams');
}
}
Here is employee_team table migration
class CreateEmployeeTeamsTable extends Migration
{
public function up()
{
Schema::create('employee_teams', function (Blueprint $table) {
$table->increments('id');
$table->integer('employee_id')->unsigned();
$table->integer('team_id')->unsigned();
$table->foreign('employee_id')->references('id')->on('employees')->onDelete('cascade');
$table->foreign('team_id')->references('id')->on('teams')->onDelete('cascade');
$table->timestamps();
});
}
Here is store function in employee controller
use App\employee;
use App\team;
use App\employee_team;
// codes
$employee = new employee();
$employee->namedropdown = implode(',', $request->input('namedropdown')); //Already save multi-select dropdown ids to the database
$employee->save();
$employee_team = new employee_team();
$employee->teams()->attach($employee->namedropdown);
return redirect()->route('employee.index')->with('success','Data Added');
}
Error comes as SQLSTATE[01000]: Warning: 1265 Data truncated for column 'team_id' at row 1
Please help me to save employee_id and team_id to the "employee_teams" table. Thank you so much.

A working sample (tested):
Migration: 2020_06_16_000000_create_employees_table.php
class CreateEmployeesTable extends Migration
{
public function up()
{
Schema::create('employees', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('employees');
}
}
Migration: 2020_06_16_000000_create_teams_table.php
class CreateTeamsTable extends Migration
{
public function up()
{
Schema::create('teams', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('teams');
}
}
Migration: 2020_06_16_000000_create_employee_team_table.php
class CreateEmployeeTeamTable extends Migration
{
public function up()
{
Schema::create('employee_team', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('employee_id')->nullable();
$table->foreign('employee_id')->references('id')->on('employees')->onDelete('cascade');
$table->unsignedBigInteger('team_id')->nullable();
$table->foreign('team_id')->references('id')->on('teams')->onDelete('cascade');
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('employee_team');
}
}
Model: Employee.php
class Employee extends Model
{
public function teams()
{
return $this->belongsToMany('App\Team');
}
}
Model: Team.php
class Team extends Model
{
public function employees()
{
return $this->belongsToMany('App\Employee');
}
}
Routes: routes/web.php:
Route::get('/select_team/{id?}', 'EmployeeController#select_team')->name('employee.select_team');
Route::post('/save_teams/{id?}', 'EmployeeController#save_teams')->name('employee.save_teams');
Controller: EmployeeController.php
use Illuminate\Http\Request;
use App\Team;
use App\Employee;
class EmployeeController extends Controller
{
public function select_team($employee_id){
return view('select_team', ['tdropdown'=>Team::all(), 'employee'=>Employee::find($employee_id)]);
}
public function save_teams(Request $request, $employee_id){
$employee = Employee::find($employee_id);
foreach ($request->namedropdown as $team_id){
$employee->teams()->attach($team_id);
}
return redirect()->route('employee.index')->with('success','Data Added');
}
}
Blade: select_team.blade.php
<!DOCTYPE html>
<form action="/save_teams/{{$employee->id}}" method="post">
#csrf
<select name="namedropdown[]" id="namedropdown" class="selectpicker" multiple data-live-search="true">
<option value="" disabled selected>Nothing selected</option>
#foreach ($tdropdown as $tdrop)
<option value="{{$tdrop->id}}">{{$tdrop->name}}</option>
#endforeach
</select>
<button>Submit</button>
</form>
</html>
I think it's a good example that can give you an idea.

Related

Retriving All Polymorphic Relations in Laravel

I've created polymorphic relations in my project. when i want to retrieve them like below
return view('category.index')->with('categories', Category::all()) ;
It returns the relations when i dd() them. However when I want to access the relation in view
when i call it in view it gives me the following result
{"id":1,"image":"abc\/abc.jpg","imageable_id":6,"imageable_type":"App\\Category","created_at":"2020-07-24T13:37:29.000000Z","updated_at":"2020-07-24T13:37:29.000000Z"}
but when i want to access the id or image index it says
Trying to get property 'id' of non-object (View:
D:\WaheedSindhani\Projects\Menu\menu_proj\resources\
views\category\index.blade.php)
i am not picking it up what is happening here
#if(isset($categories))
#foreach($categories as $category)
<tr>
<th scope="row">{{$loop->index+1}}</th>
<td>{{$category->name}}</td>
<td>{{$category->images->image}}</td>
</tr>
#endforeach
#endif
It says no attribute named image found.
Migration are as below
Images Table
public function up()
{
Schema::create('images', function (Blueprint $table) {
$table->id();
$table->string('image');
$table->unsignedInteger('imageable_id');
$table->string('imageable_type');
$table->timestamps();
});
}
Menus Table
public function up()
{
Schema::create('menus', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->boolean('visible');
$table->integer('priority');
$table->timestamps();
});
}
Categories Table
public function up()
{
Schema::create('categories', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->boolean('visibility');
$table->integer('priority');
$table->timestamps();
});
}
Models are as follow
class Menu extends Model
{
public function images()
{
return $this->morphMany( 'App\Image', 'imageable');
}
}
class Image extends Model
{
protected $guarded = [];
public function imageable(){
return $this->morphTo();
}
}
class Category extends Model
{
protected $guarded = [];
public function images()
{
return $this->morphMany(Image::class, 'imageable');
}
}
your problem occurs because the category->images is a Collection of images, not a single image. Because your relation is one to many, not one to one relationship so the soultion would be to loop over the images using a each loop and then do your work there.
that is why you are getting the error that you are trying to access a prop on a non-object.
#if(isset($categories))
#foreach($categories as $category)
<tr>
<th scope="row">{{$loop->index+1}}</th>
<td>{{$category->name}}</td>
#foreach($category->images as $image)
<td>{$image->name}</td>
#endforeach
</tr>
#endforeach
#endif
and this concept is true for every relationship that has a Many in them, hasMany, belongsToMany, etc...

Laravel: Retrieving Data in Loop in a One to Many Relationship

I'm using Laravel 5.8. Here's my code...
CreateSchoolsTable migration
public function up()
{
Schema::create('schools', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->timestamps();
});
}
CreateStudentsTable migration
public function up()
{
Schema::create('students', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('school_id');
$table->string('first_name');
$table->timestamps();
});
}
School model
class School extends Model
{
public function students()
{
return $this->hasMany('App\Student');
}
}
Student Model
class Student extends Model
{
public function school()
{
return $this->belongsTo('App\School');
}
}
Controller
class SchoolsController extends Controller
{
public function index()
{
$schools = School::all();
return view('schools.index', compact('schools'));
}
}
My view: views>schools>index.blade.php
#foreach ($schools as $school)
{{ $school->students->first_name }}
#endforeach
I want to display all the first names in the loop and $school->students->first_name gives me an error.
Property [first_name] does not exist on this collection instance. (View: /Users/philginsburg/Laravel/project1/resources/views/schools/index.blade.php)
When I echo out $school->students it displays an array of the students table, but not sure why I cant loop through with the field name like first_name.
In this case you are dealing with 2 Collections: schools and students (of each school), so you should use 2 different loop to loop through those collections, like this:
#foreach ($schools as $school)
<p>In this school there are those students:</p>
<ul>
#foreach($school->students as $student)
<li>{{ $student->first_name }}</li>
#endforeach
</ul>
#endforeach
The reason is $school->students is array, there is no property called first_name.
you need to
#foreach ($school->students as $student)
{{ $student->first_name }}
#endforeach

Get category and Sub_subcategories list using query builder

How to get a list of Category and subcategories like this:
1 mobile
apple
samsung
nokia
2:Laptops
Mac
HP
Dell
Sony
3:Tvs
Samsung
using query builder in controller and foreach loop in view
My Controller
$sub_catagories = DB::table('books_categories')
->join('sub_catagories','sub_catagories.catId','=','books_categories.catId')->get();
return view('index',compact('sub_catagories'));
My category table
public function up()
{
Schema::create('books_categories', function (Blueprint $table) {
$table->increments('catId');
$table->string('catName', 50)->nullable(false);
$table->timestamps();
});
}
My sub_catagory table
public function up()
{
Schema::create('sub_catagories', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->integer('catId');
$table->timestamps();
});
}
I've written some example of whole cycle. There is convention in laravel to use unique auto increment 'id's, and have foreign keys like RELATION_id. So if you want to change the table and column names anyway, you can do that with following to this example:
Category Model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Category extends Model
{
protected $table = 'categories';
protected $fillable = [
'id',
'name',
];
public function subcategories(){
return $this->hasMany(Subcategory::class, 'category_id', 'id');
}
}
Subcategory Model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Subcategory extends Model
{
protected $table = 'subcategories';
protected $fillable = [
'id',
'category_id',
'name',
];
public function category(){
return $this->belongsTo(Category::class, 'category_id');
}
}
categories table Migration
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateCategoriesTable extends Migration
{
public function up()
{
Schema::create('categories', function (Blueprint $table) {
// PRIMARY
$table->bigIncrements('id');
// ADDITIONAL
$table->string('name');
// TIME
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('categories');
}
}
subcategories table Migration
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateSubcategoriesTable extends Migration
{
public function up()
{
Schema::create('subcategories', function (Blueprint $table) {
// PRIMARY
$table->bigIncrements('id');
// FOREIGN
$table->unsignedBigInteger('category_id')->nullable();
$table->foreign('category_id')->references('id')->on('categories')->onDelete('cascade')->onUpdate('cascade');
// ADDITIONAL
$table->string('name');
// TIME
$table->timestamps();
});
}
public function down()
{
Schema::dropIfExists('subcategories');
}
}
usage in controller
// 1
public function categories()
{
$categories = Category::all()->get();
return view('categories', [
'categories' => $categories,
]);
}
// 2
public function catsWithSubcats()
{
$cats_with_subcats = Category::with('subcategories')->get();
return view('cats_with_subcats', [
'categories' => $cats_with_subcats,
]);
}
// 3
public function subcatsWithCats()
{
$subcats_with_cats = Subcategory::with('category')->get();
return view('subcats_with_cats', [
'subcategories' => $subcats_with_cats,
]);
}
If you want to show all categories with their subcategories in the blade, you don't need to use 2nd or 3rd method, just use 1st method. Create "categories.blade.php" inside of "resources/views/..." and write there something like this:
#foreach($categories as $category)
#foreach($category->subcategories as $subcategory)
<p>{{ $subcategory->name }}</p>
#endforeach
#endforeach

Eloquent - How to match data between tables of a single ID

Having multiple tables with data that relates to each other, i'm trying to display that data in a view using Laravel.
I must be confused with how Laravel runs its queries and I need help to sort how to do, what in PHP&SQL would be a left join.
My Asset Model:
public function category(){
return $this->hasOne(Category::class);
}
My Category Model:
public function asset()
{
return $this->belongsTo(Asset::class);
}
My Country Model:
public function country()
{
return $this->belongsTo(Asset::class);
}
And my AssetsController:
public function asset($id)
{
$asset = Asset::find($id);
return view('admin.assets.asset')->with('assets', $asset);
}
And the Router:
Route::get('/admin/assets/asset/{id}', [
'uses' => 'AssetsController#asset',
'as' => 'assets.asset'
//Show the Asset
]);
And the View:
<p><strong>Price:</strong>{{$assets->price}} €</p>
<p><strong>Description:</strong>{{$assets->description}}</p>
<p><strong>Country:</strong>{{$assets->country}}</p>
<p><strong>Category:</strong>{{$assets->name}}</p>
So in the 'asset.blade.php' I get the id from a previous index.blade.php that has a list of all the assets. I want to get via the ID, an asset page that displays the category name and the country name, instead of the ID that belongs to the Asset table.
So it should echo something like $assets->country->country_name and $assets->category->name
dd($asset);
EDIT: Additional information about migrations
categories_table migration
public function up()
{
Schema::create('categories', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('url');
$table->timestamps();
});
}
assets_table migration:
public function up()
{
Schema::create('assets', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->double('price',15,2);
$table->mediumText('description');
$table->integer('country');
$table->integer('category');
$table->integer('subcategory');
$table->integer('subsubcategory');
$table->integer('broker');
$table->string('featured');
$table->string('slug');
$table->timestamps();
});
}
Got it working.
class Category
{
public function asset()
{
return $this->hasMany(Asset::class);
}
}
class Asset
{
public function category()
{
return $this->belongsTo(Category::class);
}
}
use App\Asset;
use App\Category;
use App\Country;
use App\Subcategory;
use Illuminate\Http\Request;
class AssetController extends Controller
{
public function asset($id)
{
$asset = Asset::find($id);
return view('admin.assets.asset')
->with('asset', $asset)
->with('category', Category::all())
->with('subcategory', Subcategory::all())
->with('country', Country::all());
}
}
The other models have the same relationship towards the Asset model and vice-versa.
The View:
<p><strong>Category:</strong>{{$asset->category->name}}</p>
<p><strong>Sub-Category:</strong>{{$asset->subcategory->name}}</p>
It now shows the name matching the id of the corresponding tables.

Eloquent Relationship returning empty array

I'm New to laravel and I'm trying to achieve something very basic stuff but still getting stuck.
I have two models namely Post.php and Like.php
I'm trying to fetch all the likes linked to a post using eloquent relationship but it is returning an empty array. Here is my code-
Post.php
public function likes(){
return $this->hasMany('App\Like');
}
Route.php
Route::get('/', function(){
$posts = Post::all()->sortByDesc("post_id");
return view('index')->with(['posts' => $posts]);
});
View.blade.php
#foreach($posts as $post)
{{ $post->likes }}
#endforeach
What am I doing wrong here?
Update-
likes table migration
public function up()
{
Schema::create('likes', function (Blueprint $table) {
$table->increments('like_id');
$table->integer('post_id')->unsigned();
$table->integer('user_id')->unsigned();
$table->foreign('post_id')->references('post_id')->on('posts')->onDelete('cascade');
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->timestamps();
});
}
Post Migration
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->increments('post_id');
$table->integer('user_id')->unsigned();
$table->string('post_message');
$table->timestamps();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
});
}
Post Model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Post extends Model
{
public function user(){
return $this->belongsTo('App\User');
}
public function likes(){
return $this->hasMany('App\Like');
}
}
Laravel expects the primary key to be id, but you are using the custom post_id.
Specify it in your model and adjust the relationship:
class Post extends Model {
protected $primaryKey = 'post_id';
public function likes() {
return $this->hasMany('App\Like', 'post_id');
}
}

Resources