How can I add a derived column to my Yii model? - php

In Yii, I need to add a "derived" column to any resultset from my model. The column doesn't actually exist in the database table.
For example, say I have an Activity model. There are only two types of Activities: (1) Income, or (2) Expense.
If I want to add a column called income_total or expense_total (depending on what type of activity is being accessed), how would I do that?
Here's a working example of an Activity model in Ruby on Rails (I'm basically wondering how to do the same thing, but in Yii):
class Activity < ActiveRecord::Base
attr_accessible :name, :effective_at, :amount, :category
scope :incomes, :conditions => { :category => 'Income' }
scope :expenses, :conditions => { :category => 'Expense' }
def self.incomes_total
incomes.sum :amount
end
def self.expenses_total
expenses.sum :amount
end
end
Update 2012-07-01:
The answer provided by Leonardo points to the use of Virtual Attributes, this adds an attribute to each "row" of the resultset that I'm retrieving from the database.
If the Activity model has a BELONGS_TO relationship with Parent, a Parent View may look like the following:
<h2><?php echo $parent->name; ?></h2>
<ul>
<?php foreach($portfolio->activities as $activity): ?>
<li>
<?php echo CHtml::link($activity->name, array('activity/view', 'id' => $activity->id)); ?>
<?php echo $activity->amount; ?>
<?php echo $activity->incomes_total; ?>
</li>
<?php endforeach; ?>
</ul>
However, it doesn't make sense for this Virtual Attribute to be accessed within the foreach() loop.
These Virtual Attributes that I want provide one "aggregated" value for the whole resultset, so I want to be able access it using $parent->activities->incomes_total, like so:
<h2><?php echo $parent->name; ?></h2>
<?php echo $parent->activities->incomes_total; ?>
<ul>
<?php foreach($portfolio->activities as $activity): ?>
<li>
<?php echo CHtml::link($activity->name, array('activity/view', 'id' => $activity->id)); ?>
<?php echo $activity->amount; ?>
</li>
<?php endforeach; ?>
</ul>
What do I need to do within the Activity model code to achieve this, or should I be thinking about this a different way?

I believe it is pretty similar to Ruby. PHP has magic methods, which in Yii is implemented by CComponent (base class of many including CActiveRecord).
In short you can do this within your model
class Activity extends CActiveRecord {
public function getIncome_Total() {
// ...
}
}
And, to access it from controller
$activity = Activity::model->findByPk(1);
$income_total = $activity->income_total;

As I posted in the other answer You can simply use a stat relation. Specify a STAT relation in Parent model as
'incomes_total'=>array(self::STAT, 'Activity', 'parent_id','select'=>'SUM(amount)','condition'=>"incomes_total.category='Income'")
Similiarly
'expense_total'=>array(self::STAT, 'Activity', 'parent_id','select'=>'SUM(amount)','condition'=>"incomes_total.category='Expense'")
NOTE: Change the attribute names parent_id and amount as in your model

I don't know how this can be done within the model.
Although it is more processing, an option or workaround is to add another foreach() loop to the View like so:
$incomes_total = 0;
foreach($parent->activities as $activity)
$incomes_total += $activity->amount;
echo $incomes_total;

Related

attempting to modify a field in codeigniter application db table but know how to identify the table

