Widget use Error

Hi,

I’m trying to make my first widget and when I go to use it on a page I get a php error stating:

Fatal error: Cannot redeclare class <classname> in <filepath> on <line #>

The long story:

The name of my widget is JuiDraggableMultiSelect (which isn’t a very good name but I’ll rename it later).

I created my widget originally in the extensions folder but I was having trouble referencing it. I kept getting a CHttpException saying:

include(JuiDraggableMultiSelect.php) [<a href=‘function.include’>function.include</a>]: failed to open stream: No such file or directory

When I tried to include it using <?php $this->widget(‘ext.draggableMultiSelect.JuiDraggableMultiSelect’,array()); ?>. When I changed the path slightly I got an error saying the alias for the path was incorrect.

So then I was reading over a few posts and tutorials and they said to put developer created widgets into the components folder because its already included and it would be easier to reference. So I did that, but I had to put it at the root of the components folder because I couldn’t reference it inside a folder for some reason. After I did that and changed my reference path, I started getting the Fatal error that I stated earlier.

What are the best practices and what is the proper way to do this? I thought that widgets were supposed to go in the extensions folder but if so, why am I having such trouble referencing it? If not why am I getting the “Fatal error: Cannot redeclare class” error? I’m not intentionally redeclaring it if that is what is actually happening.

Thanks,

-Nazum

  1. The components autoloaded on startup is because of these lines in config/main.php



	// autoloading model and component classes

	'import'=>array(

		'application.models.*',

		'application.components.*',

	),




You can add other folders here to register your component/widgets …

But it’s not a good idea to include a widget/component on every request when it’s not needed.

So your code in a view when using




 $this->widget('ext.draggableMultiSelect.JuiDraggableMultiSelect');



is ok.

  1. Note:

In most cases you don’t use ‘include’ in Yii, you use Yii::import.

You never include components like ‘include(JuiDraggableMultiSelect.php)’

For example in a controller class file or a view file, when your components/widgets are stored in the folder

ext.myExtension.components




 Yii::import('ext.myExtension.components.*');


 $c1 = new myComp1;


 $c2 = new myComp2;




  1. The error “Cannot redeclare class” is maybe a bug in your implementation or you forgot to remove your widget class from the components folder and it’s included on startup…

The error message should tell where you have included the class first.

This is exactly what I have and its not working. I get the error below when using this configuration.

But I’m not explicitly including the file. I’m not using Yii::import() either but if I add it, I get the same error.

Any Ideas?

Thanks,

-Nazum

Could this possibly be a permissions issue for apache? I have another widget in the extensions folder that I downloaded and it works just fine. My file structure looks like this:

1905

Screen Shot 2011-07-29 at 11.43.47 AM.png

I checked the permissions on the directory and it is exactly the same as the permissions on the other widget that I’m using. I’m calling both widgets exactly the same way as well. This just doesn’t make sense.

This is the code for my widget. Which again is in "/protected/extensions/draggableMultiSelect/"





class draggableMultiSelect extends CWidget

{

    //widget public properties

    public $alternativeCss;

    

    public $name = 'draggableMultiSelect';

    

    public $list;

    

    

    //default script and Css files

    private static $scriptFile='draggableMultiSelect.js';

    private static $defaultCssFile='defaultDraggableMultiSelect.css';

    

    

    public function init()

    {

        parent::init();

        

        if (!isset($this->list))

        {

            throw new CHttpException(503, "A source list and a target list is required for the '$this->name' draggableMultiSelect widget.");

        }

        $this->registerScripts();

    }

    

    public function run()

    {

        parent::run();

        

        $this->generateHtml();

    }


    public function registerScripts()

    {

        //make the asset path availiable.

        $path = pathinfo(__FILE__);

        $basePath = $path['dirname'].DIRECTORY_SEPARATOR.'assets';		

        $baseUrl=Yii::app()->getAssetManager()->publish($basePath);

        

        //register the needed scripts and default css files

        $cs=Yii::app()->getClientScript();

        $cs->registerCoreScript('jquery');

        $cs->registerScriptFile($baseUrl.DIRECTORY_SEPARATOR.$this->scriptFile, CClientScript::POS_HEAD);

        $cs->registerCssFile($baseUrl.DIRECTORY_SEPARATOR.$this->defaultCssFile);

        

        return;

    }

    

    public function generateHtml()

    {

        if(!isset($this->list) && empty($this->list))

        {

            throw new CHttpException(504,"A list is required for the '$this->name' draggableMultiSelect object.");

        }

        if(is_array($this->list))

        {

            // Iterate through the target list if the target list is an array of lists 

            // and create a new target list object for each one.

            foreach($this->list as $tList)

            {

                $tList->generateHtml();

            }

        }

        else

        {

            $this->list->generateHtml();

        }

        

        return;

    }   

}



And this is my code in my view to use it:




<?php  

            $this->widget('ext.draggableMultiSelect.JuiDraggableMultiSelect',array(

                'list'=>array('1', '2', '3'),

                'name'=>'test',

            ));  ?>



And this is the error that I’m getting:

Am I missing something?

Any and all help is appreciated.

Thanks,

-Nazum

Is your widget’s class name “draggableMultiSelect” or “JuiDraggableMultiSelect”?

It might be just an inconsistency between the class name and the file name that gives you a "No such file or directory" error.

Conventions - 5 File

Wow, good call. That worked, thanks. Always seem to tear my hair out over the simple things.

-Nazum