Gii CRUD generator and related tables - yii

I am using Yii framework and I have got a problem with CRUD generator.
I have got two tables called Users and news with the following structures:
CREATE TABLE IF NOT EXISTS `news` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`keyword` varchar(1000) COLLATE utf8_persian_ci DEFAULT NULL,
`user_id` tinyint(3) unsigned NOT NULL,
`title` varchar(100) COLLATE utf8_persian_ci DEFAULT NULL,
`body` varchar(1000) COLLATE utf8_persian_ci DEFAULT NULL,
`publishedat` date DEFAULT NULL,
`state` tinyint(1) unsigned DEFAULT NULL,
`archive` tinyint(1) unsigned DEFAULT NULL,
`last_modified` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `news_FKIndex1` (`keyword`(255)),
KEY `news_FKIndex2` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_persian_ci AUTO_INCREMENT=3 ;
CREATE TABLE IF NOT EXISTS `users` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(20) NOT NULL,
`password` varchar(128) NOT NULL,
`create_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`lastvisit_at` timestamp NULL DEFAULT NULL,
`is_disabled` tinyint(1) NOT NULL DEFAULT '1',
PRIMARY KEY (`id`),
UNIQUE KEY `username` (`username`),
KEY `status` (`is_disabled`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=7 ;
when I generate a CRUD using Gii for my news table I cannot see the fields for users table. Instead of user_id I want to see the username in the table created by CRUD generator. How can I make a change in the code to get the result as above?

First, user_id needs to be a foreign key field not just a key field.
Second, gii will not generate the field as you require by default. For such functionality an extension such as Giix might help. However, since a relation exists you could always use relationName.username to display the username in a grid view or a list view.

Related

Foreign key constraint is incorrectly formed when import table

I have some question about database structure, laravel orm and constraints.
So first I have some tables(this code is from my DB dump):
CREATE TABLE `person` (
`person_id` int(10) UNSIGNED NOT NULL,
`first_name` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
`middle_name` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`last_name` varchar(100) COLLATE utf8mb4_unicode_ci NOT NULL,
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE `worker` (
`worker_id` int(10) UNSIGNED NOT NULL,
`hire_date` date NOT NULL,
`person_id` int(10) UNSIGNED NOT NULL,
`notes` text COLLATE utf8mb4_unicode_ci
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE `worker_contract` (
`worker_contract_id` int(10) UNSIGNED NOT NULL,
`notes` text COLLATE utf8mb4_unicode_ci,
`worker_id` int(10) UNSIGNED NOT NULL,
`salary` decimal(10,2) NOT NULL,
`worker_id_boss` int(10) UNSIGNED DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE `worker_specialty` (
`worker_specialty_id` int(10) UNSIGNED NOT NULL,
`worker_id` int(10) UNSIGNED NOT NULL,
`notes` text COLLATE utf8mb4_unicode_ci
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
CREATE TABLE `describe` (
`describe_id` int(10) UNSIGNED NOT NULL,
`person_id` int(10) UNSIGNED DEFAULT NULL,
`describe` text COLLATE utf8mb4_unicode_ci
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
ALTER TABLE `person`
MODIFY `person_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=47;
ALTER TABLE `worker`
MODIFY `worker_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=45;
ALTER TABLE `worker_contact`
MODIFY `worker_contact_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2;
ALTER TABLE `describe`
MODIFY `describe_id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=8;
ALTER TABLE `person`
ADD PRIMARY KEY (`person_id`);
ALTER TABLE `worker`
ADD PRIMARY KEY (`worker_id`),
ADD KEY `person_id_FK` (`person_id`) USING BTREE;
ALTER TABLE `worker_contract`
ADD PRIMARY KEY (`worker_contract_id`),
ADD KEY `worker_id_FK` (`worker_id`) USING BTREE,
ADD KEY `person_id_boss_foreign` (`person_id_boss`);
ALTER TABLE `describe`
ADD PRIMARY KEY (`describe_id`);
ALTER TABLE `worker_contract`
ADD CONSTRAINT `worker_id_boss_foreign` FOREIGN KEY (`worker_id_boss`) REFERENCES `person` (`person_id`) ON DELETE CASCADE;
ALTER TABLE `describe`
ADD CONSTRAINT `person_id_tag_foreign` FOREIGN KEY (`person_id`) REFERENCES `person` (`person_id`) ON DELETE SET NULL;
Here is my problem, when I delete person table from databasa and I want to import it without checking foregin key I have #1005 cannot create 'db'.'person' (Errno: 150 "Foreign key constraint is incorrectly formed").
I create migration with Laravels ORM. All id field are the same type and there no mistakes in name fields.
When I remove constraint from DB it works and phpMyAdmin didn't show the relations between models. When I import db dump there is no errors.
When I have describet models in php code, in which place ORM use relations from model class? Only in app place?
When I remove constraints the db efficiency will will get smaller? And is it need?
What I should fix or what here is wrong?
First, disable FOREIGN_KEY_CHECKS
DB::statement('SET FOREIGN_KEY_CHECKS=0;'); // disable
//do your import logic
DB::statement('SET FOREIGN_KEY_CHECKS=1;'); //enable

SQLite database creating through script

There is the following script:
CREATE TABLE IF NOT EXISTS `location_cities` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`location_region_id` int(11) NOT NULL DEFAULT '0',
`location_district_id` int(11) DEFAULT NULL,
`location_country_id` int(11) NOT NULL DEFAULT '0',
`lon` float(11,8) NOT NULL DEFAULT '0.00000000',
`lat` float(11,8) NOT NULL DEFAULT '0.00000000',
`prefix` varchar(50) DEFAULT NULL,
`name` varchar(128) NOT NULL,
`size` int(3) NOT NULL DEFAULT '0' COMMENT 'Размер города',
`tz_name` varchar(128) DEFAULT NULL,
`timezone` varchar(100) NOT NULL DEFAULT '+00:00',
`timezone2` varchar(100) NOT NULL DEFAULT '+00:00',
PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=12393 ;
When I try to execute it using 'sqlite3 db/development.sqlite3 < alogist.sql' I got error 'Error: near line 27: near "AUTO_INCREMENT": syntax error' (27 - the line with "CREATE_TABLE ...". So, what's the trouble? How can I fix it? Thanks!
In sqlite, an autoincrement column is specified as
INTEGER PRIMARY KEY AUTOINCREMENT
Replace your int(11) NOT NULL AUTO_INCREMENT with that.
Further problems:
COMMENT is not supported. Remove COMMENT 'Размер города'
Remove PRIMARY KEY (ID) - the primary key has already been specified.
Remove the MySQL-specific ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=12393.
SQLite syntax:
`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL

