keeping layouts in database instead of files

Hi,

I need to keep layouts in database to keep revisions of them.

Like layouts i also want to keep css and javascript files in db, like modx does.

I guess extending CController::getLayoutFile() will be enough for layouts but i dont know what to do for css and js files…

Having read about “CSS or JS files as MODx documents” at the modx site, it seems to me like you actually want to store the CSS/JS content in DB, not only the file name. You can tell I’m not a CMS guy. :)

I think it might be possible to extend CAssetManager and override publish(). In case of a new version in DB, dump to a file for publishing. Just a thought.

Edit:

On a second thought a separate DB extraction class would be more appropriate. Then the generated file can be published like any other file. Or maybe it’s viable to generate inline content? (CClientScript, registerCss/registerScript)

/Tommy

You might want to look into stream wrappers:

http://us3.php.net/manual/en/book.stream.php

Stream wrappers allow you to get content from any source, for example a database, using file-syntax - for example, file_get_contents(“http://www.google.com”) is possible in PHP, thanks to the built-in “http” stream wrapper. Implementing your own “layout” stream wrapper, for example, you could use a path like “layout://standard-page”, and your stream wrapper could perform something like “SELECT content FROM layouts WHERE id = ‘standard-page’” and return the content from the database. To most file-related functions in PHP, this would work like any other file.

They are not hard to implement, and presumably would be compatible with existing framework components - so rather than extending every class that needs to use content stored in a database rather than from a file, you can simply implement a stream wrapper for your database.

There is probably a performance concern, but there is already a performance concern in terms of having to access the database for everything. And besides CPU/memory performance, there is always productivity (programmer performance) to consider - you might be able to kill a lot of birds with one stone here.

Just a thought :slight_smile:

yes, i want to store the contents in db, not file names.

since getting layouts from db took longer than i thought, i coudnt work on getting css and js files from db yet. but i ll try to get them by extending CClientScript first, thank you for the idea Tommy…

thank you mindplay, i ve never used before stream wrappers, they really looks like life saver. i ll check them asap.

but for now i ve managed to get layouts from db by extending controller.




class _Controller extends CController

{   

	public function render($view,$data=null,$return=false)

	{

		$output=$this->renderPartial($view,$data,true);

		$layoutContent = $this->renderLayout($this->layout);

		$output=$this->renderInternalContent($layoutContent,array('content'=>$output));

		$output=$this->processOutput($output);


		if($return)

			return $output;

		else

			echo $output;

	}

	

	public function renderLayout($layout) 

	{

		if (empty($layout)) { $layout = Yii::app()->layout; } 

		

		$content=Resource::model()->find(array(

		    'select'=>'body',

		    'condition'=>'type=1 AND name=:layoutName',

		    'params'=>array(':layoutName'=>$layout)

		));

		

		return $content->body;

	}

	

	public function renderInternalContent($_content_,$_data_=null)

	{

		// we use special variable names here to avoid conflict when extracting data

		if(is_array($_data_)) {

			extract($_data_,EXTR_PREFIX_SAME,'data');

		}

		else {

			$data=$_data_;

		}


		ob_start();

		ob_implicit_flush(false);

		

		// since i ve just copied and pasted from layout php file, i ll have to do some clean up

		$code=str_replace('<'.'?php','<'.'?',$_content_);

		$code='?'.'>'.trim($code).'<'.'?';

		eval($code);


		return ob_get_clean();

	}

	

	

	

} 

probably this is not the best solution. but so far, this looks like working.

Be aware that eval()'ing every template could impact the performance of your server, as this function bypasses any bytecode cache your server might be running.