add new item to CHtml in yii - yii

I work Yii with doctrine 2. I have a problem, datetime in doctrine 2 is an object of DateTime class, and I can't update it with regular methods of CHtml or form.
How can I add new item in CHtml that can handle this situation.
--Best Regards
Moe Far

You can extend the CHtml class and add your own functions. The code should look something like this:
class MyHtml extends CHtml {
// add you own logic or override CHtml functions
public static function myFunction() {
return 'yeah!';
}
}
You can then use MyHtml::myFunction() and also use all the standard CHtml functions.
Take a look at this question for more info on extending classes in Yii: How to extend Yii framework classes and where to place the files

Related

How to define constructor ?Where?

How to define constructor in Yii application?
Where ?to define the constructors?
I need to create constructors. Where it defines inside model or controller.
Can you guys give some example of formats ?
In a lot of Yii classes there are 2 methods that can be used to define initialization code : __construct() and init():
__construct() is a native php method to instantiate the object.
init() is called when Yii has performed it's own instantiation of the class (for example in a CActiveRecord class Yii has set the scenario name)
it's up to you to use
public function __construct()
{
//Your code
return parent::contruct()
}
or just to use the init method
public function init()
{
//Your code
}
if you use construct be carefull because some classes constructors have some params that you'll also have to set (for example CActiveRecord take the scenario name as a param)
If I were you I'll use the init method as often as possible.

Kohana - Best way to pass an ORM object between controllers?

I have Model_Group that extends ORM.
I have Controller_Group that gets a new ORM:
public function before()
{
global $orm_group;
$orm_group = ORM::factory('Group');
}
...and it has various methods that use it to get different subsets of data, such as...
public function action_get_by_type()
{
global $orm_group;
$type = $this->request->param('type');
$result = $orm_group->where('type', '=', $type)->find_all();
}
Then I have another controller (in a separate module) that I want to use to manipulate the object and call the relevant view. Let's call it Controller_Pages.
$orm_object = // Get the $result from Controller_Group somehow!
$this->template->content = View::factory( 'page1' )
->set('orm_object', $orm_object)
What is the best way to pass the ORM object from Controller_Group to Controller_Pages? Is this a good idea? If not, why not, and what better way is there of doing it?
The reason for separating them out into different controllers is because I want to be able to re-use the methods in Controller_Group from other modules. Each module may want to deal with the object in a different way.
This is the way I would do it, but first I would like to note that you shouldn't use global in this context.
If you want to set your ORM model in the before function, just make a variable in your controller and add it like this.
public function before()
{
$this->orm_group = ORM::factory('type');
}
In your Model your should also add the functions to access data and keep the controllers as small as possible. You ORM model could look something like this.
public class Model_Group extends ORM {
//All your other code
public function get_by_type($type)
{
return $this->where('type', '=', $type)->find_all();
}
}
Than in your controllers you can do something like this.
public function action_index()
{
$type = $this->request->param('type');
$result = $this->orm_group->get_by_type($type);
}
I hope this helps.
I always create an helper class for stuff like this
Class Grouphelper{
public static function getGroupByType($type){
return ORM::factory('Group')->where('type','=',$type)->find_all();
}
}
Now you're been able to get the groups by type where you want:
Grouphelper::getGroupByType($type);

Base class for common YII functions?

