I am a beginner of laravel. I want to join some of the tables and getting it displayed in datatables, I am using yajra datatables. I have four tables which are Schedule, Trip, BusTransport and BusConductor. The issues that I facing right now is I wan to display Schedule in a blade view, I want to get trip_id from Trip Table, bus_id from BusTransport Table and bus_conductor_id from BusConductor Table. I able to display the data for Trip and BusConductor but I keep getting an error for one of the field from BusTransport. It shows me that DataTables warning: table id=example - Exception Message: Trying to get property 'bus_code' of non object. Can anyone help me to spot my problem? Thanks and appreciate.
Trip Table
public function up()
{
Schema::create('trip', function (Blueprint $table) {
$table->engine = 'InnoDB';
$table->bigIncrements('id');
$table->string('trip_code')->unique();
$table->string('trip_origin');
$table->string('trip_destination');
$table->date('depart_date');
$table->time('depart_time');
$table->timestamps();
});
}
BusTransport Table
public function up()
{
Schema::create('bus_transport', function (Blueprint $table) {
$table->engine = 'InnoDB';
$table->bigIncrements('id');
$table->string('bus_code')->unique();
$table->string('bus_number_plate');
$table->timestamps();
});
}
BusConductor Table
public function up()
{
Schema::create('bus_conductor', function (Blueprint $table) {
$table->engine = 'InnoDB';
$table->bigIncrements('id');
$table->string('bus_conductor_name');
$table->string('bus_conductor_contact_number');
$table->timestamps();
})
Schedule Table
public function up()
{
Schema::create('schedule', function (Blueprint $table) {
$table->engine = 'InnoDB';
$table->bigIncrements('id');
$table->string('schedule_code')->unique();
$table->bigInteger('trip_id')->unsigned();
$table->bigInteger('bus_id')->unsigned();
$table->bigInteger('bus_conductor_id')->unsigned();
$table->timestamps();
});
Schema::table('schedule', function (Blueprint $table) {
$table->foreign('trip_id')->references('id')->on('trip')->onUpdate('cascade');
$table->foreign('bus_id')->references('id')->on('bus_transport')->onUpdate('cascade');
$table->foreign('bus_conductor_id')->references('id')->on('bus_conductor')->onUpdate('cascade');
});
}
Trip Model
class Trip extends Model
{
use HasFactory;
protected $table = 'trip';
protected $fillable = [
'trip_code',
'trip_origin',
'trip_destination',
'depart_date',
'depart_time'
];
public function schedule()
{
return $this->hasMany(Schedule::class);
}
}
BusTransport Model
class BusTransport extends Model
{
use HasFactory;
protected $table = 'bus_transport';
protected $fillable = [
'bus_code',
'bus_number_plate'
];
public function schedule()
{
return $this->hasMany(Schedule::class);
}
}
BusConductor Model
class BusConductor extends Model
{
use HasFactory;
protected $table = 'bus_conductor';
protected $fillable = [
'bus_conductor_name',
'bus_conductor_contact_number'
];
public function schedule()
{
return $this->hasMany(Schedule::class);
}
}
Schedule Model
class Schedule extends Model
{
use HasFactory;
protected $table = 'schedule';
protected $fillable = [
'schedule_code',
'trip_id',
'bus_id',
'bus_conductor_id'
];
public function trip(){
return $this->belongsTo(Trip::class);
}
public function busTransport(){
return $this->belongsTo(BusTransport::class);
}
public function busConductor()
{
return $this->belongsTo(BusConductor::class);
}
}
Ajax request for Schedule datatables
<script type="text/javascript">
$(function() {
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
var table = $('.table-striped.first').DataTable({
processing: true,
serverSide: true,
ajax: "{{ route('schedule.list') }}",
columns: [{
data: 'schedule_code',
name: 'schedule_code'
},
{
data: 'trip_code',
name: 'trip_code'
},
{
data: 'bus_code',
name: 'bus_code'
},
{
data: 'bus_conductor_name',
name: 'bus_conductor_name'
},
{
data: 'action',
name: 'action',
orderable: true,
searchable: true
},
]
});
Schedule Controller
public function schedule(Request $request)
{
if ($request->ajax()) {
$data = Schedule::with('trip', 'busTransport', 'busConductor')->get();
return Datatables::of($data)
->addIndexColumn()
->addColumn('trip_code', function($row){
return $row->trip->trip_code;
})
->addColumn('bus_code', function($row){
return $row->busTransport->bus_code;
})
->addColumn('bus_conductor_name', function($row){
return $row->busConductor->bus_conductor_name;
})
->addColumn('action', function($row){
$btn = 'Edit';
$btn = $btn.' <i class="far fa-trash-alt btn-outline-danger"></i>';
return $btn;
})
->rawColumns(['trip_code', 'bus_code', 'bus_conductor_name', 'action'])
->make(true);
}
return view('admin.schedule', compact('trips', 'busTransports', 'busDrivers', 'busConductors'));
}
Please try in your Schedule Model
public function busTransport(){
return $this->belongsTo(BusTransport::class, 'bus_id', 'id');
}
Related
I have three tables locations, unique_routes and tours, migration example is below.
// locations table
public function up() {
Schema::create('locations', function (Blueprint $table) {
$table->increments('id');
$table->string('name')->unique();
// extra data ...
});
}
// unique_routes table
public function up() {
Schema::create('unique_routes', function (Blueprint $table) {
$table->increments('id');
$table->integer('location_id_1')->unsigned();
$table->integer('location_id_2')->unsigned();
// extra data ...
});
Schema::table('unique_routes', function (Blueprint $table) {
$table->foreign('location_id_1')->references('id')->on('locations')->onDelete('cascade');
$table->foreign('location_id_2')->references('id')->on('locations')->onDelete('cascade');
});
}
// tours table
public function up() {
Schema::create( 'tours', function ( Blueprint $table ) {
$table->increments( 'id' );
// extra data ...
$table->integer( 'unique_route_id' )->unsigned();
$table->boolean( 'reverse_route' )->default( 0 );
// extra data ...
} );
Schema::table( 'tours', function ( Blueprint $table ) {
$table->foreign( 'unique_route_id' )->references( 'id' )->on( 'unique_routes' );
} );
}
And Models:
class Tour extends Model {
public function unique_route() {
return $this->belongsTo( Route::class, 'route_id', 'id' );
}
}
class UniqueRoute extends Model {
public function location_one() {
return $this->belongsTo('App\Location', 'location_id_1', 'id');
}
public function location_two() {
return $this->belongsTo('App\Location', 'location_id_2', 'id');
}
}
If I need location one name from unique route from tour:
$tour->route->location_one->name
It works OK.
The problem is that sometimes I need location_two object if "reverse_route" on tours is true! The question that I have is, how can I set conditional on Model? Or is there another approach?
I'm trying to understand how I can join the tables users and teams to members in fact ?
Users Table:
id | name | email | password
1 alain alain#gmail.com *****
2 eric eric1#gmail.com *****
Teams Table:
id | name
1 R.O.S
2 Stephanois
Members Table:
id | user_id (email) | team_id (name)
1 1 1
2 2 1
DataBase:
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('email')->unique();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
public function up()
{
Schema::create('members', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned()->nullable();
$table->foreign('user_id')->references('id')->on('users');
$table->integer('team_id')->unsigned()->nullable();
$table->foreign('team_id')->references('id')->on('teams');
$table->timestamps();
});
}
public function up()
{
Schema::create('teams', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->integer('user_id')->unsigned()->nullable();
$table->foreign('user_id')->references('id')->on('users');
$table->timestamps();
});
}
User Model:
protected $fillable = [
'name', 'email', 'password',
];
public function team(){
return $this->hasOne('App\Team', 'user_id', 'id'); ?
}
public function member(){
return $this->hasOne('App\Member', 'user_id', 'id'); ?
}
Team Model:
protected $fillable = [
'user_id', 'name'
];
public function member(){
return $this->hasMany('App\Member', 'team_id'); ?
}
public function user(){
return $this->belongsTo('App\User', 'id', 'user_id'); ?
}
Member Model:
protected $fillable = [
'id', 'user_id', 'team_id'
];
public function team(){
return $this->belongsTo('App\Team', 'team_id');
}
public function user(){
return $this->belongsTo('App\User', 'id', 'user_id'); ?
}
I thank you in advance for your help
Edit: when I log in with the user 'alain#gmail.com' I don't retrieve the information for the user 'alain#gmail.com' ? ie user_id and team_id.
public function index(Request $request)
{
$user = $request->user();
$members = Member::query()
->when($user->hasRole('admin') !== true, function (Builder $query) use ($user) {
$query->where('id???', $user->email); ????
})
->when($request->has('search'), function (Builder $query) use ($request) {
$query->where('name??', 'like', '%' . $request->input('search') . '%');
})->with('team:id,name')
->paginate(5);
return view('admin.members.index', compact('members'))
->with('display_search', $user->hasRole('admin'));
}
Which one is you're trying to achieve is not enough clear. If I guess, you want to find out which user is in which team then, in this situation you can go through -
User.php model -
protected $fillable = [
'name', 'email', 'password',
];
public function member(){
return $this->belongsTo('App\Member', 'user_id', 'id');
}
Member.php model -
protected $fillable = [
'id', 'user_id', 'team_id'
];
public function team(){
return $this->belongsTo('App\Team', 'team_id');
}
public function user(){
return $this->belongsTo('App\User', 'user_id', 'id');
}
Team.php model (keep as it is for now)-
class Team extends Model
{
protected $fillable = [
'name'
];
}
And finally call your members those are already in a team in your controller method-
$members = Member::with('team', 'user')->get();
return view('your-blade-file-name', compact('members'));
And, in your blade file -
#foreach($members as $member)
<p>Name: {{ $member->user->name }} , Email: {{ $member->user->email }} , Team - {{ $member->team->name }}</p>
#endforeach
Output:
Name: alain, Email: alain#gmail.com , Team - R.O.S
Name: eric, Email: eric1#gmail.com , Team - R.O.S
If you want a user can belong to a single team, then you don't need an intermediate table. Just add a column in the user table like team_id that will hold the value of which team the user belong.
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('email')->unique();
$table->string('password');
$table->unsignedInteger('team_id'); //make it nullable or anything based on your need
$table->rememberToken();
$table->timestamps();
});
Schema::create('teams', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->timestamps();
});
And now make the relationships in the models:
User Model
protected $fillable = [
'name', 'email', 'password','team_id'
];
public function team()
{
return $this->belongsTo('App\Team', 'team_id');
}
Team Model
protected $fillable = [
'name'
];
public function users()
{
return $this->hasMany('App\User', 'team_id');
}
In the above relationships a user belongs to a single team and a team has many users. I am pretty sure you are trying to achieve this. Feel free to ask if you find anything hard to understand.
Look you don't need the intermediate model Member. If you want a many to many relationship then you need to use an intermediate table.
how to insert data to related tables ? I have two related tables with one-to-many relationship, below is the structure :
Edition table :
public function up()
{
Schema::create('edition', function (Blueprint $table) {
$table->increments('id');
$table->string('title')->unique();
$table->text('cover')->nullable();
$table->timestamps();
});
//Set FK di kolom id_edition di table Journal
Schema::table('journal', function(Blueprint $table) {
$table->foreign('id_edition')->references('id')->on('edition')->onDelete('cascade')->onUpdate('cascade');
});
}
Journal table :
public function up()
{
Schema::create('journal', function (Blueprint $table) {
$table->increments('id');
$table->string('title', 200);
$table->string('author');
$table->text('abstract');
$table->text('file');
$table->integer('id_edition')->unsigned();
$table->timestamps();
});
}
Edition model :
class Edition extends Model
{
protected $table = 'edition';
protected $fillable = [
'title',
'cover',
];
public function journal()
{
return $this->hasMany('App\Journal', 'id_edition');
}
}
Journal model :
class Journal extends Model
{
protected $table = 'journal';
protected $fillable = [
'title',
'author',
'abstract',
'file',
];
public function edition()
{
return $this->belongsTo('App\Edition', 'id_edition');
}
}
The edition table supposed to has many journals in it, like an album that has many photos. So, how is the create and the save method would look like ? I did trying and I get this error "Constraint fails", below are the codes :
Controller :
public function create() {
return view('journal/create');
}
public function store(JournalRequest $request, Edition $edition) {
$input = $request->all();
//Input PDF
if ($request->hasFile('file')) {
$input['file'] = $this->uploadPDF($request);
}
//Insert data journal
$journal = Journal::create($input);
return redirect('journal');
}
The button code that supposed to open a create form in :
<div class="tombol-nav">
Add new Journal to this edition
</div>
Assuming, edition_id is in the input variable, here's how you can add the journal belonging to specific edition:
$edition_id = $request->get('edition'); //replace this with your way of retrieving edition_id
$journal = Edition::findOrFail($edition_id)->journal()->create($input);
I hope this thread find everyone healthy.
What is wrong with the following code? I am getting an error on my many to many relationship. For the past 4 hours i am stuck with this problem. I would be very thankful if you find the bug or source of problem.
Here is my code and tables:
Schema::create('products', function(Blueprint $table)
{
$table->increments('id');
$table->integer('category');
$table->string('thumbnail');
$table->string('images');
$table->string('logo');
$table->string('main_photo');
$table->timestamps();
});
//categories table
Schema::create('product_categories', function(Blueprint $table)
{
$table->increments('id');
$table->string('category');
});
//relationship table
Schema::create('product_productcategory', function(Blueprint $table)
{
$table->increments('id');
$table->integer('product_id'); // the id of the bear
$table->integer('productcategories_id'); // the id of the picnic that this bear is at
});
products model:
class Product extends Model
{
protected $table = 'products';
public function product_category() {
return $this->belongsToMany('App\product_category', 'App\product_productcategory', 'product_id', 'productcategories_id');
}
}
And pivot model
class product_category extends Model
{
protected $table = 'product_categories';
public function product() {
return $this->belongsToMany('App\Product', 'App\product_productcategory', 'productcategories_id', 'product_id');
}
}
Thanks in advance!
Updates: The problem is solved thanks to #mimo.
But now i want to translate the categories in different languages so i created a table like this:
Schema::create('category_translations', function(Blueprint $table)
{
$table->increments('id');
$table->string('name');
$table->integer('category_id')->unsigned();
$table->foreign('category_id')->references('id')->on('product_categories')->onDelete('cascade');
$table->integer('locale_id')->unsigned();
$table->foreign('locale_id')->references('id')->on('locales')->onDelete('cascade');
$table->unique(['category_id', 'locale_id']);
});
And my product categories with new relationship to the translations
class product_category extends Model
{
protected $table = 'product_categories';
public function product() {
//return $this->belongsToMany('App\Product', 'App\product_productcategory', 'productcategories_id', 'product_id');
return $this->belongsToMany('App\Product', 'product_productcategory');
}
public function translation($lang) {
return $this->hasMany('App\Category_Translation')->where('locale_id', '=', $lang);
}
}
And in category translation:
class Category_Translation extends Model
{
protected $table = 'category_translations';
public function product_category() {
return $this->belongsTo('App\product_category');
}
}
And finally my Product:
class Product extends Model
{
protected $table = 'products';
public function translation($lang) {
return $this->hasMany('App\Product_Translation')->where('locale_id', '=', $lang);
}
public function product_category() {
//return $this->belongsToMany('App\product_category', 'App\product_productcategory', 'product_id', 'productcategories_id');
//return $this->belongsToMany('App\product_category', 'product_productcategory');
return $this->belongsToMany('App\product_category', 'product_productcategory')->translation(1);
}
}
Now when i run:
$product = App\Product::find(1)->first();
echo $product->product_category;
I get error:
Call to undefined method Illuminate\Database\Query\Builder::translation()
Your migration file is wrong:
//relationship table
Schema::create('product_productcategory', function(Blueprint $table)
{
$table->integer('product_id')->unsigned()->index(); // the id of the bear
$table->foreign('product_id')->references('id')->on('products');
$table->integer('productcategories_id')->unsigned()->index(); // the id of the picnic that this bear is at
$table->foreign('productcategories_id')->references('id')->on('product_categories');
});
This code will made the relationship on the database level.
When you have 12 min free time you can check out this tutorial about many to many relationships in laravel:
https://laracasts.com/series/laravel-5-fundamentals/episodes/21
Update:
you need to update your relationships too:
class Product extends Model
{
protected $table = 'products';
public function product_category() {
return $this->belongsToMany('App\product_category', 'product_productcategory');
}
}
and:
class product_category extends Model
{
protected $table = 'product_categories';
public function product() {
return $this->belongsToMany('App\Product', 'product_productcategory');
}
}
I have a many to many relationship between products and a product_categories tables. Now I want to create a translation table for categories.
But how do I relate them in eloquent? i am learning database relationships so forgive my ignorance.
Here is my tables:
//languages
Schema::create('locales', function(Blueprint $table)
{
$table->increments('id');
$table->string('code', 2);
$table->string('name');
});
//products
Schema::create('products', function(Blueprint $table)
{
$table->increments('id');
$table->string('thumbnail');
$table->timestamps();
});
//categories
Schema::create('product_categories', function(Blueprint $table)
{
$table->increments('id');
$table->string('category');
});
//relationship table
Schema::create('product_productcategory', function(Blueprint $table)
{
$table->integer('product_id')->unsigned()->index(); // the id of the bear
$table->foreign('product_id')->references('id')->on('products');
$table->integer('product_category_id')->unsigned()->index(); // the id of the picnic that this bear is at
$table->foreign('product_category_id')->references('id')->on('product_categories');
});
//category translations
Schema::create('category_translations', function(Blueprint $table)
{
$table->increments('id');
$table->string('name');
$table->integer('category_id')->unsigned();
$table->foreign('category_id')->references('id')->on('product_categories')->onDelete('cascade');
$table->integer('locale_id')->unsigned();
$table->foreign('locale_id')->references('id')->on('locales')->onDelete('cascade');
$table->unique(['category_id', 'locale_id']);
});
Product Model:
class Product extends Model
{
protected $table = 'products';
public function product_category() {
return $this->belongsToMany('App\product_category', 'product_productcategory')->translation(1);
}
}
Product categories:
class product_category extends Model
{
protected $table = 'product_categories';
public function product() {
return $this->belongsToMany('App\Product', 'product_productcategory');
}
}
Category Translations
class Category_Translation extends Model
{
protected $table = 'category_translations';
public function product_category() {
return $this->belongsTo('App\product_category');
}
}
But when i run:
$product = App\Product::find(1)->first();
echo $product->product_category;
I get error:
Call to undefined method Illuminate\Database\Query\Builder::translation()
You should not call translation in the Product model category relation (because you still interacting with the query builder), instead you should access the translation as a property on the category object:
echo $product->product_category->first()->getTranslatedIn(1)->name;
So you could refactor your code like this:
Product Model:
class Product extends Model
{
protected $table = 'products';
public function product_category() {
return $this->belongsToMany('App\product_category', 'product_productcategory');
}
}
Product categories:
class product_category extends Model
{
protected $table = 'product_categories';
public function product() {
return $this->belongsToMany('App\Product', 'product_productcategory');
}
public function translations() {
return $this->hasMany('App\Category_Translation', 'category_translations');
}
// relation filtered by language (cannot be accessed as a property unless you define the parameter as optional)
public function translatedIn($language) {
return $this->hasOne('App\Category_Translation', 'category_id')->where('locale_id', $language);
}
// access translated object
public function getTranslatedIn($language) {
return $this->translatedIn($language)->getResults();
}
}