Saving File From Parent Model

Hi there,

I’ve an unusual situation.

My parent model (Booking) has a related model (Bookingdocument) to manage received/sent documents. For received documents, my child model has an upload form and this works fine. Documents to be sent out are created and phisically saved by my parent model as pdf files. I need to save a Bookingdocument model for each of these pdf files as they are created and here I’m stuck.

My Booking model code looks like this:




$fName = $this->pdfCreateDocument($rDoc->documenttype->template, $rDoc->documenttype->filename, $this->getBookingFolder());

if ($this->pdfSendDocument($fName, $rDoc->documenttype->template))

{

	$newBDoc = new Bookingdocument;

	$newBDoc->booking_id = $this->id;

	$newBDoc->bookingpax_id = 0;

	$newBDoc->offertypedocument_id = $rDoc->documenttype_id;

	$newBDoc->docdate = date('Y-m-d H:i:s');

	$newBDoc->document_filename = $fName;

								

	$docFile = CUploadedFile::getInstance($newBDoc,'document_filename');

	if (is_object($docFile) && get_class($docFile)==='CUploadedFile')

					$newBDoc->document_filename = $docFile;

				

	$bookFolder = $this->getBookingFolder();

	if (is_object($newBDoc->document_filename))

	 				$newBDoc->document_filename->saveAs($bookFolder.DIRECTORY_SEPARATOR.$newBDoc->document_filename->name);

								

	var_dump('Saving object type '.get_class($docFile));

	$tmpResult = $newBDoc->save();

	if($tmpResult)

		var_dump('Saved');

}



I’ve copied lines from my BookingdocumentController here but this is obviously wrong: I’m not uploading any file, I’m using a file that has been already created, saved (by pdfCreateDocument) and sent (by pdfSendDocument).

I shouldn’t get an instance of an uploaded file, because my file is already existing.

And I shouldn’t save file, right?

Moreover, get_class($docFile) above returns class ‘Booking’, not what I thought.

But I have no idea how to face this issue.

Anyone pointing me to the right direction?

TIA,

rash*

If you already saved the file then why do you need the CUploadedFile here?

The only purpose of the CUploadedFile is to handle $_FILES superglobal and it can return information about uploaded files (like size and name) and re-save them from the temp folder to the folder you specify.

So if you already saved the file to some non-temp location then you do not need CUploadedFile.

Wouldn’t it work if you just delete the part of code related to CUploadedFile:




$fName = $this->pdfCreateDocument($rDoc->documenttype->template, $rDoc->documenttype->filename, $this->getBookingFolder());

if ($this->pdfSendDocument($fName, $rDoc->documenttype->template))

{

	$newBDoc = new Bookingdocument;

	$newBDoc->booking_id = $this->id;

	$newBDoc->bookingpax_id = 0;

	$newBDoc->offertypedocument_id = $rDoc->documenttype_id;

	$newBDoc->docdate = date('Y-m-d H:i:s');

	$newBDoc->document_filename = $fName;

								

	$tmpResult = $newBDoc->save();

	if($tmpResult)

		var_dump('Saved');

}



Yep, I understand why I do not need to play with CUploadedFile. I’ve already tried what you suggest but it doesn’t work, i.e. saving $newBDoc always returns false.

rash*

You need to check why it is not saved using $newBDoc->getErrors():




    $tmpResult = $newBDoc->save();

    if($tmpResult) {

         var_dump('Saved');

    } else {

         var_dump($newBDoc->getErrors());

    }



It is possible that you have a file validator for "document_filename" and it can be used only with CUploadedFile.

If this is right than you need to use different scenarios to save with uploaded file and to save with manual file, see examples in definitive guide.

Uh, thanks a lot Seb.

I’ll dig into your suggestions.

Thanks a ton!

rash*

Hi again,

yes, I do have a file validator. And the error I receive (by getErrors()) is "Document Filename cannot be blank".

From the Model documentation you linked, I understand I need to set a scenario and relax validation for my file field.

So I’ve changed my model’s validation rules to this


array('document_filename', 'file', 'allowEmpty'=>false, 'except'=>'autoLoad'), ...

where i named ‘autoLoad’ my new scenario. I’ve also taken off document_filename from the list of required parameters, like this:


array('booking_id, offertypedocument_id', 'required'),

array('document_filename', 'required', 'except'=>'autoLoad'), ...



When creating a new model, I thus use


$newBDoc = new Bookingdocument('autoLoad');

but when it gets to save my model, I still receive the same error…

For completness, code from my model is this:


...

$fName = $this->pdfCreateDocument($rDoc->documenttype->template, $rDoc->documenttype->filename, $this->getBookingFolder());

if ($this->pdfSendDocument($fName, $rDoc->documenttype->template))

  {

	$newBDoc = new Bookingdocument('autoLoad');

	$newBDoc->booking_id = $this->id;

	$newBDoc->bookingpax_id = 0;

	$newBDoc->offertypedocument_id = $rDoc->documenttype_id;

	$newBDoc->docdate = date('Y-m-d H:i:s');

	$newBDoc->document_filename = $fName;

								

	var_dump('Saving document '.$fName.' in scenario '.$newBDoc->getScenario());

	$tmpResult = $newBDoc->save();

	if($tmpResult)

	{

		var_dump('Saved');

	}

	else

	{

	    var_dump($newBDoc->getErrors());

	}

}

...

and code for my related model’s rules() function is this:


public function rules() {

	return array(

		array('booking_id, offertypedocument_id', 'required'),

		array('document_filename', 'required', 'except'=>'autoLoad'),

		array('booking_id, bookingpax_id, offertypedocument_id', 'numerical', 'integerOnly'=>true),

		array('document_filename', 'file', 'types'=>'doc, docx, pdf, ods, tif, jpg, png, gif'),

		array('document_filename', 'file', 'allowEmpty'=>false, 'except'=>'autoLoad'),

		array('bookingpax_id', 'default', 'setOnEmpty' => true, 'value' => null),

		array('id, booking_id, bookingpax_id, offertypedocument_id, document_filename, docdate', 'safe', 'on'=>'search'),

	);

}



Call to var_dump tells me that I’m in scenario ‘autoLoad’ and filename is my just saved file.

What am I missing?

rash*

Everything looks OK except the rules() method - you have file validator two times:




    array('document_filename', 'file', 'types'=>'doc, docx, pdf, ods, tif, jpg, png, gif'),

    array('document_filename', 'file', 'allowEmpty'=>false, 'except'=>'autoLoad'),               



Also I think that ‘required’ validator does not need to be excluded - the ‘document_filename’ is not empty in both cases.

Yep, thanks, I’ve excluded ‘required’ validator after first try was not working, I understand it’s unneeded.

What about the two ‘file’ validators? How should I keep type validation while excluding ‘allowEmpty’?

Edit: mmmh…silly me… I do not need type validation while in my own scenario… right? But, why do I get ‘cannot be blank’ error then…?

rash*

And, yesssss, it works now (excluding both file validators).

Thanks a lot Seb for your help.

rash*