How to insert into a table join other table using Activerecord in CodeIgniter?

I'm new to CodeIgniter and ORM, I hope you guys can help me with this.
The question table:
CREATE TABLE `question` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`title` varchar(128) NOT NULL DEFAULT '',
`content` text NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
The answer table:
CREATE TABLE `answer` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`question_id` int(11) unsigned NOT NULL,
`content` text NOT NULL,
PRIMARY KEY (`id`),
KEY `question_id` (`question_id`),
CONSTRAINT `answer_ibfk_1` FOREIGN KEY (`question_id`) REFERENCES `question` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
The equivalent SQL is:
INSERT INTO answer(content, question_id)
VALUES('Ironman', (select id
from question
where title ='favourite characters'
and content = 'Who is your favourite characters in Avanger?'));
Anyone can tell me how to achieve the same thing but using CodeIgniter Activerecord?
Don't do that, instead use the primary key (id) to insert directly into the base table.

Optimize a mysql like query

I added the jquery autocomplete plugin to my places textfield to help users better select a location. What I didn't realize before building is that the query would be very slow.
select * from `geoplanet_places` where name LIKE "%San Diego%" AND (place_type = "County" OR place_type = "Town")
The query above took 1.18 seconds. Then I tried adding indexes for name and place_type but that only slowed it down (1.93s).
Is there a way to optimize this query or is there another technique to speed up the query.
This geoplanet_places table has 437,715 rows (mysql)
CREATE TABLE `geoplanet_places` (
`id` int(11) NOT NULL auto_increment,
`woeid` bigint(20) default NULL,
`parent_woeid` bigint(20) default NULL,
`country_code` varchar(255) collate utf8_unicode_ci default NULL,
`name` varchar(255) collate utf8_unicode_ci default NULL,
`language` varchar(255) collate utf8_unicode_ci default NULL,
`place_type` varchar(255) collate utf8_unicode_ci default NULL,
`ancestry` varchar(255) collate utf8_unicode_ci default NULL,
`activity_count` int(11) default '0',
`activity_count_updated_at` datetime default NULL,
`bounding_box` blob,
`slug` varchar(255) collate utf8_unicode_ci default NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `index_geoplanet_places_on_woeid` (`woeid`),
KEY `index_geoplanet_places_on_ancestry` (`ancestry`),
KEY `index_geoplanet_places_on_parent_woeid` (`parent_woeid`),
KEY `index_geoplanet_places_on_slug` (`slug`),
KEY `index_geoplanet_places_on_name` (`name`),
KEY `index_geoplanet_places_on_place_type` (`place_type`)
) ENGINE=InnoDB AUTO_INCREMENT=5652569 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
EXPLAIN
id 1
select_type SIMPLE
table geoplanet_places
type ALL
possible_keys index_geoplanet_places_on_place_type
key NULL
key_len NULL
ref NULL
rows 441273
Extra Using where
You can switch the storage engine of the table to MyISAM to take advantage of full text indexing.
The name index wont help you unless you change the like to LIKE 'San Diego%' which can do a prefix search on the index
Get rid of the leading '%' in your where-like clause, so it becomes: where name like "San Diego%". For auto complete, this seems a reasonable limitation (assumes that the user starts typing correct characters) that should speed up the query significantly, as MySql will be able to use an existing index (index_geoplanet_places_on_name).