I am beginner in code igniter php framework. Today I have a task to modify existing code and somehow I am lost in the middle of the line on attempting to located a database table. This is the controller snippet that renders the view
..........
$data["all_types"] = $this->data_model->get_data("all_types",300,"Asc");
$this->load->view("preview_brands",$data);
...........
when the view is loaded I am iterating through the in the view to load data as shown
<div class="decoration"></div>
<?php foreach($all_types as $item): ?>
<div style="display:block;color:#000;">
<a style="font-size:17px;margin:15px 2px;font-family:Cgothic;"
href="<?php echo site_url()."...../..../".$item["id"]; ?>"
class="scale-hover"
title="<?php echo str_replace("_"," ",$item["name"]);?>">
<strong><?php echo str_replace("_"," ",$item["name"]);?></strong>
</a>
</div>
<?php endforeach; ?>
this is the model snippet code as shown
function get_data($db,$i,$order)
{
$this->db->order_by("name",$order);
$this->db->where('consent',"yes");
$query=$this->db->get($db);
return $query->result_array();
}
My challenge is how can I locate or identify the database table the above model is pointing to to fetch data. Hoping someone assists me
all_types is your table name.
$this->db->get($your_table name), get method take table name as a parameter.
Get Method Documentation
If more help needed I'm happy to help.
Happy Coding.
From your model code:
$query=$this->db->get($db);
This means $db is the table name. Looking at your controller code which calls the model function:
$data["all_types"] = $this->data_model->get_data("all_types",300,"Asc");
I can say that all_types is the name of the table.

CakePHP 3 create dynamic Menu

I am trying to create a short submenu for CakePHP with a Database Table.
First I tried this solution how to create dynamic navigation menu cakephp which seemed outdated (because its two years old) and since I donĀ“d need to add menus over the add function, its to big anyways.
So can I solve this with just the table in my DB, the model in Cake and an element?
Thats what I got so far:
src/template/element/main.ctp
<ul class="header main-menu">
foreach($something as $something ) :
?>
<li>
somethine
</li>
<? endforeach; ?>
</ul>
my view
<?= $this->element('main'); ?>
My Model
class Menu extends Entity
{
var $name = 'Menu';
}
Is this the way to go?
your question is a little generic, but here's something you want to consider:Html helper class
and in particular Html helper lists. That way you can do in your main.ctp:
$list = [];
foreach ($menu as $menuItem) {
$list[] = $menuItem;
}
echo $this->Html->nestedList($list);

CakePHP why is associated null?

I have several tables and corresponding models, that is to say, Staffs, Dpmembers, Subjects and Positions tables.
In my Staff model I create hasOne on Department because I want to retrieve data from Department table which is working.
But I have also created more associations of hasMany on Dpmember, Subject and Position models because I want to save the corresponding staff records.
The view newstaff.ctp looks like this
<div class="staff form">
<?php echo $this->Form->create('Staff');?>
<h3><?php echo __('Add a new staff member'); ?></h3>
<?php
echo $this->Form->input('name');
echo $this->Form->input('marital',array('label'=>'Marital status','options'=>array('empty'=>'Choose status','Single'=>'Single','Divorced'=>'Divorced','Married'=>'Married')));
echo $this->Form->input('Children');
echo $this->Form->input('nationality');
echo $this->Form->input('location');
echo $this->Form->input('email');
echo $this->Form->input('phone',array('label'=>'Phone number'));
echo $this->Form->input('nextofkeen',array('label'=>'Next of keen'));
echo $this->Form->input('keenrelation',array('label'=>'Next of keen relationship','options'=>array('Choose option'=>'Choose option','Husband'=>'Husband','Wife'=>'Wife','Guardian'=>'Gaurdian','Child'=>'Child')));
echo $this->Form->input('school');
echo $this->Form->input('award');
echo $this->Form->input('schoolperiod');
echo $this->Form->input('workplace',array('label'=>'Workplace'));
echo $this->Form->input('workposition');
echo $this->Form->input('workperiod');
echo $this->Form->input('dpmember.department.',array('options'=>$department,'empty'=>'Choose Department','label'=>'Department'));
echo $this->Form->input('subject.subjcet',array('options'=>array('Choose option'=>'Choose option','Science'=>'Science','Social Studies'=>'Social studies','English'=>'English','Mathematics'=>'Mathematics'),'label'=>'Subject'));
echo $this->Form->input('position.role',array('options'=>array('Choose option'=>'Choose option','Class teacher'=>'Class teacher','Bursar'=>'Bursar','Cook'=>'Cook'),'label'=>'Position'));
echo $this->Form->submit('Save staff', array('class' => 'btn btn-success', 'title' => 'Click here to add the user') );
?>
<?php echo $this->Form->end(); ?>
</div>
My Staff Model Staff.php like this
<?php
class Staff extends AppModel{
public $hasOne = array(
'Department'=>array(
'className'=>'Department'
));
public $hasMany = array(
'Dpmember'=>array(
'className'=>'Dpmember',
'foreign_key'=>'Dpmember.staff_id'
),
'Subject'=>array(
'className'=>'Subject',
'foreign_key'=>'Subject.staff_id'
),
'Position'=>array(
'className'=>'Position',
'foreign_key'=>'Position.staff_id'
)
);
}
?>
In my StaffsController.php I have a function newstaff() with the code below
public function newstaff() {
/*Create a select form field for departments */
$department = $this->Staff->Department->find('list',array('fields'=>array('Department.title','Department.title')));
$this->set('department', $department);
/*End creation of a select form field for departments */
if (!empty($this->request->data)) {
debug($this->request->data); // returns all data
debug($this->Staff->Subject->subject); // has returned null
debug($this->Staff->Position->position); // has returned null
debug($this->Staff->Dpmember->departement); // has returned null
}
}
I don't know why but for some reason, I have not been able to found out. Running debug($this->request->data) returns expected data.
But accessing individual associated form fields returns null values not the expected data. Please help me.
Thank you
You seem to be using CakePHP 3.0 syntax, while using CakePHP 2.3. The data returned is an array in Cake 2, not an object. So the data is under array keys, like:
$this->request->data['Staff']['Subject']['subject'];
$this->request->data['Staff']['Position']['position'];
$this->request->data['Staff']['Dpmember']['departement'];
Well I think finally I have got the values which are not null. Since I created relationships or rather associations among the models and am using CakePHP 2.3 the right way is
$this->request->data['associateModel']['FormField'];
Therefore I was supposed to do.
$this->request['Subject']['subject'];
$this->request['Subject']['position'];
$this->request['Subject']['department'];
Thank you very much #Oldskool

