Revision #6 has been created by wei on Oct 25, 2010, 3:01:59 AM with the memo:
formatting, spelling
[...]
Let's view an example. We have two tables: Event and PhotoEvent. When we want to create an Event we want to add some photos to it.
This is the database tables example:
![Alt text](http://i40.tinypic.com/eap9xi.jpg)
How can we add N photos input field in the form d
iyna
lmically?
First of all you have to create your IMG_DIR_PATH directory where to save the images and give it the rights to write inside.[...]
```php
<?php
'image'=>array(
'class'=>'application.extensions.image.CImageComponent',
// GD or ImageMagick
'driver'=>'GD',
// ImageMagick setup path
'params'=>array('directory'=>'/opt/local/bin'),
)
?>
```
)
```
This is how is made the html page to collect the inputs:[...]
[html]
<h2>New Event</h2>
<div class="actionBar">
[<?php echo CHtml::link('Event List',array('list')); ?>]
[<?php echo CHtml::link('Manage Event',array('admin')); ?>]
</div>
<div class="yiiForm">
<p>
Fields with <span class="required">*</span> are required.
</p>
<?php echo CHtml::form('','post',array('enctype'=>'multipart/form-data')); ?>
<?php echo CHtml::errorSummary(array_merge( array($event), $photosEvent)); ?>
<div class="simple">
<?php echo CHtml::activeLabelEx($event,'name'); ?>
<?php echo CHtml::activeTextField($event,'name'); ?>
</div>
<div class="simple">
<?php echo CHtml::activeLabelEx($event,'description'); ?>
<?php echo CHtml::activeTextField($event,'description'); ?>
</div>
<div class="simple">
<?php echo CHtml::activeLabelEx($event,'expireDate'); ?>
<?php echo CHtml::activeTextField($event,'expireDate'); ?>
</div>
<?php echo CHtml::button('add Photos', array('name'=>'addPhotos', 'id'=>'addPhotos')); ?>
<?php foreach($photosEvent as $i => $photo): ?>
<div id="photo-<?php echo $i ?>">
<div class="simple">
<?php echo CHtml::activeLabelEx($photo,'photoUrl'); ?>
<?php echo CHtml::activeFileField($photo, "photoUrl[$i]"); ?>
</div>
<br />
</div>
<?php endforeach; ?>
<div class="row action">
<?php echo CHtml::submitButton($update ? 'Save' : 'Create', array('name'=>'submitDatas')); ?>
</div>
</form>
</div>
<script type="text/javascript">
/*<![CDATA[*/
// I need to know how many photos I've already added when the validate return FALSE
var photosAdded = <?php echo $photosNumber; ?>;
// Add the event to the period's add button
$('#addPhotos').click(function () {
// I'm going to clone the first div containing the Model input couse I don't want to create a new div and add every single structure
var divCloned = $('#photo-0').clone();
// I'm attaching the div to the last input created
$('#photo-'+(photosAdded++)).after(divCloned);
// Changin the div id
divCloned.attr('id', 'photo-'+photosAdded);
// Initializing the div contents
initNewInputs(divCloned.children('.simple'), photosAdded);
});
function initNewInputs( divs, idNumber ) {
// Taking the div labels and resetting them. If you send wrong information,
// Yii will show the errors. If you than clone that div, the css will be cloned too, so we have to reset it
var labels = divs.children('label').get();
for ( var i in labels )
labels[i].setAttribute('class', 'required');
// Taking all inputs and resetting them.
// We have to set value to null, set the class attribute to null and change their id and name with the right id.
var inputs = divs.children('input').get();
for ( var i in inputs ) {
inputs[i].value = "";
inputs[i].setAttribute('class', '');
inputs[i].id = inputs[i].id.replace(/\d+/, idNumber);
inputs[i].name = inputs[i].name.replace(/\d+/, idNumber);
}
}
/*]]>*/
}
</script>
~~~[...]
```php
<?php
public function actionCreate()
{
// Adding jQuery to the view page.
Yii::app()->getClientScript()->registerCoreScript('jquery');
$event = new Event;
// Adding an empty PhotoEvent to the form
$photosEvent = array( new PhotoEvent, );
// If everything is setted I will check and process the inputs
if( isset( $_POST['submitDatas'] ) && isset( $_POST['PhotoEvent'], $_POST['Event'] ) )
{
$event->attributes = $_POST['Event'];
// DB date layout
$event->expireDate = date_format(date_create($event->expireDate), 'Y-m-d');
$valid = $event->validate();
// This is the crappy part of the script that I need to improve and make it more elegance
// I've to add to the photoEvent array a new PhotoEvent for every istance in $_POST['PhotoEvent']
foreach ( $_POST['PhotoEvent'] as $i => $photo ) {
$photosEvent[$i] = new PhotoEvent;
if ( isset( $_POST['PhotoEvent'][$i] ) )
$photosEvent[$i]->photoUrl = CUploadedFile::getInstance($photosEvent[$i], "photoUrl[$i]" );
//$photosEvent[$i]->photoUrl = CUploadedFile::getIstance($photosEvent[$i], "photoUrl[$i]" );
$valid = $valid && $photosEvent[$i]->validate();
}
if( $valid && $event->save(false) ) {
// You will need this if you want to resize and play around images :)
//Yii::import('application.extensions.image.Image');
// Saving each period ( i've to change the date format couse in Italy we use dd/mm/yyyy
foreach ( $photosEvent as $i => $photo ) {
$photo->eventId = $event->id;
// Taking and saving the image in the filesystem in the IMG_DIR_PATH/ directory path.
// In this case IMG_DIR_PATH is in the root of the
// site and you need to give it rights to write the image :)
$photo->photoUrl->saveAs('IMG_DIR_PATH/'.$photo->photoUrl->getName());
/* If you need to resize the image use this path of code
$image = new Image('IMG_DIR_PATH/'.$photo->photoUrl->getName());
$image->resize(200, 200);
$image->save();
*/
$photo->save(false);
}
$this->redirect(array('show','id'=>$event->id));
}
}
$this->render('create', array(
'event' => $event,
'photosEvent' => $photosEvent,
'photosNumber' => isset($_POST['PhotoEvent']) ? count($_POST['PhotoEvent'])-1 : 0, //How many PhotoEvent the user added
'update' => false,
));
}
?>}
```
I wish you will enjoy my guide :) Please gimme some feedback to improve it :)
See ya! Emanuele "StErMi" Ricci.