Slow query, can I speed it up?

I'm retrieving images stored as blobs in the database using a python script running on the same server.
SELECT *
FROM imagedb_production.imagedb IMAGE
LEFT JOIN dccms_production.tblmedia MEDIA ON IMAGE.name = MEDIA.name
LEFT JOIN dccms_production.tblmultimedia CAP ON MEDIA.contentItemID = CAP.contentItemID
LIMIT 5000,100;
An EXPLAIN returns
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE IMAGE index NULL name_idx 767 NULL 10145962 Using index
1 SIMPLE MEDIA ref name name 63 imagedb_production.IMAGE.name 1
1 SIMPLE CAP eq_ref PRIMARY,idx_contentItemID PRIMARY 4 dccms_production.MEDIA.contentItemID 1 Using index
(Sorry the output looks like crap)
This query takes close to 12 minutes is there any way I can speed this up before going through and tuning the mysql db instance?
Additional information
'imagedb', 'CREATE TABLE `imagedb` (
`multimediaID` int(11) NOT NULL auto_increment,
`name` varchar(255) NOT NULL,
`content` mediumblob,
`description` longtext,
`mime_type` varchar(255) default NULL,
PRIMARY KEY (`multimediaID`),
KEY `name_idx` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=2320759 DEFAULT CHARSET=utf8'
'tblmedia', 'CREATE TABLE `tblmedia` (
`mediaID` int(11) NOT NULL auto_increment,
`contentItemID` int(11) NOT NULL default ''0'',
`name` varchar(255) default NULL,
`width` int(11) default NULL,
`height` int(11) default NULL,
`file1Size` bigint(20) default NULL,
`file2Size` bigint(20) default NULL,
`mediaSlug` int(11) default NULL,
PRIMARY KEY (`mediaID`),
KEY `idx_contentItemID` (`contentItemID`),
KEY `name` (`name`(20))
) ENGINE=InnoDB AUTO_INCREMENT=899975 DEFAULT CHARSET=utf8'
'tblmultimedia', 'CREATE TABLE `tblmultimedia` (
`contentItemID` int(11) NOT NULL default ''0'',
`caption` text,
`mimeType` varchar(255) default NULL,
PRIMARY KEY (`contentItemID`),
KEY `idx_contentItemID` (`contentItemID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8'
You have 10,000,000 rows with no sorting, I would fix that. Add a default order by clause.
Older versions of MySQL did not take limit clauses into account until much later. I think newer versions do a better job of that. You might want to check into different ways to limit the result set.