Implementing a custom getter in Yii? - php

I am working with Yii and I have the following situation:
I have a MySQL table:
charges {
id INT AUTOINCREMENT,
name VARCHAR(256),
value DOUBLE
}
Then I have the model from this table. And finally I have the views for create, list, admin, update and view.
In the admin and view views I want to display the value field formated with two decimal numbers. One option to do this could be in the view and admin files format the number. Is there a way to create a method in the model and then not having to do anything in the views but the method itself will solve formating the number?
thanks

You can override the afterFind() method of CActiveRecord in your model and format the value field in it.
Alternatively you could also declare a virtual attribute of the model, and set it in the afterFind() method, and use this virtual attribute in the views.
Example(with virtual attribute):
Class ChargesModel extends CActiveRecord{
public $valueModified;
/*
* other code
*/
protected function afterFind(){
parent::afterFind();
// in the following line i'm just making $valueModified and $value equal, but obviously you would have to insert the 2 decimals
$this->valueModified=$this->value;
}
}
Then you can access the virtual attribute like this : $modelObject->valueModified
I would recommend you to use the virtual attribute, because you then have both the unmodified $value and modified $modifiedValue, once the formatting is done, we can use either as required, and not have to reformat back to original when we need the original.

Related

Laravel replace variable on Model

I would like to be able to override a variable on the model, so that a normal field is instead replaced by a relationship's field, i.e.
Where product.image might normally be a field, I want to run a function which will go through all of the resulting products from a query and replace the image field with something like the following --
(Product.php) Model
...
public function variantImages(){
return $this->image = $this->variants()->first()->pluck('image_url');
}
...
So the default product image field is replaced by the "first product variant's image". I don't want to do this in a collection once I have already got the data, the problem here is being able to do this at a Model level.
Is there a way to do this within a scope?
You can create an accessor instead of a normal function:
// Singular because it only gets one
public function getVariantImageAttribute(){
return $this->image = $this->variants()->first()->pluck('image_url');
}
This will make it available under $product->variant_image
Then you can ensure it is always appended to your model (if you want) by adding it to the appends e.g.:
$appends = [ 'variant_image' ];
Since this is not the best idea since it will force load the relationship every time you get a product (even if you didn't request it) you can conditionally control when to append it via e.g.:
return response()->json($product->append('variant_image'));
Note that the append method also works for collecitions of eloquent models.

Laravel Eloquent : How to generate a fake column in a Json response?

I have two models: Uai and Information with an hasOne relationship.
Uai (uai_id, a)
Information (uai_id, b)
I want to generate a Json response witch contains :
all the Uai records
a "fake" column whitch says true if the hasOne Relationship exists between Uai and Information and false if there is no relationship
Any idea ?
Thanks in advance
Paguemaou
Edit One
Thanks jedrzej.kurylo for your answer.
How can I use the uai_id of the current row in the fake column getter ? I othen use getters and seeters but I never try to use the content of another column. Can you give me an example ?
If I understand, I can use the fake column name in a select like others columns name. I am true ?
Eloquent allows you to easily add custom field to a model's JSON representation.
Firstly, you need to define a list of additional fields by defining $appends property in your model class:
protected $appends = ['fakeColumnName'];
Secondly, add a getter for the fake column that will provide the value for custom column:
public function getFakeColumnNameAttribute() {
//here add the code that will return custom column's value
}

How to make models use defaults in Phalcon PHP Framework?

If a table has defaults on certain fields and NULL is not allowed, one would expect the insert script to use those defaults, as MariaDB/MySQL usually does. For example, if the table products has an AI field "id", a required field "name" and two required fields "active" and "featured" which both default to 1, then the query
INSERT INTO products (name) VALUES ('someName');
automatically inserts 1 as the value of active and featured. However, when using Phalcon's models like so:
$product = new Products();
$product->setName('someName');
$product->save();
returns validation errors saying "active" and "featured" are required.
Is there a flag I should provide during model generation in order for Phalcon tools to harvest and input the defaults into Model classes, or another way to make Phalcon automatically use defaults if found? Best approach would be just ignoring the fields that weren't set, I reckon. Can I make the models do that?
You can use a raw database value to avoid that, in specific inserts:
<?php
use Phalcon\Db\RawValue;
$product = new Products();
$product->setName('someName');
$product->setType(new RawValue('default')); //use default here
$product->save();
Or, general before create/update for specific fields:
use Phalcon\Db\RawValue;
class Products extends Phalcon\Mvc\Model
{
public function beforeValidationOnCreate()
{
$this->type = new RawValue('default');
}
}
Or ignore these fields in every SQL INSERT generated:
use Phalcon\Db\RawValue;
class Products extends Phalcon\Mvc\Model
{
public function initialize()
{
$this->skipAttributesOnCreate(array('type'));
}
}
Although I find twistedxtra's answer fascinating from the aspect that Phalcon contains this wicked method to read the column default, I believe from a architectural point of view this might be the wrong approach as you rely on your database to define the defaults of the properties of your model.
I would set the default value when declaring the property and keep the logic in the application layer. But that's just me.
Use Like below
The skipAttributesOnCreate will make sure Phalcon does not attempt to put a a value in that column. The database will apply the default value.
public function initialize()
{
$this->setSource('table_name');
$this->skipAttributesOnCreate(['name_of_column']);
}

Data can't save after alter the table in yii

I new in yii framework. i create an application in yii framework. i created model, controller, views using gii. After that i alter database table. I deleted 2 column and add 3 new columns. After that overwrite the model using the gii. But when i am trying to save into that table it show property(which was old column that I deleted) is not defined. Plz provide me a solution for this.
You need to define all columns in the validation rules() method in your model, have a look and make sure that you have defined a rule for every column in the table there, for example (if it's a string with max length 128):
public function rules()
{
return array(
...
array('myField', 'length', 'max'=>128),
...
);
}
See some info about validation rules.
Also, for forms if you're using CActiveForm widget and calling fields like so:
echo $form->labelEx($model,'myField');
echo $form->textField($model,'myField');
Then you'll need to make sure that a label is defined in the model too, in the attributeLabels() method, for example:
public function attributeLabels()
{
return array(
...
'myField'=>'My Field',
...
);
}
Lastly, if you want the field to be searchable, you'll need to add a statement to the search() method in the model, for example:
public function search()
{
...
$criteria->compare('myField',$this->myField);
...
}
Make sure you have all of those elements present and you shouldn't get the '* is not defined' error.
Also, if you're using schema caching in your main config file, you'll have to clear your cache before the app will see your new database structure.
Your changes should also be set at the Views since there are forms, widgets using the old properties !! (for this exact save issue, you will need to fix _form.php which is the partial responsible from your model Save & Update actions.
You can either do the same as you did with the model: (regenerate it using gii) or you can edit it manually (i recommend you get used to this since in the future you will have code you don't want to loose just because of altering a column name. simple Find & edit in most of the text editors will do the job).
May be you need to read a bit more about how MVC works in general & in Yii in special
This is because you are using schema-cache. Your table schema is cached in Yii. You need to flush AR cache. Either flush full schema cache or use
Yii::app()->db->schema->getTable('tablename', true); in start of your action. This will update model schema-cache.

Cakephp and database with uncomon structure

how can I access any table from database in my model?
For example, I have Indexcontroller and code inside it:
$results = $this->Index->query("SELECT COUNT(*) FROM my_own_table");
Error: Database table indices for model Index was not found.
So, as I understand, I can access only table with naming related to model/controller name. But what to do if I can't modify the table naming and I want to access it's data?
You're not limited to using a model that's directly associated with your controller (this is just default behaviour); you can use any model.
To achieve what you want, create a new model for this table, eg. MyOwnTable, and in your controller, you can add this property to the class:
public $uses = array('Index', 'MyOwnTable');
Now you can access MyOwnTable using CakePHP's built in ActiveRecord functionality:
$results = $this->MyOwnTable->find('count');
If you have other tables you want to access, simply create models for those and add them to the $uses property. (You can also use $this->loadModel('Model') inside the action if you prefer).
If you have a table name that isn't very readable (eg. my_tb_own_1_x or some such), you can call the model class something human readable (eg. MyTable), and add the $useTable property to the model:
public $useTable = 'my_tb_own_1_x';
/* and change the default primary key if you have an unusual one */
public $primaryKey = 'my_tb_own_1_x_idx_pk';
See the CakePHP manual for more info on how to change default model and controller behaviour:
1.3 - Model Attributes
2.0 - Model Attributes
1.3 - Controller Attributes
2.0 - Controller Attributes
Nope. You can access different tables. However, CakePHP stumbles over the fact that the table that is associated by default to the Index model doesn't exist.
In other words, the model Index expects a table 'indices' to exist (and an error is thrown when it doesn't). You can do one of two things:
Create a table indices
Add the following to your Index model: var $useTable = false;
If you have any use for an indices table I'd go with option 1. If you're not going to use the indices table, go with option 2.
If you go with either step 1 or 2, your example should start working.

Categories