Im trying out a sample project in CakePHP. It is taken from the cakePHP documentation. It has a total of 4 tables and two of the are listed here.
CREATE TABLE users (
id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(255) NOT NULL UNIQUE,
password CHAR(40) NOT NULL,
group_id INT(11) NOT NULL,
created DATETIME,
modified DATETIME
);
CREATE TABLE posts (
id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
user_id INT(11) NOT NULL,
title VARCHAR(255) NOT NULL,
body TEXT,
created DATETIME,
modified DATETIME
);
As you can see the id from the users table is added to the posts table as a foreign key in the form of user_id. But in the sample there are no relationships defined. I mean normally we would explicitly define user_id as a foreign key by adding the constraints (in my case using the Relation View of phpMyAdmin). But it is not done here or we are not instructed to do so. When using Cake Bake console to bake our Models do we need this foreign key constraints in place or does cakephp figure them out automatically?
Convention over configuration
Cakephp figures them out automatically for you but you have to follow the naming conventions
Related
I have a couple of questions about zf-oauth (Apigility), and php-oauth server database schema.
The database schema is:
CREATE TABLE oauth_clients (
client_id VARCHAR(80) NOT NULL,
client_secret VARCHAR(80) NOT NULL,
redirect_uri VARCHAR(2000) NOT NULL,
grant_types VARCHAR(80),
scope VARCHAR(2000),
user_id VARCHAR(255),
CONSTRAINT clients_client_id_pk PRIMARY KEY (client_id)
);
CREATE TABLE oauth_access_tokens (
access_token VARCHAR(40) NOT NULL,
client_id VARCHAR(80) NOT NULL,
user_id VARCHAR(255),
expires TIMESTAMP NOT NULL,
scope VARCHAR(2000),
CONSTRAINT access_token_pk PRIMARY KEY (access_token)
);
CREATE TABLE oauth_authorization_codes (
authorization_code VARCHAR(40) NOT NULL,
client_id VARCHAR(80) NOT NULL,
user_id VARCHAR(255),
redirect_uri VARCHAR(2000),
expires TIMESTAMP NOT NULL,
scope VARCHAR(2000),
id_token VARCHAR(2000),
CONSTRAINT auth_code_pk PRIMARY KEY (authorization_code)
);
CREATE TABLE oauth_refresh_tokens (
refresh_token VARCHAR(40) NOT NULL,
client_id VARCHAR(80) NOT NULL,
user_id VARCHAR(255),
expires TIMESTAMP NOT NULL,
scope VARCHAR(2000),
CONSTRAINT refresh_token_pk PRIMARY KEY (refresh_token)
);
CREATE TABLE oauth_users (
username VARCHAR(255) NOT NULL,
password VARCHAR(2000),
first_name VARCHAR(255),
last_name VARCHAR(255),
CONSTRAINT username_pk PRIMARY KEY (username)
);
CREATE TABLE oauth_scopes (
type VARCHAR(255) NOT NULL DEFAULT "supported",
scope VARCHAR(2000),
client_id VARCHAR (80),
is_default SMALLINT DEFAULT NULL
);
CREATE TABLE oauth_jwt (
client_id VARCHAR(80) NOT NULL,
subject VARCHAR(80),
public_key VARCHAR(2000),
CONSTRAINT jwt_client_id_pk PRIMARY KEY (client_id)
);
You can find it at:
https://github.com/zfcampus/zf-oauth2
https://bshaffer.github.io/oauth2-server-php-docs/
https://apigility.org/documentation/modules/zf-oauth2
So, this schema seems really "standard" because is adopted by Zend Technologies (zend framework and apigility), but I have some questions:
Why aren't any "ordinary" primary keys? (int auto increment field).
I would to use oauth_users table for registration account and the form's fields are "email" and "password". I could store email into oauth_users.username field, but It does not seem a good idea to use this field as a foreign key. Finally, my url looks better in profile-url/[:id] than profile-url/[:username/] (email in my case). So, I have to create a custom primary key or I could go against problems?
Why aren't any foreign keys? this questions is related to the first. I have to add foreign keys or I could go against problems? using oauth_users.username as foreign key for my other tables, It does not seem a good idea.
As you can see in the composer json require list ZF-Oauth2 is built on top of bshaffer/oauth2-server-php for which you can find the original documentation here. It has some nice explanations on the working of OAuth2. It is also the same repository that #Adam is referring to.
You can definitely customize these OAuth modules to a certain extend (like use your own table names). To do this you can introduce a custom OAuthAdapter with your own logic. There are also other modules available that do exactly that, like for example this zf-oauth2-doctrine module that is made for using OAuth2 with Doctrine 2.
That one comes with the following database diagram (source: https://github.com/API-Skeletons/zf-oauth2-doctrine):
Here is the scenario: I have been following the "yii" book by Larry Ullman in which he gave his MYsql for CMS but he didn't described any tool , how to create these tables of sql. The only way I know is through migrations but the sql written in the book is not working in migrations.
The sample sql is given for a table from the book :
CREATE TABLE IF NOT EXISTS yii_cms.user ( id INT UNSIGNED NOT NULL AUTO_INCREMENT,
username VARCHAR(45) NOT NULL,
email VARCHAR(60) NOT NULL,
pass CHAR(64) NOT NULL,
type ENUM('public','author','admin') NOT NULL,
date_entered TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id),
UNIQUE INDEX username_UNIQUE (username ASC),
UNIQUE INDEX email_UNIQUE (email ASC) )
ENGINE = InnoDB DEFAULT
CHARACTER SET = utf8
If you don't mind, you can use straight-forward way to execute sql so:
$sql = 'your sql here';
Yii::app()->db->createCommand($sql)->execute();
The other way is to use Yii QueryBuilder and the createTable() command. More information for QueryBuilder is here and for createTable() here.
Alright, I have been searching and finding very much about this subject,
but nothing satisfying.
I want to keep track of who has liked what, not just add a +1 to a table.
I have three tables: posts, comments and likes.
The table design looks like this for the moment
CREATE TABLE IF NOT EXISTS `likes` (
`like_id` int(11) NOT NULL PRIMARY KEY AUTO_INCREMENT,
`post_id_fk` INT(11),
`comment_id_fk` INT(11),
`uid_fk` int(11) NOT NULL,
`date` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`ip` varchar(39) COLLATE utf8_unicode_ci NOT NULL DEFAULT '0.0.0.0',
FOREIGN KEY (uid_fk) REFERENCES users(uid),
FOREIGN KEY (post_id_fk) REFERENCES post(post_id),
FOREIGN KEY (comment_id_fk) REFERENCES comments(comments_id),
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1;
And as you can see i have three different foreign keys, uid_fk for the user uid so i can know who has liked what. And now comes there problem, one foreign key to post_id and one for comments_id.
Mysql won't accept a foreign key if it doesn't exist. if i want to "like" a comment, it won't let be because of the foreign key of post_id_fk.
How to solve this DB mess?
And the AJAX like/delike problem:
I found this jQuery : Changing class of button with AJAX call when i was searching, and it looks simpel and very nice. And i have also follow this http://pluscss.com/tutorials/ajax-like-script-using-php-mysql-jquery tutorial. But I'm having problems combine them.
This is what I'm trying to do:
count the current amount of likes
check if the user have liked it before
give the user the option to like (or delike if previously liked)
with ajax and like.php
Could someone help me with this i would be very thankful!
It would be better to separate the tables.
Create a post_likes table and comments_likes table.
That way not only you're getting rid of your existing problem but the structure is more decoupled and more reusable.
There are numerous 'getting started' tutorials out there on how to implement zfc-user and zfc-rbac into Zend Framework 2. The github pages for zfc-user and zfc-rbac (https://github.com/ZF-Commons) are clear and the implementation is indeed pretty easy (as stated on many of the tutorials). I also found the SQL schemes which are needed for both zfc-user and zfc-rbac (/vendor/zf-commons/zfc-[user/rbac]/data/).
The creation of a user into the database is easy, since zfc-user already sets this up for you (http://example.com/user). Everything fine so far. Now I want to populate the roles, but it's not clear to me on how to populate the rbac tables correctly. The lack on information about this surprises me, since the zfc-rbac component is a popular module for the Zend Framework.
I understand the principal of Role Based Access Control and the population of the tables for the permissions and the table linking the permissions and roles together are clear, it's the role table that's not clear to me. I understand that you can have a role which has a parent role, but it's not clear how to populate the table with a parent role since there is a foreign key constraint which states the 'parent_role_id' has to be a 'role_id'.
Below is the SQL for the role table (this is the SQL provided by zfc-rbac):
CREATE TABLE `rbac_role` (
`role_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`parent_role_id` int(11) unsigned NOT NULL,
`role_name` varchar(32) NULL,
PRIMARY KEY (`role_id`),
KEY `parent_role_id` (`parent_role_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
ALTER TABLE `rbac_role`
ADD CONSTRAINT `rbac_role_ibfk_1` FOREIGN KEY (`parent_role_id`) REFERENCES `rbac_role` (`role_id`);
With the foreign key in place adding a parent role seems impossible?
INSERT INTO `rbac_role` (parent_role_id, role_name) VALUES (NULL, 'admin');
Basically my question is (and I feel very stupid for asking this) but how does an insert for a parent role look like? And if the insert statement I presented is in fact correct, do I always need to remove the foreign key before inserting a parent role?
Change your create table to the following:
CREATE TABLE `rbac_role` (
`role_id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`parent_role_id` int(11) unsigned NULL,
`role_name` varchar(32) NULL,
PRIMARY KEY (`role_id`),
KEY `parent_role_id` (`parent_role_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;
Notice that parent_role_id is NULL instead of NOT NULL. If parent_role_id is NOT NULL then that means that it has to have a parent but since the foreign key reference is to the same table there is no way to insert a parent row!
fyi: This issue has been fixed. Version 0.2.0 of zfc-rbac will allow NULL value as parent_role_id
I have 2 tables: release_servers and release_components
I have a link table release_server_to_components
I right now have it so that each server can have multiple components and that each component can be on multiple servers.
The following are the create statements:
CREATE TABLE `release_components` (
`id` int(11) NOT NULL auto_increment,
`buildID` varchar(45) default NULL,
`svnNumber` varchar(45) NOT NULL,
`componentType` varchar(45) NOT NULL,
`release_id` varchar(45) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM
CREATE TABLE `release_servers` (
`id` int(11) NOT NULL auto_increment,
`server_name` varchar(45) NOT NULL,
`server_environment` varchar(45) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM
Link table:
CREATE TABLE `release_server_to_components` (
`id` int(11) NOT NULL auto_increment,
`release_component_id` int(11) NOT NULL,
`release_server_id` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM
What I want to add is the ability to have a system ID -- this system ID would be per component on a server (not per server and not per component, but per the component on each server). I want to be able to easily add the system ID per component and insert it into the database.
I can provide code for models and controllers if needed.
You want to "fake" Ruby's through association with CakePHP.
Why do this over HABTM?
Because you want to save data about the association. With Cake's HABTM saving data about the association is difficult, because the only thing you really have is a JOIN table. You need something more powerful than this.
First, get rid of the $hasAndBelongsToMany property in your model. Next we'll be refitting your release_server_to_components table as your "through" table.
So, in ReleaseComponent and ReleaseServer model you would have an association like this:
$hasMany = array('ReleaseServerToComponent');
Now, in your new ReleaseServerToComponent model you would have an association like this:
$belongsTo = array('ReleaseComponent', 'ReleaseServer');
Now, you can access this table just like a normal Cake model, ie $this->ReleaseServer->ReleaseServerToComponent->find(). You can add additional fields to the through table, like server_component_name. You already have a unique identifier for specific, server components with the primary key of the release_server_to_components table.
You could save this data using Cake's saveAll() method. Alternatively you could generate your own data to save, simply plugging in the server ID and component ID from form fields. At the top of that link is the format saved data should be in when you pass it to the model's save method.