I know how to create a class the will allow me to instantiate it and use across my project. What I want to be able to do is have functions without instantiating classes. For example, I know how to do this:
$core = new core();
$val = $core->convertToMyNotation($anotherval);
But what I want is to be able to do this ANYWHERE in any view, class whatever:
$val = convertToMyNotation($anotherval);
Where would I place these functions in order to be able to do that?
best way to do it, create a public function in components/Controller.php
public function globalFunction(){
// do something here.
}
and access it anywhere by
$this->globalFunction();
You can define a static method as an option.
class core{
public static function convertToMyNotation($value){
//do whatever here
return $value;
}
}
Then call it like so:
$val = core::convertToMyNotation($anotherval);
This requires no instantiation of the object to use. The only restriction is that you cannot use the $this property inside a static method.
Alternately, just define a file with your functions in it and include the file at some point early like, like within the boostrap script in your public_html/index.php file.
Edit: darkheir makes some good suggestions. Include such a class in your protected/components folder, and have it extend CComponent to gain some potentially useful enhancements.
By including the class in the protected/components folder, you gain the advantage of autoloading the class, by default.
There is no definitive question of your answer, it depends a lot on what the function will be doing!
If the function is performing some things specific to a model
(getting the last users, ...) this has to be in the User model as
Willem Renzema described:
class theModelClass {
public static function convertToMyNotation($value){
//do whatever here
return $value;
}
}
And you'll call it like
$val = theModelClass::convertToMyNotation($anotherval);
If the function is handling user inputs (sanitizing he inputs,
checking the values, ...) then it has to go to the controller and
you'll use Hemc solution:
Create a public function in components/Controller.php
public function globalFunction(){
// do something here.
}
and access it anywhere by
$this->globalFunction();
If the function is an Helper: performing some actions that do not
depend on models or user inoput then you can create a new class that
you'll put in your component directory:
class core extends CComponent{
public static function convertToMyNotation($value){
//do whatever here
return $value;
}
}
And
$val = core::convertToMyNotation($anotherval);
Actually, I think you're looking for this answer instead:
http://www.yiiframework.com/wiki/31/use-shortcut-functions-to-reduce-typing/
In essence, in your entry script, before you load up Yii, include a global functions file:
require('path/to/globals.php');
Then, any function defined in that file can be used as a shortcut. Be careful, but enjoy the power! :-)
Create something like
Class Core extends CApplicationComponent{
public function doSomething(){}
}
and in config main.php
'components'=>array(
'core'=>array(
'class' => 'Core'
),
),
and now you can call whenever you want
Yii::app()->core->doSomething();

How to extend an activeRecord model in Yii

I'm trying to create a form in Yii that is paged. Each page is for a group of fields. The best way to do this, I figured, would be to extend the ActiveRecord model and add a parameter for the current page. This also allows me to override the rules() methods with my own rules for the form itself.
My problem with this is, Yii doesn't allow us to natively extend models. I had to override the getMetaData() method because Yii runs self::model(get_class($this)) on itself, which ends up breaking everything.
Not only that, but I can't use findByPk because Yii relies heavily on the class name.
I know of tons of work arounds to make this work, but I'm wondering if I'm missing something.
Thanks,
Kyle
-- edit --
I totally figured it out, and I totally feel stupid. All I had to do with overwrite the model() method to return the current model class.
So:
class MyAr extends CActiveRecord {
public static function model($class = __CLASS__){return parent::model($class);}
}
class ExtendedForm extends MyAr {
public static function model($class = __CLASS__){return parent::model($class);}
}
Yeah ... I feel stupid.
To extend an ActiveRecord model, simply extend it! All you need to do is override the model method:
class MyAr extends CActiveRecord {
public static function model($class = __CLASS__){return parent::model($class);}
}
class ExtendedForm extends MyAr {
public static function model($class = __CLASS__){return parent::model($class);}
}
The model classes are subclasses of ActiveRecord, so you can override some vars/methods of ActiveRecord whitin them. What I mean is that there's no need to extend Activerecord... again! It is extended when defining models! So just add what whatever you need in there. Of course, this way has the inconvenience of adding the code manually in every model class. If it is too much, and if you're using gii, then you could just modify the code template that gii uses to generate the models.

Zend_Form disable populate before isValid()

Im not able to disable populating values in Zend_Form .
I have my own form class. With hidden token element where I would like to dynamicaly setup random value every time the form is called (or reposted). I thought that setValue will make the job.
class MY_Form_Test extends Zend_Form {
public function init() {
...
$this->addElement('hidden', 'token');
$this->getElement('token')->setValue(uniqid('',true));
...
}
BUT: When I have simple controller like this. Zend automate populating old hidden values except to generate new one.
$form = new JC_Form_Test();
if($form->isValid($_POST)){
// Action ...
}
else{
// Error
}
SOLUTION: The only solution I found is to call setValue in Controler AND AFTER isValid method. eg. in Error block.
QUESTION: Is there any way to setup element values directly in form class OR disable populate values in form class or before isValid() is called?
I think it's the best way to do it.
I work much with Zend Framework and have my own library for overwrite some Zend classes.
It's not bad to change something, but don't do it directly within Zend Framework
SECOND SOLUTION: Second solution I found is to overload isValid() method in Form class. Like this. Then I dont need to put setValue() into every Controller.
class MY_Form_Test extends Zend_Form {
...
public function isValid($data){
// Propagate values
$valid = parent::isValid($data);
$this->getElement('token')->setValue(uniqid('',true));
return $valid;
}
Are there any other solution eg. some element option to do this job more simple?