Laravel migration script produces multiple primary key columns - laravel

The following migration function:
public function up()
{
Schema::create('translations', function (Blueprint $table) {
$table->increments('id');
$table->string('table_name', 32);
$table->string('column_name', 32);
$table->integer('foreign_key', 11)->unsigned();
$table->string('locale', 11);
$table->text('value');
$table->unique(['table_name', 'column_name', 'foreign_key', 'locale']);
$table->timestamps();
});
}
is producing the following SQL query:
create table `translations` (
`id` int unsigned not null auto_increment primary key,
`table_name` varchar(32) not null,
`column_name` varchar(32) not null,
`foreign_key` int unsigned not null auto_increment primary key,
`locale` varchar(11) not null,
`value` text not null,
`created_at` timestamp null,
`updated_at` timestamp null
) default character set utf8mb4 collate utf8mb4_unicode_ci engine = InnoDB ROW_FORMAT=DYNAMIC
Notice the additional auto_increment primary key on the foreign_key field. This is the problem. How do I alter the migrations script so that it does not make foreign_key a second auto_increment primary key column?
(In case this looks familiar, this is from the base code for Voyager.)

This is because the second argument of the integer() method is the step value used for the autoincrement. You can't set the length of a integer column, instead use the column type that better suits your needs.
https://laravel.com/docs/5.4/migrations#columns

Related

Laravel - Is it possible to make relation between models (belongsTo) via an element of array as text in table

I'm absolute beginner in Laravel.
Is it possible to make relation, say belongsTo between models via an element of array.
Column in table1 like this:
mapping: ["misc","rates","photos"]
I need something similar to following:
public function dependencies() : BelongsTo
{
// This is impossible because "mapping" is array in Depends model and text type in database.
return $this->belongsTo(Depends::class, 'mapping', 'element_of_array');
}
or something similar (hasMany etc).
Table looks like this:
CREATE TABLE `dependings` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`media_id` int(10) unsigned NOT NULL,
`type` varchar(30) COLLATE utf8mb4_unicode_ci NOT NULL,
`mapping` text COLLATE utf8mb4_unicode_ci NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `dependent_collection_mappings_collection_id_type_unique` (`media_id`,`type`),
CONSTRAINT `dependent_collection_mappings_collection_id_foreign` FOREIGN KEY (`media_id`) REFERENCES `media` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci

Laravel how to get list of related fields through pivot table

