Is it possible that i can pass some variable to the model in table name?
I have a module that creates Customers.
Now for each Customers we create a separate table.
The Customers has a login and logout credentials.
Now for whenever a customer is created i can't always create a new model and pass it name there.
So i want that it gets dynamically, I am not sure how i can do it.
For each customer there will be one separate table.
Now i want to create a model for login, but what should i pass in the table name,it should be dynamic right?
What should be the mysql schema to get this done?
This my sample Model code:
class Customer_User_M extends MY_Model
{
protected $_table_name = 'customer1';
protected $_order_by = 'name';
public function __construct()
{
parent::__construct()
}
}
The Customer Table:
CREATE TABLE IF NOT EXISTS `customer1` (
`id` int(10) NOT NULL AUTO_INCREMENT,
`site_key` varchar(50) NOT NULL,
`display_name` varchar(100) NOT NULL,
`ext` varchar(15) NOT NULL,
`auth_user` varchar(100) NOT NULL,
`password` varchar(128) NOT NULL,
`base_ini_id` varchar(50) NOT NULL,
`comments` varchar(200) NOT NULL,
`custom_ini_filename` varchar(50) NOT NULL,
`email` varchar(50) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=4 ;
You can simply make a function in the model and put the code of create table in the function and pass dynamic table name in the function from controller like below....
Model function code:
function access_customer_table($table_name)
{
//put ur select query here with table name in FROM clause will be $table_name
}
and call this model function in your controller after load the model... and put your table name as argument...
like :
$this->load->model('Customer_User_M');
$this->Customer_User_M->access_customer_table('new_customer_table_name');
Please correct syntax if needed.. let me know if anything wrong in the logic...
I tried to set the table name after loading the model. Just worked for me.
$this->load->model('customer_model','customer');
then,
$customer->table_name = "customer_xxx";
It is better to save common customer details in a customer table and create another tables to store different data of customers with different fields having foreign key customerid.
Here, if you want to pass dynamic tablename to model then you need to predefine all table names as an associative array with key-value pair.Then you can pass desired key-value to model.It can be implemented using a library.So that you can use it all your controllers.
Related
Hi I have these two tables that I want to join using relations in Yii, The problem is Im having a hard time figuring out how Yii relation works.
picturepost
id
title
link_stat_id
linkstat
id
link
post_count
I also have a working SQL query. This is the query I want my relation to result when I search when I want to get picturepost
SELECT picturepost.id, picturepost.title,linkstat.post_count
FROM picturepost
RIGHT JOIN linkstat
ON picturepost.link_stat_id=linkstat.link;
I want something like this when I search for a post.
$post = PicturePost::model() -> findByPk($id);
echo $post->linkCount;
Here's my table for extra info:
CREATE TABLE IF NOT EXISTS `picturepost` (
`id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`title` text COLLATE utf8_unicode_ci DEFAULT NULL,
`link_stat_id` char(64) COLLATE utf8_unicode_ci NOT NULL
) ENGINE=MyISAM;
CREATE TABLE IF NOT EXISTS `linkstat` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`link` char(64) COLLATE utf8_unicode_ci NOT NULL,
`post_count` int(11) DEFAULT '0',
PRIMARY KEY (`id`),
KEY `post_count` (`post_count`),
KEY `link_stat_id` (`link`)
) ENGINE=InnoDB;
Thanks in advance I hope I explained it clearly.
There are a few tutorial regarding this, and I won't repeat them, but urge you to check them out.
The easiest starting point will be to create your foreign key constraints in the database, then use the Gii tool to generate the code for the model, in this case for the table picturepost.
This should result in a class Picturepost with a method relations(),
class Picturepost extends {
public function relations()
{
return array(
'picturepost_linkstats' => array(self::HAS_MANY,
'linkstat', 'link_stat_id'),
);
}
This links the 2 tables using the *link_stat_id* field as the foreign key (to the primary key of the linked table).
When you are querying the table picturepost, you can automatically pull in the linkstat records.
// Get the picturepost entry
$picturepost = PicturePost::model()->findByPk(1);
// picturepost_linkstats is the relationship name
$linkstats_records = $picturepost->picturepost_linkstats;
public function relations()
{
return array(
'linkstat' => array(self::HAS_ONE, 'Linkstat', array('link_stat_id'=>'link')),
);
}
More on yii relations.
This assumes that you have an active record model Linkstat that represents data in table linkstat.
I have following table
create table `groupusers`(
`id` int not null auto_increment,
`user` varchar(100) not null,
`group` varchar(100) not null,
UNIQUE KEY(`id`),
PRIMARY KEY(`user`, `group`)
)
My model looks like this,
class Model_Groupuser extends ORM{
protected $_table_name = 'groupusers';
public function rules(){
return array(
'user' => array(
array('not_empty'),
array(array($this, 'user_group_not_exists')),
),
'group' => array(
array('not_empty'),
array(array($this, 'user_group_not_exists')),
)
);
}
public function user_group_not_exists($param){
// Need to get other field's value here.
}
}
Problem is every time user_group_not_exists is called, its called with a single parameter. Either user or group. But I need both to determine if the combination exists in the db already.
How can I get current model's fields' value?
You can get other fields value using $this->object() function.
public function user_group_not_exists($user_or_group){
$obj = $this->object();
$group = $obj['group'];
$user = $obj['user'];
// Check if ($group, $user) pair exists in db here
}
You have not really named your table columns comfortable. Naming them user and group and the relations also user and group creates ambiguity between the two.
As kohana does this great thing where you can access table fields, relationships etc. as if it's an objects property. $i_am_lazy = $object-><field,relation,whatever>. Now you named your fields and relations such that it is not clear what you are trying to get.
The only way you can access these id's now is like the following (or the hard way through $this->object() as stated in the other answer, both don't feel good anyway):
$user = $this->user->id;
$group = $this->group->id;
Though, I recommend just renaming the table columns.
create table `groupusers`(
`id` int not null auto_increment,
`user_id` varchar(100) not null,
`group_id` varchar(100) not null,
UNIQUE KEY(`id`),
PRIMARY KEY(`user`, `group`)
)
That way you can simply use $this->user_id or $this->group_id.
How can I delete records in yiiframework when users logged-out in Whosloggedin model by column username?
table - whosloggedin
CREATE TABLE `erc_whosloggedin` (
`id` int(11) DEFAULT NULL,
`username` varchar(50) DEFAULT NULL,
`complete_name` varchar(95) DEFAULT NULL,
`date` date DEFAULT NULL,
`time` time DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8
I Have tried something like this
$whosloggedin=Whosloggedin::model()->find($users->username);
$whosloggedin->delete();
Parameters passed to find function is wrong.
In Find function we have to pass $condition & $params parameters, by default $condition is an empty & $params is an empty array.
find($condition='',$params=array())
You solution would be:
$whosloggedin=Whosloggedin::model()->find('username=:username',array(':username'=>$users->username) );
$whosloggedin->delete();
check out beforeLogout() and afterLogout() methods of the CWebUser class.
You can override them and do your work there.
Not sure about afterLogout() but surely in beforeLogout() there should still be a reference to the username.
http://www.yiiframework.com/doc/api/1.1/CWebUser#afterLogout-detail
Also (and on a sidenote):
you would probably also want to query the user table for users that haven't logged out but whos session timed out.
About finding the user:
use findByAttributes() for a single or findAllByAttributes() for more than 1 row.
$user = Whosloggedin::model()->findByAttributes(array(
'username' => Yii->app()->user->name,
));
Seems like this should be the easy part, but I can't seem to get this going. My created and updated fields are not being populated. I've tried renaming the fields to something different, but no go. Other than the schema and setting up the class (very basic) as below, am I missing something?
Codeigniter v2.1.2
Datamapper ORM v1.8.2.1
Schema:
CREATE TABLE `users` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`username` varchar(255) NOT NULL,
`password` varchar(255) NOT NULL,
`created` datetime NOT NULL,
`updated` datetime NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `username` (`username`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=latin1
User Class:
<?php
class User extends DataMapper
{
function User()
{
parent::DataMapper();
}
}
Ok, found the answer and hopefully this will help someone out. I needed to set the following in the application/config/datamapper.php file:
$config['local_time'] = TRUE;
$config['unix_timestamp'] = FALSE;
$config['timestamp_format'] = 'Y-m-d H:i:s';
In your config/datamapper.php file ensure 'created_field' and 'updated_field' are set to match your DB columns. Or you can override them in the model itself. ie.
<?php
class User extends DataMapper
{
var $created_field = 'created';
var $updated_field = 'updated';
function User()
{
parent::DataMapper();
}
}
When programming OO in PHP i never know exactly how to map a class to simple lists of data. I will try to make a simple example wich i am running into every day:
First the MySQL table creates:
/* create product table */
CREATE TABLE `product` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
`description` text COLLATE utf8_unicode_ci,
`price` decimal(10,0) NOT NULL,
`brand` int(11) NOT NULL,
`deliverytime` int(11) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
/* data list for all kind of brands */
CREATE TABLE `brand` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`brand` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
/* brand data*/
insert into `brand`(`id`,`brand`) values (1,'nike'),(2,'adidas'),(3,'diesel'), (4,'dkny'),(5,'lacoste');
/* data list for deliverytime */
CREATE TABLE `deliverytime` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`deliverytime` varchar(100) COLLATE utf8_unicode_ci NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
/* deliverytime data */
insert into `deliverytime`(`id`,`deliverytime`) values (1,'1 day'),(2,'2 days'),(3,'3 days'),(4,'4 days'),(5,'5 days'),(6,'6 days'),(7,'1 week'),(8,'1 - 2 weeks'),(9,'2 - 3 weeks'),(10,'4 - 5 weeks');
Then i create the product class.
class Product{
private
$name,
$description,
$price,
$brand
$deliverytime;
public function __construct(){
// etc etc
}
public function save(){
// save the product
}
}
Now the big question(s) are:
How should i handle $brand and $deliverytime in my Product class?
Should i make a Brand and DeliveryTime object (wich in turn are responsible for fetching the right brand and or deliverytime data)?
And what about saving the Product object?
How should i handle the brand and deliverytime data?
What is the beste practice or pattern to handle this kind of situations?
Sorry for this noobish question but i wasnt sure where to look for (tags to search for) :/
EDIT:
Ok lets say i dont want to use somekind of ORM framework (Doctrine, dORM, redbean etc) since it would be a gigantic overkill for my little system + i am realy want to know how to create the mapping myself for learning purposes... any suggestions?
This is a style I like to use
class ProductModel {
public function find($id) {
// fetch product with your database code using parameters to filter
$product = new ProductEntity(
// initialize with non foreighn values (eg. $row->id, $row->name)
new ProductBrandEntity($row->brand_id, $row->brand_name); // available because you joined brand??
new ProductDeliveryTime(/* initialize */)
);
return $product;
}
}
I like to call the object from the database Entities but you can call them whatever you want.. It's basically what you suggested in your question but i prefer to have a Model (from MVC) to initialize the entities and not the entities initializing themselves. You should do some research on ORMs and ActiveRecord because this work has basically already been done for you!