I'm trying to display category for each entry's page, but they all only display 'JavaScript.'
(A category can have many entries, but each entry has exactly one category.)
My Category model:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Category extends Model
{
protected $table = 'categories';
protected $fillable = [
'name'
];
public function entries() {
return $this->hasMany(Entry::class);
}
}
My Entry model:
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Entry extends Model
{
protected $table = 'entries';
protected $fillable = [
'title',
'hours',
'minutes',
'category_id',
'difficulty',
'url'
];
public function categories() {
return $this->belongsTo(Category::class, 'category_id');
}
public function getCreatedAtAttribute($value)
{
return date('F d, Y H:i', strtotime($value));
}
}
My EntryController's show() method:
/**
* Display the specified resource.
*
* #param Entry $entry
* #return \Illuminate\Http\Response
*/
public function show(Entry $entry)
{
$category = Entry::find($entry->category_id)->categories()->first();
return view( 'entries.show', compact( 'entry', 'category' ) );
}
My categories table's up() method:
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('categories', function (Blueprint $table) {
$table->id();
$table->string('name', 255);
});
}
My entries table's up() method:
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('entries', function (Blueprint $table) {
$table->id();
$table->string('title', 255);
$table->timestamps();
$table->integer('hours');
$table->integer('minutes');
$table->foreignId('category_id')->constrained('categories');
$table->string('difficulty', 255);
$table->string('url', 255);
});
Schema::enableForeignKeyConstraints();
}
You are fetching entry by category_id, no need to find the Entry again.
$category = Entry::find($entry->category_id)->categories()->first();
Should be
$category = $entry->category;
BelongsTo is a singular relation and can be described as below.
public function category() {
return $this->belongsTo(Category::class);
}
Related
i have a problem with function attach(). I have created 3 tables. 1 table is for added movies. Table 2 applies to the movie categories. 3 table is a collection of movie ID and category ID. A combination of many to many.
When i want add a new video with category from form this i have error -> Call to a member function attach() on boolean. If anyone knows the answer, please help. Thank you for your time!
VideoController.php -> look at the method store();
<?php
namespace App\Http\Controllers;
use Request;
use App\Http\Requests\CreateVideoRequest;
use App\Video;
use App\Category;
use Auth;
use Session;
class VideoController extends Controller
{
public function __construct(){
$this->middleware('auth', ['except' => 'index']);
}
public function index(){
$videos = Video::latest()->get();
return view('videos.index')->with('videos', $videos);
}
public function show($id){
$video = Video::find($id);
return view('videos.show')->with('video', $video);
}
public function create(){
$categories = Category::pluck('name', 'id');
return view('videos.create')->with('categories',$categories);
}
public function store(CreateVideoRequest $request){
$video = new Video($request->all());
//dd($request->all());
Auth::user()->videos()->save($video);
$categoryIds = $request->input('CategoryList');
$video->categories()->attach($categoryIds);
Session::flash('video_created', 'Added');
return redirect('video');
}
public function edit($id){
$video = Video::findOrFail($id);
return view('videos.edit')->with('video', $video);
}
public function update($id, CreateVideoRequest $request){
$video = Video::findOrFail($id);
$video->update($request->all());
return redirect('video');
}
}
Video.php - model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Video extends Model
{
protected $fillable = [
'title',
'url',
'description'
];
public function user(){
return $this->belongsTo('App\User');
}
public function categories(){
return $this->belongsToMany('App\Video')->withTimestamps;
}
}
Category.php - model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Category extends Model
{
protected $fillable = [ 'name' ];
public function videos(){
return $this->belongsToMany('App/Video')->withTimestamps;
}
}
User.php - model (maybe you need a User.php model solves problems)
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email', 'password',
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
/**
* The attributes that should be cast to native types.
*
* #var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
public function videos(){
return $this->hasMany('App\Video');
}
}
Migration - create_category_video_table.php
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateCategoryVideoTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('category_video', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('category_id');
$table->foreign('category_id')->references('id')->on('categories')->onDelete('cascade');
$table->unsignedBigInteger('video_id');
$table->foreign('video_id')->references('id')->on('videos')->onDelete('cascade');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('category_video');
}
}
Migration - create_categories_table.php
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateCategoriesTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('categories', function (Blueprint $table) {
$table->bigIncrements('id');
$table->string('name');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('categories');
}
}
Migration - create_videos_table.php
<?php
use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateVideosTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('videos', function (Blueprint $table) {
$table->bigIncrements('id');
$table->unsignedBigInteger('user_id');
$table->string('title');
$table->string('url');
$table->text('description');
$table->timestamps();
$table->foreign('user_id')->references('id')->on('users');
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::dropIfExists('videos');
}
}
form.blade.php - simple form in Laravel Collection
{!! Form::select('CategoryList', $categories, null, ['multiple' => 'multiple']) !!}
For the timestamps for the pivot you would call the "method" withTimestamps() not a "property" named withTimestamps:
// Video
public function categories()
{
return $this->belongsToMany(Category::class)->withTimestamps();
}
// Category
public function videos()
{
return $this->belongsToMany(Video::class)->withTimestamps();
}
I want to print which user is an author of a subcategory but when I do dd(). I get a NULL value.
User model:
<?php
namespace App;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Spatie\Permission\Traits\HasRoles;
class User extends Authenticatable
{
use Notifiable;
use HasRoles;
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'name', 'email', 'password'
];
/**
* The attributes that should be hidden for arrays.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
/**
* The attributes that should be mutated to dates.
*
* #var array
*/
protected $dates = [
'created_at',
'updated_at'
];
}
Category model:
class Category extends Model
{
public function subcategory()
{
return $this->hasMany(Subcategory::class);
}
public function user()
{
return $this->belongsTo(User::class);
}
}
Subcategory Model:
class Subcategory extends Model
{
public function category()
{
return $this->belongsTo(Category::class);
}
public function user()
{
return $this->belongsTo(User::class);
}
}
Function where I want to print an author of subcategory.
public function show(Category $category)
{
$subcategories = $category->subcategory->user->name;
dd($subcategory);
return view('subcategories', compact('subcategories '));
}
DD output: NULL also when I do dd($category) In "relations" i can see my "subcategory" but there is not "user" relation anywhere. Please help :/
Migrations:
public function up()
{
Schema::create('categories', function (Blueprint $table) {
$table->increments('id');
$table->text('description');
$table->timestamps();
});
}
public function up()
{
Schema::create('subcategories', function (Blueprint $table) {
$table->increments('id');
$table->string('description')->nullable();
$table->foreign('category_id')->references('id')->on('categories')
->onUpdate('cascade')->onDelete('cascade');
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users')
->onUpdate('cascade')->onDelete('cascade');
$table->timestamps();
});
}
Requests:
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class ItemRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* #return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* #return array
*/
public function rules()
{
return [
//
];
}
}
View:
#foreach($subcategories as $subcategory)
<li>{{$subcategory->user->name}}</li>
#endforeach
Your Category model defines the relation as subcategories, but you are calling $category->subcategory. Instead, call the relation as you have it defined:
$subs = $category->subcategories;
Also, since the relation is one to many, you will need to loop through each subcategory in order to retrieve the user. Example:
$user_names = array();
foreach ($subs as $s) {
$user_names[] = $s->user->name
}
dd($user_names);
Or, get the nth subcategory, etc.:
dd($category->subcategories->first()->user->name);
//Or
dd($category->subcategories->last()->user->name);
//Etc.
Edit:
Change your show method to this:
public function show(Category $category)
{
$subcategories = $category->subcategory;
dd($subcategories);
return view('subcategories', compact('subcategories'));
}
If You are still unable to see the user relation in each subcategory, try it with this:
$subcategories = $category->subcategory()->with('user')->get();
subcategory does not have a user() relationship, only category has.so the user's name would be:
$category->user->name
I want to do something like this:
$posts= Status::where('users_id',$user->id)->orWhere(DB::table('user_status_share.user_id', $user->id))->orderBy('created_at', 'DESC')->get();
But I'm getting an error: strtolower() expects parameter 1 to be string, object given - how can I change the table in "orWhere" method? Is this possible? If not - how to use 2 tables in one query?
Schema (Status):
public function up()
{
Schema::create('users_status', function (Blueprint $table) {
$table->increments('id')->unique();
$table->longText('status_text');
$table->integer('users_id')->unsigned();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('users_status');
}
Schema (StatusShare):
public function up()
{
Schema::create('user_status_share', function (Blueprint $table) {
$table->increments('id');
$table->integer('status_id');
$table->integer('user_id');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('user_status_share');
}
Model Status:
namespace App\Eloquent;
use Illuminate\Database\Eloquent\Model;
class Status extends Model
{
public $timestamps = true;
protected $table = 'users_status';
protected $guarded = ['id'];
public function comments()
{
return $this->hasMany(StatusComments::class);
}
public function likes()
{
return $this->hasMany(StatusLikes::class);
}
public function shares()
{
return $this->hasMany(StatusShare::class);
}
}
Model StatusShare:
<?php
namespace App\Eloquent;
use Illuminate\Database\Eloquent\Model;
class StatusShare extends Model
{
public $timestamps = true;
protected $table = 'user_status_share';
protected $guarded = ['id'];
public function status()
{
return $this->hasOne(Status::class);
}
}
I think you should try something like this
tweak it , i didnt test it
$posts = DB::table('status')->where('users_id',$user->id)->orWhere(function ($query) use ($user) {
$query->table('user_status_share')->where('user_id', $user->id);
})
->get();
can you share more informations because i have a feeling that these can be reached in a simple way using relations (show us database structure and relations in your models)
I am pretty new to the Laravel Eloquent ORM and am having difficulty building a dynamic query to query products of a category.
I parse the request object and return products according to what vars have been passed through. This is easy enough when I am querying a single Model but I want to know how to build a query dynamically if a category is passed through to. This is easy enough using standard MYSQL and PHP but I am unsure as to how this is achieved in LAravel.
Here is my code:
Product Model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Product extends Model
{
protected $primaryKey = 'id',
$table = 'products',
$fillable = array('title', 'SKU', 'description', 'created_at', 'updated_at');
public $timestamps = true;
/**
* Get the categories assoicated with the product
*
* #return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*
*/
public function categories() {
return $this->belongsToMany('App\Category')->withTimestamps();
}
}
Category model:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Category extends Model
{
/**
* Returns all products related to a category
*
* #return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function products() {
return $this->belongsToMany('App\Product')->withTimestamps();
}
}
Inside my product controller I have this function to get products which calls a method 'filterProduct' in a class called 'filtervars':
public function index(Request $request)
{
return FilterVars::filterProduct($request->all());
}
And here is the filterProduct method:
public static function filterProduct($vars) {
$query = Product::query();
if((array_key_exists('order_by', $vars)) && (array_key_exists('order', $vars))) {
$query = $query->orderBy($vars['order_by'], $vars['order']);
}
if(array_key_exists('cat', $vars)) {
$query = $query->whereHas('categories', function($q) use ($vars){
return $q->where('category_id', $vars['cat']);
});
}
return $query->get();
The product database migration:
class CreateProductsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('products', function(Blueprint $table) {
$table->increments('id');
$table->string('title', 75);
$table->string('SKU')->unique();
$table->text('description')->nullable();
$table->timestamps();
});
}
And the migration which shows the structure of the categories table, the pivot table and foreign keys etc:
class CreateCategoriesTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('categories', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('description');
$table->timestamps();
});
Schema::create('category_product', function(Blueprint $table) {
$table->integer('product_id')->unsigned()->index();
$table->foreign('product_id')->references('id')->on('products')->onDelete('cascade');
$table->integer('category_id')->unsigned()->index();
$table->foreign('category_id')->references('id')->on('categories')->onDelete('cascade');
$table->timestamps();
});
}
I had a go at trying to incorporate the 'has' method on the query but this doesn't seem to work. can anyone advise as to where I am going wrong?
Thanks!
May be you need whereHas method
$query = $query->whereHas('categories', function($q) use ($vars) {
$q->where('id', $vars['cat']);
});
EDIT
You should use id column in whereHas method because you apply where condition to categories table, which hasn't category_id column
public static function filterProduct($vars) {
$query = Product::query();
if((array_key_exists('order_by', $vars)) && (array_key_exists('order', $vars))) {
$query = $query->orderBy($vars['order_by'], $vars['order']);
}
if(array_key_exists('cat', $vars)) {
$query = $query->whereHas('categories', function($q) use ($vars){
$q->where('id', $vars['cat']);
});
}
return $query->get();
}
I have been in big problem, I am maintaining eloquent relationship setup in my project where i am having the following relationship:
User info related to login stored in users table.
User profile related information stored in profiles information.
Users address stored in address table
configurations related information stored in configurations like city, state, country
Efforts
Here is the migration and model and their relationship:
Users migration table:
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateUsersTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('email')->unique();
$table->string('password', 60);
$table->rememberToken();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('users');
}
}
User Model:
namespace App;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
/**
* The attributes that are mass assignable.
*
* #var array
*/
protected $fillable = [
'email', 'password',
];
/**
* The attributes excluded from the model's JSON form.
*
* #var array
*/
protected $hidden = [
'password', 'remember_token',
];
public function profile()
{
return $this->hasOne('App\Profile','user_id');
}
}
Profile migration table:
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateProfilesTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('profiles', function (Blueprint $table) {
$table->increments('profile_id');
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->string('lastname')->nullable();
$table->string('firstname')->nullable();
$table->string('gender')->nullable();
$table->string('phonenumber', 20)->nullable();
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('profiles');
}
}
Profile Model:
namespace App;
use Illuminate\Database\Eloquent\Model;
class Profile extends Model
{
protected $fillable = [
'firstname', 'lastname',
];
public function user(){
return $this->belongsTo('App\User');
}
public function address()
{
return $this->hasOne('App\Address','profile_id');
}
}
Configuration migration table:
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateConfigurationsTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('configurations', function (Blueprint $table) {
$table->increments('config_id');
$table->string('configuration_name');
$table->string('configuration_type');
$table->string('parent_id');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('configurations');
}
}
Configuration Model:
namespace App;
use Illuminate\Database\Eloquent\Model;
class Configuration extends Model
{
public function children() {
return $this->hasMany('App\Configuration','parent_id');
}
public function parent() {
return $this->belongsTo('App\Configuration','parent_id');
}
public function city() {
return $this->hasOne('App\Address', 'city');
}
public function state() {
return $this->hasOne('App\Address', 'state');
}
public function country() {
return $this->hasOne('App\Address', 'country');
}
}
Address Migration Table:
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
class CreateAddressesTable extends Migration
{
/**
* Run the migrations.
*
* #return void
*/
public function up()
{
Schema::create('addresses', function (Blueprint $table) {
$table->increments('address_id');
$table->integer('profile_id')->unsigned();
$table->foreign('profile_id')->references('profile_id')->on('profiles')->onDelete('cascade');
$table->string('address')->nullable();
$table->integer('city')->unsigned();
$table->foreign('city')->references('config_id')->on('configurations')->onDelete('cascade');
$table->string('pincode')->nullable();
$table->integer('state')->unsigned();
$table->foreign('state')->references('config_id')->on('configurations')->onDelete('cascade');
$table->integer('country')->unsigned();
$table->foreign('country')->references('config_id')->on('configurations')->onDelete('cascade');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* #return void
*/
public function down()
{
Schema::drop('addresses');
}
}
Address Model:
namespace App;
use Illuminate\Database\Eloquent\Model;
class Address extends Model
{
public function profile(){
return $this->belongsTo('App\Profile');
}
public function city() {
return $this->belongsTo('App\Configuration');
}
public function state() {
return $this->belongsTo('App\Configuration');
}
public function country() {
return $this->belongsTo('App\Configuration');
}
}
I have used Eloquent relation setup, two foreign keys to same table to make my project relationship. But unfortunately above code does not generating desire output. Take a look:
If I use the command Auth::user()->profile->firstname it will print user first name. So if i use Auth::user()->profile->address->city it should print city name stored in configuration table, but instead print name it print the id.
Please suggest me the solution.
Thanks,
Well, I found the solution for my own question. Thanks for everyone who think this question have some worth.
Well, we don't nedd to change user or profile, we just need to make some changes in configuration and address model only.
change
class Address extends Model
{
public function profile(){
return $this->belongsTo('App\Profile');
}
public function city() {
return $this->belongsTo('App\Configuration');
}
public function state() {
return $this->belongsTo('App\Configuration');
}
public function country() {
return $this->belongsTo('App\Configuration');
}
}
to
class Address extends Model
{
public function profile(){
return $this->belongsTo('App\Profile');
}
public function cityConfiguration() {
return $this->belongsTo('App\Configuration', 'city');
}
public function stateConfiguration() {
return $this->belongsTo('App\Configuration', 'state');
}
public function countryConfiguration() {
return $this->belongsTo('App\Configuration', 'country');
}
}
and change
class Configuration extends Model
{
public function children() {
return $this->hasMany('App\Configuration','parent_id');
}
public function parent() {
return $this->belongsTo('App\Configuration','parent_id');
}
public function city() {
return $this->hasOne('App\Address', 'city');
}
public function state() {
return $this->hasOne('App\Address', 'state');
}
public function country() {
return $this->hasOne('App\Address', 'country');
}
}
To
class Configuration extends Model
{
public function children() {
return $this->hasMany('App\Configuration','parent_id');
}
public function parent() {
return $this->belongsTo('App\Configuration','parent_id');
}
public function city() {
return $this->hasOne('App\Address', 'city');
}
public function state() {
return $this->hasOne('App\Address', 'state');
}
public function country() {
return $this->hasOne('App\Address', 'country');
}
}
and that's it. Everything is working fine.