Extension interacting with database


(system) #1

Hi everybody,

I am new to Yii and want to know how I can create an extension which will interact with the backend database. For example, a simple extension containing Add,Update,Delete functionality which anyone can use in their application.

I am not getting where to put the 3 parts of the MVC pattern which you get after running the CRUD yiic shell command.

Most of the extensions currently available are related to UI. Can anybody help me for this? Thank you. :D


(Sebathi) #2

Just use this:

application.extensions.myextension.models

application.extensions.myextension.views

the controller must extend from CExtController.


(Qiang Xue) #3

What sebas said is correct.

Also, if you do not intend to share your code, you don't need to package them into extensions.


(system) #4

Hi sebas  :D,

Thanks for quick reply. But I have some problem. Here is what I did.

I just ran the yiic CRUD command on simple 'employee' table in database which gave me the model,views and EmployeeController. As you said I placed the model class in 'models' and 5 views in 'views' folder under the extensions/employee (name of extension) folder. I also extend EmployeeController  from CExtController and place it under 'employee' folder.

Now, I want to place this extension in some other view, say MyView.php which is in default 'site' views. For that I wrote one php class which is as follows and I put it in the extension directory 'employee' along with EmployeeController:

<?php

class EmpExtRender extends CWidget

{

public function run()


{


	$class=Yii::import(&#039;application.extensions.employee.models.employee&#039;);


	$identity=new $class();


	


	$this-&gt;renderFile(&#039;D:\xampp\htdocs\testdrive\protected\extensions\employee\views\show.php&#039;,array(&#039;employee&#039;=&gt;$identity));


}

}

?>

Doing all this, I did get the view 'show' to be displayed inside view 'MyView', but when u click on the links for 'Add' or 'Update' operations, it is not been able to find the corresponding view, because it searches for those views under the 'site' controller, while the views are actually present under extensions/employee.

So, if u understand whats the problem, pls let me know. Thanks in advance  ;)


(Notzippy) #5

This has been discussed here http://www.yiiframew…pic,214.15.html and the solution has been implemented in version 1.0.1


(Qiang Xue) #6

The problem is because you are reusing a controller view in a widget. That's not really a good practice.


(system) #7

Hello notzippy,

Can u post  that example ?

Thanks!


(Notzippy) #8

I ken try !

The widget & action (can be in same file)



class HelloWidget extends CWidget {





  /**


   * This could render a view but to keep things simple I just echo the output,


   * note how the URL is formed using the actionPrefix, this is KEY !


   */


  public function run() {


    $nameid = $this->getId();


    echo "<div id="". $nameid ."div"></div>".


          CHtml::ajaxButton("Hello",


                            array($this->actionPrefix."hello"),


                            array('success'=>'function(html){jQuery("#".$nameid."div").html(html)}' ));


  }





  /**


   * Declare the action map for the button


   */


  public static function actions() {


    return array("hello"=>"HelloAction");


  }





}


/**


 * The action handler


 */


class HelloAction extends CAction {


  /**


   * Simply return some script that says hello


   */


  public function run() {


    Yii::app()->clientScript->registerScript("Hello","alert('Hello !')",CClientScript::POS_END);


    echo $this->controller->processOutput("");


    


  }


}


The controller, note the "hey." prefix for the HelloWidget, this is how the controller knows that all action response should be dispatched to that widget. The period is also crucial.



class SiteController extends CController {


  public function actions() {


    return array("hey."=>"HelloWidget");


  }





The controller view, once again the actionPrefix "hey." must be specified



<com:HelloWidget actionPrefix="hey."/>


nz


(Notzippy) #9

A bit of an explanation,

The HelloWidget is created in the SiteController view. It knows the action prefix is "hey.". Using that prefix this widget generates all its controls, in this case an ajax button with a div. The HelloWidget also contains a static method called "actions" this returns a list of actions handled by the widget (yes the static method does not know about the non static action prefix but this is resolved at request time)

So the page is built with a Ajax Button on it saying Hello. Clicking it sends a command back to the SiteController like "r=site/hey.hello" . The SiteController loads the actions() and tries to find a match. Since it cannot find a match for the action "hey.hello" it then takes the first section of the action that ends at the "." anotherwords the "hey." and tries to match that to the actions for the controller. And it finds a match - "HelloWidget". Now it invokes the static method "actions()" on the widget and tries to find a match on the last portion of the action - "hello". A matched action is found : "HelloAction" and the run() function is invoked on it.

This type of matching is recursive so a widget may contain a widget that contains a widget … As long as each of the widgets follow the rule of having the actionPrefix defined as the callback they will function fine.

Hope this helps, note this is relevant to release v 1.0.1

nz


(system) #10

Hello notzippy,

Thanks for ur quick reply and also for explaination.  :D

I will try that one.


(system) #11

Hello notzippy,

     

      I tried as per ur suggestion and it is working fine. But what I want is that when I perform any action (eg. click on the link to another view or perform some add/update/delete operation ) on the widget (which is an extension) , My default view (on which I have placed the extension widget) should not get overwritten.

     

      What is happening right now is that only the resultant view after performing action on the widget is getting rendered. I want my default view should also be there and only the part which is taken by the extension widget should be replaced by resultant view.

     

      I will also attach some files here. My example contains default controller view called 'MyView' which is a simple 'Addition of two numbers' view and it also contains the extension widget called 'employee' which contains normal 'CRUD' operations.

     

      Can u tell me what is the best way to achieve this? Thanks!  :D


(Notzippy) #12

I am not positive which is the best way to implement this. But I have a couple of ideas

  1. The widget updates itself in place using ajax. This can be achieved if all the controls on the widget are ajax based. The implementation is similar to the HelloWidget described above. Probably the simplest to implement.

  2. The widget calls a method on the controller to redraw the "page". The issue is the widget has no information about the controller's current state, so it will have no information to tell the controller what view it needs to draw so the controller will have to make an assumption. Like $controller->run($controller->defaultAction); If you want the controller to simply be a layout of a bunch of widgets then this may work.

For the most part option 1 would be the more used option (I think). Those ideas are just off the top of my head…

nz


(Megabr) #13

why not use in the YII module way…?

[after this use Yii::import]


(Tjhaichristian) #14

Hi, I am interested in this, and have been looking for the examples to use CExtController but can’t find any. Please kindly give me an example of the CExtController.

And how do you access the controller url then ?

Thanks!


(Tjhaichristian) #15

Hi notzippy,

Where can I found reference about this: <com:HelloWidget actionPrefix="." /> ? And what do you call this ?

Thank you!