CakePHP 2.0 Model relationships (Groups and Users) - orm

So, In my project there are groups and users. Each users belongs to a group, and one of those users is also an Admin of the group. I have been struggling to figure out how to map those relationships.
Currently with the set up I am creating a form that will create a new group, and its admin at the same time (so also a new user).
I want to know how to set this up so A- I can save the user and group correctly and B- So in the form both the user and the group information can be validated and show the errors.
This is the current layout of my DB tables
Groups Table:
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`user_id` int(10) unsigned DEFAULT NULL,
`name` varchar(60) NOT NULL,
`account_active` tinyint(1) DEFAULT NULL,
`create_date` date NOT NULL,
`last_modified` date NOT NULL,
`delete_date` date DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `groups_fk_admin` (`administrator`),
CONSTRAINT `groups_fk_admin` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`)
And the Users Table:
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`group_id` int(10) unsigned DEFAULT NULL,
`email` varchar(200) NOT NULL,
`password` varchar(40) NOT NULL,
`first_name` varchar(45) NOT NULL,
`last_name` varchar(45) NOT NULL,
`create_date` date NOT NULL,
`last_modified` date NOT NULL,
`delete_date` date DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `email` (`email`),
KEY `users_group_id_fk` (`group_id`),
CONSTRAINT `users_group_id_fk` FOREIGN KEY (`group_id`) REFERENCES `groups` (`id`)
Then my models are currently setup like....
Group Model:
public $hasMany = array(
'User' => array(
'className' => 'User',
'foreignKey' => 'group_id',
'dependent' => false,
)
);
public $belongsTo = array(
'Administrator' => array(
'className' => 'User',
'foreignKey' => 'user_id',
)
);
Users Model:
public $hasMany = array(
'Admin' => array(
'className' => 'Group',
'foreignKey' => 'user_id',
'dependent' => false,
),
);
public $belongsTo = array(
'Group' => array(
'className' => 'Group',
'foreignKey' => 'group_id',
)
);
Thank you for your help! And let me know if I can provide any more information.

Group hasMany User
User belongsTo Group
And just add another column to the Users table called is_admin or whatever, with the value of the ID of the group it is admin of.
For certain actions you should simply check if it passes a certain condition. So if you want to check if a user is an administrator of group 4, it has to check if it's is_admin id is equal to 4. You could set to 0 for 'normal' users.
Being a property of a user, administrator shouldn't be declared in your DB relation with a User hasMany admin and a group belongsTo admin, admin isn't a model on its own. It is a property of User, a role.

Related

SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'email' cannot be null [LARAVEL]

I don't know what is wrong my code,please help I am almost finish it. I am using Laravel 7 btw
I received this message when I wanna update the phone number/email/password
Illuminate\Database\QueryException
SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'email' cannot be null (SQL:
update `users` set `email` = ?, `password` =
$2y$10$KZBGY4BFJIWzgh2wGhQ3yuZivuzo..MOLs2ahAYbXpecOUZsZ/nvC, `users`.`updated_at` = 2022-01-26
21:46:50 where `id` = 7)
Here is my update function
public function updateStaffDetails(Request $request, Staff $staff, User $user)
{
//$name = $request->input('stud_name');
$staff->update([
'staffPhone' => $request['staffPhone'],
'staffEmail' => $request['staffEmail'],
'staffPassword' => $request['staffPassword'],
]);
$user =Auth::user();
$user->update([
//'name' => $staff->staffName,
'email' => $staff->staffEmail,
'password'=> Hash::make($staff->staffPassword), //bcrypt($staff->staffPassword)
]);
$staff->user_id = $user->id;
$user->save();
$staff->save();
return redirect()->route('home',Auth::user())
->with('success','Staff details updated successfully.');
}
as you can see the Staff table will be copied to the users table once it is updated but the email from Users table is null...
here is my routes (because I think the problem is my route but i am not sure )
//admin show details
Route::get('/showDetailsAdm', 'StaffController#showDetailsAdm')->name('admins.showDetailsAdm');
//admin update
Route::put('/admins/updateStaffDetails', 'StaffController#updateStaffDetails')->name('admins.updateStaffDetails');
here is the picture of the column Staffs and Users user_id is FK from Users table
tables
Your route must be like
Route::put('users/{user}/staffs/{staff}/update','StaffController#updateStaffDetails')->name('admins.updateStaffDetails');
Then you can get $user and $staff in your controller. Now, $staff isn't null so you can get email from it.
While calling to this route you need to pass user_id and staff_id as shown below:
route('admins.updateStaffDetails', [$user_id, $staff_id] )

Laravel Violates not-null constraint with default value

I am having an issue with Laravel and default values. I created the field in my table like so:
$table->string('title', 255)->default('');
And in the model, I have a default set again using this:
protected $attributes = [
'title' => '',
];
Yet I am always getting this error:
SQLSTATE[23502]: Not null violation: 7 ERROR: null value in column
"title" violates not-null constraint DETAIL: Failing row contains
(3dd07c7a-e3f3-4f20-8d16-0f066b219dc2, dsfs, sdfs, null, null, null,
sdfs, null, 0, 0, 0, 0, 0, 0, null, null, null). (SQL: insert into
"users" ("title", "first_name", "last_name", "email", "business_unit",
"linkedin_profile") values (, dsfs, sdfs, sdfs, , ) returning
"user_id")
My abbreviated save action (example without validation) is the following:
$data = Input::all();
$user = new Users($data);
$user->save();
The following is the $data:
array (size=12)
'_token' => string '0EI9JGmgiNDAqmv83pdQZaktyWNLiX3GB9JQSfvA' (length=40)
'first_name' => string 'ads' (length=3)
'last_name' => string 'asd' (length=3)
'email' => string 'asd' (length=3)
'title' => null
'business_unit' => null
'linkedin_profile' => null
'is_admin' => string '0' (length=1)
'is_employee' => string '0' (length=1)
'is_manager' => string '0' (length=1)
'is_trainer' => string '0' (length=1)
'rt' => string '/users' (length=6)
How come my default value is not being set?
The problem is that your database column does not allow null values for title.
You can allow them like this:
$table->string('title')->nullable()->default('');
Or even without the default to have it as NULL by default:
$table->string('title')->nullable();
Otherwise, you have to make sure your title is not null.
If you don't want to allow null values and convert it automatically to empty string, you can add a mutator like this to your model:
public function setTitleAttribute($title)
{
$this->attributes['title'] = is_null($title) ? '' : $title;
}
For more information: https://laravel.com/docs/5.6/eloquent-mutators
Because the 'title' key is in the provided array, it'll try to insert it: you should be able to insert null values.
You could use a mutator setTitleAttribute($val) method in your Model class, or simply unset the 'title' array key if the value is empty before inserting. You could also filter using collection helpers or array_filter to remove unset all null values.

How to get multiple table values to gridview?

I have two tables and i need to filter and put those two table data to gridview.i use joined two table like this
$student=new Student;
$marks=new AssimentMarks;
$criteria_st=new CDbCriteria;
$criteria=new CDbCriteria;
$criteria->select = 't.st_id,t.st_name,stu.ass_id,stu.marks_cr1,stu.marks_cr2,stu.marks_cr3,stu.marks_cr4,stu.marks_cr5';
$criteria->join = 'INNER JOIN assiment_marks stu ON stu.st_id=t.st_id';
$criteria->condition = 'stu.ass_id=:ass_id';
$criteria->params = array(':ass_id'=>Yii::app()->session['modelcrite']['ass_id']);
$criteria->addInCondition('t.st_id', $studentid);
return new CActiveDataProvider($student, array('criteria'=>$criteria,));
but in gridviwe only show the student database values.it is show as .how can i pass two models to CActiveDataProvider ?
this is how data shows
http://i.stack.imgur.com/Kogjz.jpg
1) Foreign key in schema
Your assiment table should reference your student table with a foreign key, like this (assuming SQLite):
CREATE TABLE student (
id INTEGER PRIMARY KEY,
name TEXT
);
CREATE TABLE assiment_record(
id INTEGER PRIMARY KEY,
student_id INTEGER,
cr1 INTEGER,
cr2 INTEGER,
cr3 INTEGER,
cr4 INTEGER,
cr5 INTEGER,
FOREIGN KEY( student_id ) REFERENCES student(id) -- FK goes in the CHILD table.
);
2) Generate models with Gii:
student -> models/Student.php
assiment_record -> models/AssimentRecord.php
Gii is smart and guesses your relations:
// AssimentRecord.php looks good! No changes made!
public function relations()
return array(
'student' => array(self::BELONGS_TO, 'Student', 'student_id'),
);
The assiment record BELONGS TO the student.
3) Tweak gii's output (Student.php)
But Gii's is not perfect, and does not know what your intentions are. The current student relation (HAS_MANY) returns an array, but I don't want to deal with the array (because I'm lazy!), so I change it into a HAS_ONE-relation instead:
// Student.php
public function relations()
{
return array(
// Change this: 'assimentRecords' => array(self::HAS_MANY, 'AssimentRecord', 'student_id'),
/* into this: */ 'assimentRecord' => array(self::HAS_ONE, 'AssimentRecord', 'student_id'),
);
}
The student HAS ONE assiment record.
4) Display the grid:
// views/site/index.php (Or wherever.)
$dataProvider = new CActiveDataProvider( 'Student' );
$this->widget('zii.widgets.grid.CGridView', array(
'dataProvider'=>$dataProvider,
'columns' => array(
'id',
'name',
'assimentRecord.cr1',
'assimentRecord.cr2',
'assimentRecord.cr3',
'assimentRecord.cr4',
'assimentRecord.cr5',
)
));

the column 'id' is not the primary_key ,how to reset the Relationship

I have a table form the second database,it is not through a migration
class Dzhfeed < Dzxdb
set_table_name "pre_home_feed"
set_primary_key :feedid
end
the table:
CREATE TABLE pre_home_feed (
feedid int(10) unsigned NOT NULL auto_increment ,
appid smallint(6) unsigned NOT NULL default '0' ,
icon varchar(30) NOT NULL default '' ',
uid mediumint(8) unsigned NOT NULL default '0' ,
username varchar(15) NOT NULL default '' ',
dateline int(10) unsigned NOT NULL default '0' ,
friend tinyint(1) NOT NULL default '0',
hash_template varchar(32) NOT NULL default '' ,
hash_data varchar(32) NOT NULL default '' ,
title_template text NOT NULL,
title_data text NOT NULL,
body_template text NOT NULL ,
body_data text NOT NULL,
body_general text NOT NULL ,
image_1 varchar(255) NOT NULL default '' ,
image_1_link varchar(255) NOT NULL default '',
image_2 varchar(255) NOT NULL default '' ,
image_2_link varchar(255) NOT NULL default '' ,
image_3 varchar(255) NOT NULL default '' ,
image_3_link varchar(255) NOT NULL default '' ,
image_4 varchar(255) NOT NULL default '' ,
image_4_link varchar(255) NOT NULL default '' ,
target_ids text NOT NULL ,
id mediumint(8) unsigned NOT NULL default '0' ,
idtype varchar(15) NOT NULL default '' ,
hot mediumint(8) unsigned NOT NULL default '0' ,
PRIMARY KEY (feedid),
KEY uid (uid,dateline),
KEY dateline (dateline),
KEY hot (hot),
KEY id (id,idtype)
) ;
but this table has another column named 'id' and not a primary_key
so ,when i want to create a new Dzhfeed ,I don't know how to set the column named id
my code is
feed = Dzhfeed.new(:appid => 0, :icon => 'doing', :uid => 1, :username => 'admin', :title_template => "xxxxxxxxxx", :body_template => '', :dateline => Time.now, :id => 0)
but it not work
the error is
Mysql::Error: Column 'id' cannot be null: INSERT INTO `pre_home_feed` (`image_3`, `uid`, `id`, `dateline`, `title_template`, `idtype`, `image_1`, `username`, `body_template`, `image_1_link`, `image_3_link`, `friend`, `title_data`, `appid`, `body_data`, `image_2_link`, `hot`, `image_4_link`, `image_4`, `hash_template`, `body_general`, `icon`, `target_ids`, `hash_data`, `image_2`) VALUES ('', 1, NULL, 1304675043, 'xxxxxxxxxx', '', '', 'admin', '', '', '', 0, '', 0, '', '', 0, '', '', '', '', 'doing', '', '', '')
How did you create the table "pre_home_feed". If it is through a migration, it would have added a id column by default and set it as a primary key. In order not to add a 'id' column you have to say :id => false, :force => true in your table definition migration file and re-run the migration. ( Re-running a migration would first require a rollback, rake db:rollback. This command will undo the last migration run. )
The way you're setting the primary key is perfectly fine. You go about creating the objects in the standard way like this;
#feed = Dzhfeed.new( :feedid => :value .. )
I suggest you go through the Rails Guides.
Update:
Linking to a two different databases is a little different. Essentially, you need to use the establish_connection method defined in ActiveRecord::Base to do that:
establish_connection(
:adapter => "postgresql",
:host => "localhost",
:username => "username",
:password => "password",
:database => "database_to_link_to"
)
Update:
According to this post here your problem should be solved using composite_primary_keys gem.
Essentially what you need to do is this:
Install the gem composite_primary_keys, and then
require 'composite_primary_keys'
class Dzhfeed < Dzxdb
set_primary_keys :feedif
end
Notice, it is set_primary_keys and not set_primary_key. This should solve your problem.

cakephp testing suite: import fixtures tables for HABTM

I have a model Post -> hasAndBelongsToMany -> Tag
For testing, I created the fixtures for each model, for example, a fixture for the model Post looks like this
class PostFixture extends CakeTestFixture {
var $import = array('model' => 'Post', 'records' => true, 'connection' => 'fixtures');
}
And everything works great for that Model, but when I try to create the fixture for the HABTM relationship, using the same approach doesn’t work:
class PostsTagFixture extends CakeTestFixture {
var $import = array('model' => 'PostTag', 'records' => true, 'connection' => 'fixtures');
}
The SQL generated by CakePHP is the following
CREATE TABLE `service_types_technicals` (
`technical_id` int(20) NOT NULL AUTO_INCREMENT,
`service_type_id` int(20) NOT NULL AUTO_INCREMENT,
`id` varchar(255) NOT NULL, PRIMARY KEY (`id`)) ;
Wich is not correct because the table does not have a field named id.
Then, I tried this:
class PostsTagFixture extends CakeTestFixture {
var $name = 'PostsTag';
var $import = array('table' => 'posts_tags', 'records' => true, 'connection' => 'fixtures');
}
And again, error, but this time the SQL was:
CREATE TABLE `service_types_technicals` (
`technical_id` int(20) NOT NULL AUTO_INCREMENT,
`service_type_id` int(20) NOT NULL AUTO_INCREMENT, PRIMARY KEY (`service_type_id`)) ;
What am I doing wrong? What is the correct way to import fixtures from another database for has and belongs to many relationships?
Thank you!
Mauro Zadunaisky,
as you state that service_types_technicals does not have an id field, I guess that CakePHP automatically deduces a HABTM from service_types to technicals, as both are nouns written in plural (CakePHP convention). If this is not what you had in mind, then you are forced to alter the name of the table to stay within the conventions.
The problem was the missing of the field id in the habtm relation table, it's fixed now