How to add functions to a MVC Joomla component to access data from a different table?

I have a custom joomla MVC component created by http://component-creator.com with 4 tables:
#__mycomponent_items 27 Fields
#__mycomponent_bids 12 Fields
#__mycomponent_journeys 9 Fields
#__mycomponent_users 8 Fields
I am trying to set the relationships between these tables, but in the absence of documentation and experience I am struggling.
The basic relationships between the tables need to allow USERS to make BIDS to deliver ITEMS.
So I have created fields for items like this:
#__mycomponent_items
id
created
updated
ordering
state
checked_out
checked_out_time
created_by
deliverydestination
itemtitle
status
requiredby
listprice
deliveredprice
commission
points_reward
accepted_bid
accepted_bidder
accepted_journey
And for bid like this:
#__mycomponent_bids
id
state
created_by
item_id
buyer
bid
created
updated
bid_status
bid_expires
journey
arrival_date
I am working in templates/mytemplate/html/com_mycomponent/item/default.php and trying to add to that view a list of the current bids on that item. To do that I assume I need to add a custom function to /components/com_mycomponent/models/item.php and the function I have created is follows:
function itemBids() {
// Get a db connection.
$db = JFactory::getDbo();
// Create a new query object.
$query = $db->getQuery(true);
// Select item record matching the $orderID
$query
//->select('*')
->select($db->quoteName(array('id', 'created_by', 'created', 'bid', 'bid_status', 'arrival_date')))
->from($db->quoteName('#__mycomponent_bids'))
->where('item_id = item.id');
// Reset the query using our newly populated query object.
// Load the results as a list of stdClass objects (see later for more options on retrieving data).
$db->setQuery($query);
$itemBids = $db->loadObjectList();
//print_r($itemBids);
}
How do I then access the data in the view /mytemplate/html/com_mycomponent/item/default.php?
I have tried this and it returns nothing:
<ul>
<?php foreach ($itemBids as $itemBid) :?>
<?php $arrivalDate = $itemBid->arrival_date; ?>
<li><strong><?php echo $itemBid->created_by; ?></strong> <small>can deliver for</small> $<?php echo $itemBid->bid;?> <small>
<?php /*?><abbr class="timeago" title="<?php echo $itemBid->created; ?>"></abbr><?php */?>
in <strong><abbr class="timeago" title="<?php echo $arrivalDate; ?>"></abbr></strong></small><div class="uk-badge uk-float-right"><?php echo $itemBid->bid_status; ?></div></li>
<?php endforeach; ?>
</ul>
You wouldn't be putting it in your template like that. the template just holds the layouts that generate the html. Also you need to have a default layout in your views/myview/tmpl folder.
You don't seem to be returning anything from your itemBids() function. You would want to add return $itemBids; or possibly return $this->itemBids; depending on what you are doing elsewhere.
YOu want to get $this->itemBids in your view.html.php class so that it is then available to your layout. THen instead of referring to $itemBids you can refer to $this->itemBids in your loop in the layout.
Have you been through the Creating an MVC Cmponent tutorial? It would probably help you get a sense of how MVC works in Joomla.
OK , as far as I understand you have a method in yourmodel.php and you are trying to access it from the view I did notice that you are not returning any values in your method
return $db->loadObjectList();
let me just make it simple by the below code
//com_component/models/yourmodel.php
class componentModelYourmodel extends JModelLegacy
{
function yourMethod()
{
//code
return $value;
}
}
And then in view file
//com_component/views/yourview/tmpl/default.php
//get the model first
$model=$this->getModel();
//call the method
$items=$model->yourMethod();
//print
print_r($items);

