I have 2 tables
CREATE TABLE `tbl_patient` (
id_patient INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(25) NOT NULL DEFAULT "not available",
att1 VARCHAR(5 ) NOT NULL DEFAULT "att1",
att2 VARCHAR(25) NOT NULL DEFAULT "att2",
att3 VARCHAR(25) NOT NULL DEFAULT "att3",
CONSTRAINT `uc_Info_patient` UNIQUE (`id_patient`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;
and
CREATE TABLE `tbl_patient_medicine` (
id_patient_medicine INTEGER NOT NULL PRIMARY KEY AUTO_INCREMENT,
id_patient INTEGER NOT NULL,
name_medicine VARCHAR(50) NOT NULL DEFAULT "",
dosis VARCHAR(50) NOT NULL DEFAULT "",
start_date timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
treatment VARCHAR(50) NOT NULL DEFAULT "",
times_per_day VARCHAR(50) NOT NULL DEFAULT "",
CONSTRAINT fk_ID_Patient_Medicine FOREIGN KEY (id_patient) REFERENCES `tbl_patient`(id_patient)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;
As you can see table patient_medicine is the intermediate table of between tbla_medicines, and table patient.
Now I want to consult all data from tbl_patient_medicine with grocery crud like in this sqlfiddle
supossing I pass the id in the uri (in the example will be id_patient=1)
I have
public function details_medication($my_id = 0)
{
try{
$crud = new grocery_CRUD();
$crud->where('id_patient',$my_id);
$crud->set_table('tbl_patient_medicine');
//HOW TO DO IT?
$crud->set_relation('id_patient', 'tbl_patient', 'id_patient');
$output = $crud->render();
$this->_output($output);
}catch(Exception $e){
show_error($e->getMessage().' --- '.$e->getTraceAsString());
}
}
SO I have tried different ways but got errors like this:
A Database Error Occurred
Error Number: 1052
Column 'id_patient' in where clause is ambiguous
SELECT `tbl_patient_medicine`.*, j7a675883.id_patient AS s7a675883
FROM (`tbl_patient_medicine`)
LEFT JOIN `tbl_patient` as j7a675883
ON `j7a675883`.`id_patient` = `tbl_patient_medicine`.`id_patient` WHERE `id_patient` = '1' LIMIT 25
Line Number: 87
I did your example:
Controller:
function medicine()
{
$crud = new grocery_CRUD();
$crud->set_table('tbl_patient_medicine');
$crud->required_fields('id_patient','name_medicine','dosis','start_date','treatment','time_per_day');
$crud->columns('id_patient','name_medicine','dosis','start_date','treatment','time_per_day');
$crud->fields('id_patient','name_medicine','dosis','start_date','treatment','time_per_day');
$crud->set_relation('id_patient','tbl_patient','name');
$output = $crud->render();
$this->_example_output($output);
}
It works!
Edited:
$crud->set_relation('id_patient','tbl_patient','{name}, {att1}, {att2}, {att3}');
Try by changing WHERE j7a675883.id_patient
Related
I have 3 models: User, Payment and Log. A User has many Payment and both User and Payment have many Log.
User Model
class User
{
public function payments()
{
return $this->hasMany('Payment', 'user_id');
}
public function logs()
{
return $this->morphMany(Log::class, 'loggable');
}
}
users table
CREATE TABLE `users` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`email` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`email_verified_at` timestamp NULL DEFAULT NULL,
`password` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`remember_token` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `users_email_unique` (`email`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
Payment Model
class Payment
{
public function user()
{
return $this->belongsTo('User', 'user_id');
}
public function logs()
{
return $this->morphMany(Log::class, 'loggable');
}
}
payments table
CREATE TABLE `payments` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`status` varchar(50),
`amount` int(11) NOT NULL,
`collection_date` date NOT NULL,
`created_at` timestamp NULL DEFAULT NULL,
`updated_at` timestamp NULL DEFAULT NULL,
`user_id` bigint(20) unsigned NOT NULL,
PRIMARY KEY (`id`),
CONSTRAINT `fk_payments_user_id` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
Log Model
class Log
{
public function loggable()
{
return $this->morphTo();
}
}
logs table
CREATE TABLE `logs` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`loggable_type` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
`loggable_id` bigint(20) unsigned NOT NULL,
`old_values` text COLLATE utf8mb4_unicode_ci,
`new_values` text COLLATE utf8mb4_unicode_ci,
`user_id` bigint(20) unsigned DEFAULT NULL, /* the user that made the change, if any */
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
The Log model stores all changes made to any other model (it's a polymorphic relationship), so if the user changes its name, the Log model will store the older name and the new name. The same applies to Payment: if a payment status changes the Log model will have a new record with the old status and the new status.
I need to show a paginated list of all Log records for a specific User ordered by date. So my code is:
$user = App\User::find($id);
$allLogs = $user->logs();
// Now I need to join (I'm using union) both sets of logs
$allLogs->union($user->payments->logs());
However, since a User can have many Payment, $user->payments returns a Collection, so is no longer a query builder/eloquent object and it fails when I try to call ->logs().
$user->payments()->logs() also doesn't work, because $user->payments() returns a HasMany object and the ->logs() method doesn't exist.
I'm trying to avoid getting each collection of Log separately and then processing them using php (it would be perfect to delegate that task to MySql).
I believe it can be done, because I can write the query on MySql:
select l.*
from payments p
join logs l on p.id = l.loggable_id and l.loggable_type = 'App\\Payments'
where p.user_id = SOMEUSERID
Thanks in advance
Eager load the relations(reduces number of queries)
$user = User::with(['payments.logs', 'logs'])->find($id);
Query using the Log model.
$logs = Log::where([
'loggable_id' => $user->id,
'loggable_type' => 'User',
])
->orWhere(function($query){
$query->whereIn('loggable_id',
$user->payments()->pluck('id'))
->where('loggable_type', 'Payment');
})->get();
OR
Get them individually and then combine them.
$all_logs = collect([]);
$all_logs->push($user->logs);
foreach($user->payments as $p){
$all_logs->push($p->logs);
}
$final_logs = $all_logs->collapse();
OR
Just use the relations, without iterating over the payments. You can combine the results if you want(as shown in the previous approach).
$user_logs = $user->logs;
$payment_logs = $user->payments->pluck('logs')->collapse();
I need to use my Website model to get a row from my database within the websites table, however this row is identified through my domains table.
So basically it would be great to do a query on my domains table and match the row, then from that get the website row from the websites table using the website_id column.
But I want to simply pass this data into my controller by just referencing the Model within the method.
class WebsiteController extends Controller {
public function index(Website $website) {
print_r($website);
return view('index');
}
}
My domains table:
CREATE TABLE `domains` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`website_id` INT(11) NOT NULL DEFAULT '0',
`domain` VARCHAR(255) NOT NULL DEFAULT '0',
`active` INT(11) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`),
INDEX `website_id` (`website_id`),
CONSTRAINT `website_id` FOREIGN KEY (`website_id`) REFERENCES `websites` (`id`)
)
COMMENT='This table will contain all of the domains registered on MarvWeb, this will link to the website record. '
COLLATE='latin1_swedish_ci'
ENGINE=InnoDB
AUTO_INCREMENT=3;
And websites table:
CREATE TABLE `websites` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255) NULL DEFAULT NULL,
`tagline` VARCHAR(255) NULL DEFAULT NULL,
`description` VARCHAR(255) NULL DEFAULT NULL,
PRIMARY KEY (`id`)
)
COMMENT='This table will contain all the websites data. '
COLLATE='latin1_swedish_ci'
ENGINE=InnoDB
AUTO_INCREMENT=2;
Does this make sense?
Add a website function to your Domain model.
class Domain extends Model{
public function website(){
return $this->hasOne('App\Website');
}
// remainder of model.
}
When you retrieve the Domain query results, the website can be accessed by
print_r($domainRowResult->$website->tagline);
I found this useful Internationalization code:
http://pastebin.com/SyKmPYTX
everything works well except I am unable to connect to database.
what I need:
1) I need to check last segment
2) this is my db
DROP TABLE IF EXISTS `translate`;
DROP TABLE IF EXISTS `trans_data`;
DROP TABLE IF EXISTS `languages`;
/*Table structure for table `languages` */
CREATE TABLE `languages` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL,
`key` varchar(5) NOT NULL,
`default` tinyint(1) NOT NULL DEFAULT '0',
`display` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
/*Data for the table `languages` */
insert into `languages`(`name`,`key`,`default`,`display`) values
('GEO','ka',1,1),
('ENG','en',0,1),
('RUS','ru',0,1);
/*Table structure for table `trans_data` */
CREATE TABLE `trans_data` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(250) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;
/*Table structure for table `translate` */
CREATE TABLE `translate` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`lang` int(11) NOT NULL,
`data` int(11) NOT NULL,
`trans` text NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `lang_2` (`lang`,`data`),
KEY `lang` (`lang`),
KEY `data` (`data`),
CONSTRAINT `translate_ibfk_1` FOREIGN KEY (`lang`) REFERENCES `languages` (`id`),
CONSTRAINT `translate_ibfk_2` FOREIGN KEY (`data`) REFERENCES `trans_data` (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=340 DEFAULT CHARSET=utf8;
in the first I need to do something like this
$this->db->where('key', end($this->segments));
$query = $this->db->get('languages');
$lang = $query->row();
if(empty($lang)){
$this->db->where('default', 1);
$query2 = $this->db->get('languages');
$lang = $query2->row();
}
$lang_array = [
"lang_key" => $lang->key,
"lang_id" => $lang->id
];
$this->session->set_userdata($lang_array);
if(end($this->uri->segment_array()) == $lang->key){
unset($this->uri->segments[intval($this->uri->total_segments() - 1)]);
}
after this functionality
then I need to download translates from database and save it in object with this query
SELECT TD.`name` , T.`trans`
FROM `translate` AS T
INNER JOIN `languages` AS L ON (T.`lang` = L.`id`)
INNER JOIN `trans_data` AS TD ON (T.`data` = TD.`id`)
WHERE (L.`key` = :lang_key);
and when I call from view
echo $this->lang->line('trans_key');
I need to get the value
but I do not undestand how to edit this class to do this job...
can you help me and edit this class for me?
thank you for future...
I have a problem while trying to save data (or update) in a crud with n_n relation, i have a product table, who is related to a product_detail, product detail has 3 foreign keys, to connect to a table called color, and other called material. Any idea why fail?, i appreciate your help, thanks.
The error is this:
A Database Error Occurred
Error Number: 1452
Cannot add or update a child row: a foreign key constraint fails (medina_db.product_detail, CONSTRAINT product_detail_ibfk_3 FOREIGN KEY (material_id) REFERENCES material (id))
INSERT INTO product_detail (product_id, color_id) VALUES ('4', '1')
Filename: /Applications/MAMP/htdocs/industrias_medina/models/grocery_crud_model.php
Line Number: 413
My Grocery Crud code:
$crud = new grocery_CRUD();
$crud->set_table('product')->set_subject('Productos');
$crud->set_relation_n_n("Colores", 'product_detail', 'color', 'product_id', 'color_id', 'name');
$crud->set_relation_n_n("Materiales", 'product_detail', 'material', 'product_id', 'material_id', 'name');
$crud->set_field_upload('image','assets/uploads/files');
$crud->fields('name','model','description', "Colores", "Materiales", 'image');
$output = $crud->render();
$this->_productos_output($output);
SQL:
CREATE TABLE `color` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(250) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=ucs2 AUTO_INCREMENT=2 ;
CREATE TABLE `material` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(250) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ;
CREATE TABLE `product` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'Unique identifier',
`name` varchar(250) NOT NULL COMMENT 'Product''s name',
`model` varchar(250) NOT NULL COMMENT 'Product''s model',
`description` varchar(400) NOT NULL COMMENT 'Product''s description',
`image` varchar(400) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Table to store products' AUTO_INCREMENT=13 ;
CREATE TABLE `product_detail` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`product_id` int(11) NOT NULL,
`color_id` int(11) NOT NULL,
`material_id` int(11) NOT NULL,
PRIMARY KEY (`id`,`product_id`,`color_id`,`material_id`),
KEY `product_id` (`product_id`),
KEY `color_id` (`color_id`),
KEY `material_id` (`material_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=14 ;
It looks like your product_detail table has a material_id column that references the material table. Your insert statement is not inserting anything into that material_id column. You need to either insert a value into that column (that exists in material), set a default value that references the key in material, or set a default of NULL for that column.
Thanks,
Andrew
Im using phpmyadmin and I have a table categories with 4 fields:
-> id
-> id_father_category (I put this with predefined: NULL) and I also put a checkbox Null
-> name
-> content
I want to give null values to my id_father_category field.
But Im having this error:
Warning: #1366 Incorrect integer value: '' for column 'id_father_category field' at row 1
And my field id_father_category stays automatically with value 0, and I dont want that.
Somebody there knows how I can solve this problem?
CREATE TABLE IF NOT EXISTS `categories` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`id_father_category` int(11) DEFAULT NULL,
`name` varchar(64) NOT NULL,
`content` varchar(256) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
Hope this will solve your problem...
This is an addition to #Nirjhor's answer.
ALTER TABLE categories MODIFY id_father_category INT(11) DEFAULT NULL;
or you can recreate the whole thing:
CREATE TABLE IF NOT EXISTS `categories` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`id_father_category` int(11) DEFAULT NULL,
`name` varchar(64) NOT NULL,
`content` varchar(256) NOT NULL,
PRIMARY KEY (`id`) )
ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
Setting the default value to NULL will handle your issue as well as set the field to NULL. One thing to note here is to make sure you don't have some weird index on that field cause that can also create an issue.