I have 4 tables : peoples, companies, countries and the pivot table company_people (as peoples & companies both belongs to many) which has both people_id and company_id.
In the People model, I have the following functions:
class People extends Model
{
// main company (only one)
public function company()
{
return $this->belongsTo(Company::class);
}
// all other companies
public function companies()
{
return $this->belongsToMany(Company::class);
}
public function country()
{
return $this->belongsTo(Country::class);
}
}
Then in the People controller, I have the following in order to prepare to display a list of all the peoples with the related main company name (only one), country name (only one) and other companies as a list of names. I can do the first 2 but not the last one. How can I do that?
$peoples = People::orderBy($sortField,$sortOrder)
->with(['companies','company','country'])
->get();
foreach ($peoples as $people) {
$people->company = '['.$people->company->company.']'; // main company name
$people->country = '['.$people->country->country.']'; // country name
$people->otherCompanies = ? // list of other company names through pivot table
}
And here all the structure of the 4 tables:
CREATE TABLE `company_people` (
`id` bigint NOT NULL,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`company_id` bigint UNSIGNED NOT NULL,
`people_id` bigint UNSIGNED NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE `countries` (
`id` varchar(4) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'AA',
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`is_active` int NOT NULL DEFAULT '1',
`country` varchar(60) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE `peoples` (
`id` bigint UNSIGNED NOT NULL,
`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`is_active` int NOT NULL DEFAULT '1',
`firstname` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '',
`lastname` varchar(120) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci DEFAULT '',
`country_id` varchar(4) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT 'ZA',
`company_id` bigint UNSIGNED DEFAULT '0'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci PACK_KEYS=0;
ALTER TABLE `company_people`
ADD PRIMARY KEY (`id`),
ADD KEY `article_id` (`company_id`),
ADD KEY `tag_id` (`people_id`);
ALTER TABLE `countries`
ADD PRIMARY KEY (`id`);
ALTER TABLE `peoples`
ADD PRIMARY KEY (`id`),
ADD KEY `country_id` (`country_id`),
ADD KEY `company_id` (`company_id`);
ALTER TABLE `company_people`
MODIFY `id` bigint NOT NULL AUTO_INCREMENT;
ALTER TABLE `peoples`
MODIFY `id` bigint UNSIGNED NOT NULL AUTO_INCREMENT;
ALTER TABLE `peoples`
ADD CONSTRAINT `peoples-company` FOREIGN KEY (`company_id`) REFERENCES `companies` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
ADD CONSTRAINT `peoples-country` FOREIGN KEY (`country_id`) REFERENCES `countries` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT;
ALTER TABLE `companies`
ADD CONSTRAINT `peoples-country` FOREIGN KEY (`country_id`) REFERENCES `countries` (`id`) ON DELETE RESTRICT ON UPDATE RESTRICT;
ALTER TABLE `company_people`
ADD CONSTRAINT `companies-peoples` FOREIGN KEY (`company_id`) REFERENCES `companies` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
ADD CONSTRAINT `peoples-companies` FOREIGN KEY (`people_id`) REFERENCES `peoples` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
you can use pluck() to get all the company name then toArray() to convert in array like this
$peoples = People::orderBy($sortField,$sortOrder)
->with(['companies','company','country'])
->get();
foreach ($peoples as $people) {
$people->company = '['.$people->company->company.']'; // main company name
$people->country = '['.$people->country->country.']'; // country name
$people->otherCompanies = $people->companies->pluck('name')->toArray(); // list of other company names through pivot table
}
And if you want otherCompanies name as comma seprate then use $people->companies->pluck('name')->join(',');

Laravel Eloquent relationship with more than one join column

I'm new to laravel and try to use Eloquent.
Assuming there is the following database structure:
CREATE TABLE `a` (
`userid` int(11) NOT NULL,
`aid` int(11) NOT NULL,
`name` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `p` (
`userid` int(11) NOT NULL,
`pid` int(11) NOT NULL,
`aid` int(11) NOT NULL,
`text` text NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE `a` ADD PRIMARY KEY (`userid`,`aid`);
ALTER TABLE `p` ADD PRIMARY KEY (`userid`,`pid`);
Now I want a relation between the tables:
p contains a with p.userid=a.userid AND p.aid=a.aid
How can I do a relationship with more than one column?
First I want to mention that if you can't find a straight solution, there is always a workaround. The reason why you cannot do a relationship with more than one column in one table is that you need the same number of columns in the other table. So if you had 2 columns of type int in the first table, you need 2 columns of type int in the second table aswell to link them both. And as I see from what you provided, you are repeating data which suggests that your database is not normalized. I would suggest you do the following:
CREATE TABLE `a` (
`userid` int(11) NOT NULL,
`aid` int(11) NOT NULL unique,
`name` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
CREATE TABLE `p` (
`id` int(11) NOT NULL,
`userid` int(11) NOT NULL,
`pid` int(11) NOT NULL unique,
`text` text NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE `a` ADD PRIMARY KEY (`userid`);
ALTER TABLE `p` ADD PRIMARY KEY (`id`);
ALTER TABLE `p` ADD FOREIGN KEY (`userid`) REFERENCES `a` (`userid`)
This is what I think that is more suitable for you. However to answer your question, since you are using laravel in the a model do this:
class A extends Eloquent{
public function p(){
return $this->belongsTo('App\P','userid')
// or hasMany
}
public function p(){
return $this->belongsTo('App\P','aid')
// or hasMany
}
}
and the same thing in the p model
class P extends Eloquent{
public function a(){
return $this->hasMany('App\A','userid')
//or belongsTO
}
public function a(){
return $this->hasMany('App\A','pid')
//or belongsTO
}
}
NOTE
PLEASE keep in mind that the method belongsTo or hasMany is decided by your database model, on how you defined the database.

what's happened with my php artisan migrate

[Illuminate\Database\QueryException]
SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error i
n your SQL syntax; check the manual that corresponds to your MySQL server v
ersion for the right syntax to use near ') on delete cascade on update casc
ade' at line 1 (SQL: alter table users add constraint users_address_id_fo
reign foreign key (address_id) references address () on delete cascade
on update cascade)
[PDOException]
SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error i
n your SQL syntax; check the manual that corresponds to your MySQL server v
ersion for the right syntax to use near ') on delete cascade on update casc
ade' at line 1
migrate [--bench[="..."]] [--database[="..."]] [--force] [--path[="..."]] [--pac
kage[="..."]] [--pretend] [--seed]
public function up()
{
Schema::create('users',function($table){
$table->increments('id');
$table->string('name',30);
$table->string('phone',11);
$table->integer('age');
$table->string('email',50);
$table->string('marry_status',10);
$table->integer('address_id');
$table->foreign('address_id')->reference('id')->on('address')->onDelete('cascade')->onUpdate('cascade');
$table->integer('points_id');
$table->foreign('points_id')->reference('id')->on('address')->onDelete('cascade')->onUpdate('cascade');
$table->timestamps();
});
}
php migrate --pretend
CreateUsersTable: create table `users` (`id` int unsigned not null auto_increment primary key, `name` varchar(30) not null, `phone` varchar(11) not null, `age` int not null, `email` varchar(50) not null, `marry_status` varchar(10) not null, `address_id` int not null, `points_id` int not null, `created_at` timestamp default 0 not null, `updated_at` timestamp default 0 not null) default character set utf8 collate utf8_unicode_ci
CreateUsersTable: alter table `users` add constraint users_address_id_foreign foreign key (`address_id`) references `address` () on delete cascade on update cascade
CreateUsersTable: alter table `users` add constraint users_points_id_foreign foreign key (`points_id`) references `address` () on delete cascade on update cascade
CreateAddressTable: create table `address` (`id` int unsigned not null auto_increment primary key, `users_id` int not null, `name` varchar(30) not null, `created_at` timestamp default 0 not null, `updated_at` timestamp default 0 not null) default character set utf8 collate utf8_unicode_ci
CreatePointsTable: create table `points` (`id` int unsigned not null auto_increment primary key, `point` int not null, `users_id` int not null, `created_at` timestamp default 0 not null, `updated_at` timestamp default 0 not null) default character set utf8 collate utf8_unicode_ci
i try but i not good
public function up()
{
Schema::create('users',function($table){
$table->increments('id');
$table->string('name',30);
$table->string('phone',11);
$table->integer('age');
$table->string('email',50);
$table->string('marry_status',10);
$table->integer('address_id');
$table->integer('points_id');
$table->timestamps();
});
Schema::table('users',function($table){
$table->foreign('points_id')->references('id')->on('address')->onDelete('cascade')->onUpdate('cascade');
$table->foreign('address_id')->references('id')->on('address')->onDelete('cascade')->onUpdate('cascade');
});
}
You have error in your syntax. You are using reference() method, but the right method is references(). Fix it and I think everything will be ok.

yii2 : can't get data from two table with active record

I want get data from two table comments,users.
comments have hasOne relation with users
public function getUser()
{
return $this->hasOne(Users::className(), ['user_id' => 'user_id']);
}
i want get comments.comment_id,comments.comment_content,comments.user_id from comments table and uses.user_name , users.user_display_name from users table to use in gridview widget.
i use
$res = Comments::find()
->select([
'comments.comment_id',
'comments.comment_content',
'comments.user_id',
'users.user_id',
'users.user_display_name',
'users.user_name',
])
->innerJoinWith('user')
->all();
this code get comments field but i can't get users.user_name,users.user_display_name from database.
How should I do it?
note: user table in database is users but when i create model with Gii,relation method declare as getUser(), i don't know why.
update 1:
comments table:
DROP TABLE IF EXISTS `comments`;
CREATE TABLE `comments` (
`comment_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`comment_content` text NOT NULL,
`comment_approved` enum('no','yes') NOT NULL DEFAULT 'no',
`comment_date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`comment_parent` bigint(20) unsigned NOT NULL DEFAULT '0',
`sms_id` bigint(20) unsigned NOT NULL DEFAULT '0',
`user_id` bigint(20) unsigned NOT NULL DEFAULT '0',
PRIMARY KEY (`comment_id`),
KEY `fk_comment_sms_id` (`sms_id`),
KEY `fk_commetn_user_id` (`user_id`),
CONSTRAINT `fk_comment_sms_id` FOREIGN KEY (`sms_id`) REFERENCES `sms` (`sms_id`),
CONSTRAINT `fk_commetn_user_id` FOREIGN KEY (`user_id`) REFERENCES `users` (`user_id`)
) ENGINE=InnoDB AUTO_INCREMENT=18 DEFAULT CHARSET=utf8;
users table:
CREATE TABLE `users` (
`user_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`user_name` varchar(60) NOT NULL DEFAULT '',
`user_pass` varchar(64) NOT NULL DEFAULT '',
`user_level` int(11) NOT NULL DEFAULT '1',
`user_email` varchar(100) NOT NULL DEFAULT '',
`user_display_name` varchar(250) NOT NULL DEFAULT '',
`user_phone_number` varchar(11) NOT NULL,
`user_registered` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`user_activation_key` varchar(60) NOT NULL,
`user_status` enum('active','deactive','delete') NOT NULL DEFAULT 'deactive',
PRIMARY KEY (`user_id`),
UNIQUE KEY `u_user_sign` (`user_name`) USING BTREE,
UNIQUE KEY `u_user_email` (`user_email`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=24 DEFAULT CHARSET=utf8;
Not sure how you're displaying or testing if the query returned any data but you should read up on relations in Yii.
Working with Relational Data
Lazy and Eager Loading
With lazy loading the data doesn't exist until you try to access it so may not appear in things like print_r or var_dump
I recommend renaming your tables to comment and user. Read here: Table Naming Dilemma: Singular vs. Plural Names why you should use singular names.
The reason Gii generates getUser and not getUsers is because of the hasOne relationship. It's getting one -user- and not multiple -users-
Are you sure the relationship definition is correct? Is user_id the PK in the users table and the FK in the comments table? And are you sure there is correct data in the DB?

Resources