Jump to content
Larry Ullman's Book Forums
Sign in to follow this  
Ziggi

Dynamic Active Record Working !

Recommended Posts

Hi,

 

The previous script has some problem with scenarios. This is a new one what is working fine and its functionality is IMHO critical but for whatever reason is missing in Yii native code:

 

Example usage:

 

Presume you have a table of addvertising mailing campaigns. Each record is a separate mailing campaing: it has a unique id, unique name, unique e-mail body, it is associated with given customer, it is owned by a specific employee etc. And finally it must be associated with a specific distribution list. And each distribution list is in fact a separate database table where each record contains a specific e-mail address, addressee name, etc.

 

So the problem is - how to create a Yii model for distribution lists? Normally one have to provide a table name while creating a model class. But here we will most probably create a new list with each and every new campaign! So - what is the solution? The solution is a dynamic active record based on code submited by Pavle Predic:


<?php

/**
* This is the model class for table "lista_x".
*
* The followings are the available columns in table 'lista_x':
* @property integer $id
* @property string $email
*/
/**
* CActiveRecord implementation that allows specifying
* DB table name instead of creating a class for each table.
*
* Usage (assuming table 'lista_x' with columns 'id' and 'email'):
*
* $model = Lista::forTable('lista_x');
* //list existing records
* foreach ($model->findAll() as $entry)
* echo $entry->id . ': ' . $entry->email . '<br />';
* //add new entry
* $model->email = 'john.doe@anonymus.com';
* $model->save();
*/

class Lista extends CActiveRecord
{
/**
 * Name of the DB table
 * @var string
 */
protected $_tableName;

/**
 * Table meta-data.
 * Must redeclare, as parent::_md is private
 * @var CActiveRecordMetaData
 */
protected $_md;

/**
 * Constructor
 * @param string $scenario (defaults to 'insert')
 * @param string $tableName
 */
public function __construct($scenario = 'insert', $tableName = null)
{
 $this->_tableName = $tableName;
 parent::__construct($scenario);
}

/**
 * Overrides default instantiation logic.
 * Instantiates AR class by providing table name
 * @see CActiveRecord::instantiate()
 * @return DynamicActiveRecord
 */
protected function instantiate($attributes)
{
 return new Lista(null, $this->tableName());
}

/**
 * Returns meta-data for this DB table
 * @see CActiveRecord::getMetaData()
 * @return CActiveRecordMetaData
 */
public function getMetaData()
{
 if ($this->_md !== null)
	 return $this->_md;
 else
	 return $this->_md = new CActiveRecordMetaData($this);
}

public function tableName()
{
 if (!$this->_tableName)
	 $this->_tableName = parent::tableName();
 return $this->_tableName;
}

/**
 * Returns an instance of Lista for the provided DB table.
 * This is a helper method that may be used instead of constructor.
 */
public static function forTable($tableName, $scenario = 'insert')
{
 return new Lista($scenario, $tableName);
}

// rest of model class code

public function rules()
{
return array(
array('email', 'required'),
array('id, email', 'safe', 'on'=>'search'),
);
}


public function relations()
{
return array(
 'campaigns' => array(self::HAS_MANY, 'Campaigns', 'list_id'),
);
}


public function attributeLabels()
{
return array(
'id' => 'ID',
'email' => 'Email',
);
}


public function search()
{

$criteria=new CDbCriteria;

$criteria->compare('id', $this->id);
$criteria->compare('email', $this->email, true);

return new CActiveDataProvider($this, array(
'criteria'=>$criteria,
));
}
}

 

As this functionality is so fundamental I feel really surprised it is missing in the generic framework code!

Share this post


Link to post
Share on other sites

Sure this can't be fixed by database normalization instead? I don't understand why a separate table is needed for every campaign. I might be missing something crucial here, but generally I would suggest you to take another look at your database structure. While this may be working fine now, how about half a year from now? The reason why this do not exist is because such problems are usually solved by well known normalization rules.

  • Upvote 1

Share this post


Link to post
Share on other sites

When I done some of my initial database planning I thought to myself a new table would need to be created for each of these situations but later I realized I was wrong. Most of the relational database problems can be fixed by a single table or two tables which means the other being intermediary. You sound to me that you are correct also Antonio unless I am missing something.

Share this post


Link to post
Share on other sites

You misunderstood - one table for all campaigns but each distribution list (or e-mail address list, as you like) is a separate table!

 

Or be so kind and provide me an alternative solution to manage distribution lists efficiently!

Share this post


Link to post
Share on other sites

Jesus - Edward - can you get focused for a moment, please?

 

If you send an e-mail during add campaign you do not send it to a single addressee but to thousands of them!

So you keep all these e-mail addressess in distribution lists - in tables full of e-mail addresses!

 

And most probably you need a distribution list A for campaing X and another distribution list B for campaign Y as these are completely different customer targets! For instance list A is a list of elderly people who are looking for appropriate health programm while list B is a list of young professionals who may be interested in exclusive active holiday trip offer.

 