How to convert to use the Yii CDataProvider on view?

I am trying to learn Yii, and have looked at Yii documentation, but still do not really get it. I still have no idea how to use the CDataProvider on the Controller and View to display all the blog posts available on the view. Can anyone please advise or give an example based on the following:
The actionIndex in my PostController:
public function actionIndex()
{
$posts = Post::model()->findAll();
$this->render('index', array('posts' => $posts));
));
The View, Index.php:
<div>
<?php foreach ($post as $post): ?>
<h2><?php echo $post['title']; ?></h2>
<?php echo CHtml::decode($post['content']); ?>
<?php endforeach; ?>
</div>
Instead of doing the above, can anyone please advise how to use the CDataProvider to generate instead?
Many thanks.
The best that i can suggest is using a CListView in your view, and a CActiveDataProvider in your controller. So your code becomes somewhat like this :
Controller:
public function actionIndex()
{
$dataProvider = new CActiveDataProvider('Post');
$this->render('index', array('dataProvider' => $dataProvider));
}
index.php:
<?php
$this->widget('zii.widgets.CListView', array(
'dataProvider'=>$dataProvider,
'itemView'=>'_post', // refers to the partial view named '_post'
// 'enablePagination'=>true
)
);
?>
_post.php: this file will display each post, and is passed as an attribute of the widget CListView(namely 'itemView'=>'_post') in your index.php view.
<div class="post_title">
<?php
// echo CHtml::encode($data->getAttributeLabel('title'));
echo CHtml::encode($data->title);
?>
</div>
<br/><hr/>
<div class="post_content">
<?php
// echo CHtml::encode($data->getAttributeLabel('content'));
echo CHtml::encode($data->content);
?>
</div>
Explanation
Basically in the index action of the controller we are creating a new CActiveDataProvider, that provides data of the Post model for our use, and we pass this dataprovider to the index view.In the index view we use a Zii widget CListView, which uses the dataProvider we passed as data to generate a list. Each data item will be rendered as coded in the itemView file we pass as an attribute to the widget. This itemView file will have access to an object of the Post model, in the $data variable.
Suggested Reading: Agile Web Application Development with Yii 1.1 and PHP 5
A very good book for Yii beginners, is listed in the Yii homepage.
Edit:As asked without CListView
index.php
<?php
$dataArray = $dataProvider->getData();
foreach ($dataArray as $data){
echo CHtml::encode($data->title);
echo CHtml::encode($data->content);
}
?>

Categories