I created two migrations, because I wanted to create a one-to-one relationship between Trend and TrendExplanation.
Schema::create('trend_explanations', function (Blueprint $table) {
$table->increments('id');
$table->text('demographical')->nullable();
$table->text('economical')->nullable();
$table->text('social')->nullable();
$table->text('technological')->nullable();
$table->text('ecological')->nullable();
$table->text('political')->nullable();
$table->timestamps();
});
This is the migration for the Trend model:
Schema::create('trends', function (Blueprint $table) {
$table->increments('id');
$table->integer('explanation_id')->unsigned();
$table->foreign('explanation_id')->references('id')->on('trend_explanations');
$table->string('name');
$table->date('date');
$table->text('description');
$table->timestamps();
});
So in the models I did the following additions:
class Trend extends Model
{
public function explanation()
{
return $this->hasOne(TrendExplanation::class);
}
}
And of course I created a seeder to test it out:
$trend = new Trend();
$trend->name = "Something";
$trend->description = "Description";
$explanation = new TrendExplanation();
// ...
$trend->explanation()->save($explanation);
$trend->save();
And when I run it, I receive the error: [Illuminate\Database\QueryException] SQLSTATE[42S22]: Column not found: 1054 Unknown column 'trend_id' in 'field list'.
How does this happen? I don't understand what I did wrong here.
You can specify the foreign and local keys when specifying the relationship. It usually goes
$this->hasOne(Class, foreign, local);
So your definition would be:
return $this->hasOne(TrendExplanation::class, 'id', 'explanation_id');
Related
I have a customer model that has many contacts. I defined a relationship to get the most recent contact of the customer using the "Has One Of Many" relationship in Laravel 8:
Models
class Customer extends Model
{
use HasFactory;
public function contacts()
{
return $this->hasMany(Contact::class);
}
public function latestContact()
{
return $this->hasOne(Contact::class)->ofMany('contacted_at', 'max')->withDefault();
}
}
class Contact extends Model
{
use HasFactory;
protected $casts = [
'contacted_at' => 'datetime',
];
public function customer()
{
return $this->belongsTo(Customer::class);
}
}
Migration (contact model)
class CreateContactsTable extends Migration
{
public function up()
{
Schema::create('contacts', function (Blueprint $table) {
$table->id();
$table->timestamps();
$table->softDeletes();
$table->foreignID('customer_id');
$table->string('type');
$table->dateTime('contacted_at');
});
}
}
In my view, I want to show all customers and order them by their latest contact. However, I can't figure out how to do that.
I tried to achieve it via the join method but then I obviously get various entries per customer.
$query = Customer::select('customers.*', 'contacts.contacted_at as contacted_at')
->join('contacts', 'customers.id', '=', 'contacts.customer_id')
->orderby('contacts.contacted_at')
->with('latestContact')
Knowing Laravel there must be a nice way or helper to achieve this. Any ideas?
I think the cleanest way to do this is by using a subquery join:
$latestContacts = Contact::select('customer_id',DB::raw('max(contacted_at) as latest_contact'))->groupBy('customer_id');
$query = Customer::select('customers.*', 'latest_contacts.latest_contact')
->joinSub($latestContacts, 'latest_contacts', function ($join){
$join->on([['customer.id', 'latest_contacts.customer_id']]);
})
->orderBy('latest_contacts.latest_contact')
->get();
More info: https://laravel.com/docs/8.x/queries#subquery-joins
I suspect there is an issue with your migration, the foreign key constraint is defined like this:
Check the documentation:
https://laravel.com/docs/8.x/migrations#foreign-key-constraints
Method 1: define foreign key constraint
public function up()
{
Schema::create('contacts', function (Blueprint $table) {
$table->id();
$table->foreignId('consumer_id')->constrained();
$table->string('type');
$table->dateTime('contacted_at');
$table->timestamps();
$table->softDeletes();
});
}
Method 2: define foreign key constraint
public function up()
{
Schema::create('contacts', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('customer_id');
$table->foreign('customer_id')->references('id')->on('customers');
$table->string('type');
$table->dateTime('contacted_at');
$table->timestamps();
$table->softDeletes();
});
}
I got the following error. How can I fix it?
Base table or view not found: 1146 Table 'account_infos'
Migration
public function up()
{
Schema::create('account_info', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('users_id');
$table->foreign('users_id')->references('id')
->on('users')->onDelete('cascade');
$table->unsignedBigInteger('axis_id');
$table->foreign('axis_id')->references('id')
->on('axis')->onDelete('cascade');
$table->enum('account_type',['legal','rightful']);
$table->timestamps();
});
}
Just add:
protected $table='account_info';
in your model
I have searched for people who encountered this error but I still can't find the solution.
I have been getting the error:
"SQLSTATE[42S22]: Column not found: 1054 Unknown column 'material_tags.material_uuid' in 'field list' (SQL: select tags.*, material_tags.material_uuid as pivot_material_uuid, material_tags.tag_uuid as pivot_tag_uuid from tags inner join material_tags on tags.uuid = material_tags.tag_uuid where material_tags.material_uuid in (05a36470-d0a0-11e7-91b4-ff3d7d9f961a) and tags.deleted_at is null)"
in which if I have to view Material 05a36470-d0a0-11e7-91b4-ff3d7d9f961a it should look like this
When I try to run this code located on the controller:
public function show(Request $request, $id)
{
$material = Material::with('tags')->where(
'uuid',
$id
)->first();
where my Material Model has this:
public function tags()
{
return $this->belongsToMany('App\Models\Tag', 'material_tags');
}
So I have a Tags table where all the tags are stored, and a Materials table that has all the materials stored. and I have the Material_tags table to see what Materials have tags.
my create_materials_table at migration
public function up()
{
Schema::connection('materials')->create('materials', function (Blueprint $table) {
$table->uuid('uuid')
->primary();
$table->string('title');
$table->integer('viewing_time')
->default(15)
->comment('In seconds');
$table->text('description')
->nullable();
$table->uuid('organization_id')
->nullable();
$table->timestamps();
$table->softDeletes();
});
}
my create_tags_table migration
public function up()
{
Schema::connection('materials')->create('tags', function (Blueprint $table) {
$table->uuid('uuid')
->primary();
$table->string('name')
->unique();
$table->timestamps();
$table->softDeletes();
});
}
and my create_material_tags_table migration
public function up()
{
Schema::connection('materials')->create('material_tags', function (Blueprint $table) {
$table->uuid('uuid')
->primary();
$table->uuid('material_id');
$table->uuid('tag_id');
$table->timestamps();
$table->foreign('material_id')
->references('uuid')
->on('materials')
->onDelete('cascade');
$table->foreign('tag_id')
->references('uuid')
->on('tags')
->onDelete('cascade');
});
}
You have to specify the custom foreign keys:
public function tags()
{
return $this->belongsToMany('App\Models\Tag', 'material_tags', 'material_id', 'tag_id');
}
I create a migration
Schema::create('roles', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('label')->nullable();
$table->timestamps();
});
Schema::create('permissions', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('label')->nullable();
$table->timestamps();
});
Schema::create('permission_role', function (Blueprint $table) {
$table->integer('role_id')->unsigned();
$table->foreign('role_id')->references('id')->on('roles')->onDelete('cascade');
$table->integer('permission_id')->unsigned();
$table->foreign('permission_id')->references('id')->on('permissions')->onDelete('cascade');
$table->primary(['role_id' , 'permission_id']);
});
Schema::create('role_user', function (Blueprint $table) {
$table->integer('role_id')->unsigned();
$table->foreign('role_id')->references('id')->on('roles')->onDelete('cascade');
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
$table->primary(['role_id' , 'user_id']);
});
Any what I write in CMD php artisan migrate and composer dumpautoload and php artisan serve and... This error is seen. and too I deleted database and I create a new database.
[Illuminate\Database\QueryException]
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'prj_roocket.permissions' doesn't exist (SQL: select * from permissions)
[PDOException] SQLSTATE[42S02]: Base table or view not found: 1146
Table 'prj_roocket.permissions' doesn't exist
This error is given by the function getPermissions in AuthServiceProvider (or somewhere else you defined your authentication service provider).
Probabily your function looks like this:
protected function getPermissions()
{
return Permission::with('roles')->get();
}
Try to replace the function getPermissions with:
protected function getPermissions()
{
try {
return Permission::with('roles')->get();
} catch (\Exception $e) {
return [];
}
}
and then run php artisan migrate again.
Note: with this fix you are not going to compromise the system security.
I've just started to learn Laravel 4 and I've run in to a small problem and I'm very curious to if there is a solution. I have a multilingual recipe database and I have, in short, modeled my database like this:
Schema::create('language', function(Blueprint $table) {
$table->string('id', 2)->primary();
$table->string('display_name');
$table->timestamps();
});
Schema::create('recipe', function(Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('slug')->unique();
$table->timestamps();
});
Schema::create('translated_recipe', function(Blueprint $table) {
$table->increments('id');
$table->integer('recipe_id')->unsigned();
$table->foreign('recipe_id')->references('id')->on('recipe')->onDelete('cascade');
$table->string('language_id', 2);
$table->foreign('language_id')->references('id')->on('language');
$table->string('translated_name')
$table->timestamps();
});
My models look like this:
class Language extends Eloquent {
protected $table = 'language';
public function translatedRecipes() {
return $this->hasMany('TranslatedRecipe');
}
}
class Recipe extends Eloquent {
protected $table = 'recipe';
public function translations() {
return $this->hasMany('TranslatedRecipe');
}
}
class TranslatedRecipe extends Eloquent {
protected $table = 'translated_recipe';
public function recipe() {
return $this->belongsTo('Recipe');
}
}
Then I have some basic seeding:
Language::create(array('id' => 'en', 'display_name' => 'English'));
Recipe::create(array('name' => 'First Recipe', 'slug' => 'first_recipe'));
Here come's the tricky part. How do I insert a translated recipe with Eloquent? I've come this far:
$recipe = Recipe::all()->first();
$lang = Language::all()->first();
$translatedRecipe = new TranslatedRecipe;
$translatedRecipe->translated_name = $lang->display_name.' '.$recipe->name;
I can easily do an INSERT with the Query Builder:
DB::table('translated_recipe')->insert(
array(
'recipe_id' => $recipe->id,
'language_id' => $lang->id,
'translated_name' => $translatedRecipe->translated_name
)
);
It doesn't set the timestamps though because I'm guessing that's a feature of Eloquent. Is there a way to keep it 100% Eloquent? I can't do this:
$translatedRecipe = $recipe->translations()->save($translatedRecipe);
...because SQL throws an "Integrity constraint violation: 1452..." error because of the missing second foreign key.
Ok, I haven't tested this but there are a few things I would change:
I would change the 'language' table to have the following fields: 'id', 'initials' and 'displayname'.
I would then change the 'language_id' field in 'translated_recipe' table to be an unsigned integer.
(It's really brave to have your primary key set to 'id' in the 'language' table - and it's not even an id by the loose meaning of the word! This is possibly the cause of the problem. Eloquent might be expecting your primary key to be the auto-incremented field which you don't have.)
Also, it's nice to make full use of the 'free' features provided in the framework at a relatively small 'fee' of following conventions such as:
naming your tables in plural form (languages, recipes, translations)
setting your primary key to be the auto-incremented field (obviously an integer)
You can scroll to the One to Many section of Dayle Rees Codehappy tutorial which was meant for Laravel 3 but is fit for our purpose. Or spare a buck or two for his CodeBright book for Laravel 4 if you want to learn other features of the framework. (I haven't yet)
Lastly, you don't have 'short_description' and 'description' fields in your 'translated_recipe' table! It's a miracle it's working at all!
Schema::create('languages', function($table)
{
$table->engine = 'InnoDB';
$table->increments('id');
$table->string('initials', 2)->unique();
$table->string('display_name');
$table->timestamps();
});
Schema::create('recipes', function($table)
{
$table->engine = 'InnoDB';
$table->increments('id');
$table->string('name');
$table->string('slug')->unique();
$table->timestamps();
});
Schema::create('translations', function($table)
{
$table->engine = 'InnoDB';
$table->increments('id');
$table->integer('recipe_id')->unsigned();
$table->integer('language_id')->unsigned();
$table->string('translated_name');
$table->timestamps();
$table->foreign('recipe_id')->references('id')->on('recipe')->onDelete('cascade');
$table->foreign('language_id')->references('id')->on('language')->onDelete('cascade');
});
Models
class Language extends Eloquent {
public function translations()
{
return $this->hasMany('Translation');
}
}
class Recipe extends Eloquent {
public function translations()
{
return $this->hasMany('Translation');
}
}
class Translation extends Eloquent {
public function recipe()
{
return $this->belongsTo('Recipe');
}
public function language()
{
return $this->belongsTo('Language');
}
}