And you need to be able to manage all these distribution lists in an easy manner - browse all addresses in a list, add them, remove them etc. But there may be dozens of individual distribution lists while each and every list is generally very same in its structure what is a common denominator.

 

Consequently - rather than handling each list with a separate model it is more clever to have one model fit to this common structure and swap between database tables behind.

 

Another solution is to keep all e-mail addresses in one huge table and keep their relation to particular campaign in an additional column but this is a risky business. Lists are imported from Excel files provided by customer - if something goes wrong during import there is a risk of table gets corrupted rendering all e-mails of all campaigns unaccessible. This is the reason why I believe keeping various distribution lists in separated tables is a less vulnerable approach.

 

Can you cope now?

Share this post


Link to post
Share on other sites

Ziggi, you really, really, really need to watch how you talk to other people in these forums. You have been told this by others many times before, and now I'm telling you. This is not how you behave when you're asking for free help from strangers. If you cannot interact with an appropriate level of decency and respect, you cannot use these forums. I don't know if this is a language issue, or a cultural one, or just a personality matter, but it's completely unacceptable.

  • Upvote 2

Share this post


Link to post
Share on other sites

????

What is so wrong, Larry??? - Sorry - this is a completely mistery for me this time!!!

 

Actually - you should notice that this time I was not asking for any help!

I rather tried to DONATE a code.

 

I actually SUPPORTED this forum with a very useful trick I stumbled upon once upon a time - but the trick was misunderstood by Edward.

 

So, indeed this might be a language issue what I am unaware of - but - is it Palace de Versaille or is it The Yii Book forum for internationals who may be not so skillful in English language used by diplomatic council ???

 

Please, Larry - enlighten me as a native speaker where the particular offence is present:

 

Here: "Jesus - Edward - can you get focused for a moment, please?"

or rather here: "Can you cope now?"

 

I am asking seriously as I really do not know!

I rapidly browse the dictionary and neither word is listed as rude or inappropriate...

 

Or is it unnaceptable to show "advanced user" he missed the point completely???

Because he missed it - sorry - not my fault!

 

And really - you should already notice - I am not so eager to ask for help in terms of "gimme code, please" any more. I am myself advanced enough to ask for ideas rather than code. If you look closer, you will notice I am CONTRIBUTING code for this forum and I am supporing you with findings what are not that obvious I hope. Consequently, I would appreciate Edward reading my messages with more focus - then there would be no need to ask me (after my second attempt to explain the issue in a comprehensive manner) this way, what I consider rather nasty and patronising:

 

"I am not following you distribution lists of what exactly?"

Share this post


Link to post
Share on other sites
What is so wrong, Larry??? - Sorry - this is a completely mistery for me this time!!!

 

The fact that you're able to pinpoint exact things that are inappropriate make me suspicious of your assertion that this is a complete mystery.

 

Actually - you should notice that this time I was not asking for any help!

I rather tried to DONATE a code.

 

I think it's great that you're trying to give back. But you can't act like a jerk whether you're asking for help or trying to be helpful.

 

So, indeed this might be a language issue what I am unaware of - but - is it Palace de Versaille or is it The Yii Book forum for internationals who may be not so skillful in English language used by diplomatic council ???

 

See: right there. Totally unnecessary. Why do you have to ask questions in such way? No, it's not the palace of Versailles. It's MY FORUM. And I expect civility and common courtesy. If you have problems with someone's response and aren't capable of being polite, then don't respond at all.

 

As it's MY FORUM, I reserve the right to kick out people who are impolite, rather than run the risk of having those people drive away nice, helpful people.

 

Please, Larry - enlighten me as a native speaker where the particular offence is present:

 

Here: "Jesus - Edward - can you get focused for a moment, please?"

or rather here: "Can you cope now?"

 

Ding, ding, ding. We have a winner!

 

I rapidly browse the dictionary and neither word is listed as rude or inappropriate...

 

Those phrases and tones are rude and inappropriate.

 

Or is it unnaceptable to show "advanced user" he missed the point completely???

Because he missed it - sorry - not my fault!

 

If that is the case, and I'm not saying it is, there's still a way of handling it with more decency.

 

And really - you should already notice - I am not so eager to ask for help in terms of "gimme code, please" any more. I am myself advanced enough to ask for ideas rather than code. If you look closer, you will notice I am CONTRIBUTING code for this forum and I am supporing you with findings what are not that obvious I hope.

 

Doesn't matter. And besides, that's this thread. You were dismissive of Antonio when he was trying to help you out just last week in another thread. I almost said something then.

 

what I consider rather nasty and patronising: "I am not following you distribution lists of what exactly?"

 

I don't take that to be nasty and patronizing at all. I saw Edward trying to understand your situation and you responded inappropriately and impolitely.

 

And, you're being snide in this response.

  • Upvote 2

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
Sign in to follow this  

×
×
  • Create New...