Being a self-confessed newbie I'm looking for some advice and guidance :)
I have a table in my database called Dams which is simply a list of dams throughout the world. One of the fields within that table is called Country; the country that the named dam is in.
I want to put a search form on my site allowing someone to search through the dams, and for the Country field I want to present it as a dropdown list, listing all the countries that occur in that field, in alphabetical order with a number after each country's name with the number of times that country occurs in the field. For example, there are 15 dams in Brazil so I want the dropdown entry for Brazil to read 'Brazil (15 dams)'.
Things are further complicated because the dam countries saved in the database are just the country codes (US, GB, etc.) not the actual country names (United States, United Kingdom etc.) which is what I want use.
I've created an array of country codes/names like so:
$countries = array(
"AF" => "Afghanistan",
"AL" => "Albania",
"DZ" => "Algeria",
"AS" => "American Samoa",
...
"ZW" => "Zimbabwe"
);
And I've created the query below to retrieve the country field contents from the table, count how many of each country occurs, and group the results:
$result = $this->db->query("select country,count(*) as count from default_dams group by country")->result_array();
Now I've got to the point where I don't know how to proceed.
I've experimented using a foreach loop like so:
foreach ($query as $row)
{
$dropdown[$row['country']] = $row['count'];
}
return $dropdown;
and it's giving...
<option value="AL">3</option>
<option value="CN">94</option>
<option value="ZW">1</option>
...so I feel I'm getting somewhere, but I don't know how to bring in my $countries array in order to provide output like:
<option value="AL">Albania (3 dams)</option>
<option value="CN">China (94 dams)</option>
<option value="ZW">Zimbabwe (1 dam)</option>
I'm guessing I need a foreach loop to go through $result and form an array of results to pass from my model to the view, but how to build that array?
By the way, the code snippet from my view file that displays the dropdown is:
$first_field = '><option value="all">Any Country</option';
echo form_dropdown('dam-country', $dropdown, 'all', $first_field);
All help and advice is gratefully received. :)
Tony.
Uhh, i'm not sure if following code be correct since i didn't get some parts of your descriptions, but i'd rewrite foreach like so:
foreach ($query as $row)
{
$option = $countries[$row['country']] . '(' . $row['count'];
// check dams number if one then word "dam" is singular, otherwise plural
if ($row['count'] == 1) {
$option .= ' dam)';
} else {
$option .= ' dams)';
}
$dropdown[$row['country']] = $option;
}
return $dropdown;
I myself not a fan of html code generation functions, i'd just write everything myseld in the view (example based on some assumptions):
// rows - data from the DB sent to View
echo '<select name="countries">';
echo '<option value="all">Any Country</option>';
foreach ($rows as $row)
{
echo '<option value="' . $row['country'] . '">';
$option = $countries[$row['country']] . '(' . $row['count'];
// there must be a dedicated function to deal with singular/plural words in CI
if ($row['count'] == 1) {
$option .= ' dam)';
} else {
$option .= ' dams)';
}
echo $option;
echo '</option>';
$dropdown[$row['country']] = $option;
}
echo '</select>';
Related
CURRENT ISSUE: I am making one plugin for listing users with there user role in WP_LIST_TABLE table.
This is my query
$this->items = $wpdb->get_results($wpdb->prepare("SELECT {$wpdb->users}.*, {$wpdb->usermeta}.meta_value as roles FROM {$wpdb->users}
LEFT JOIN {$wpdb->usermeta} ON {$wpdb->users}.ID = {$wpdb- >usermeta}.user_id
WHERE {$wpdb->usermeta}.meta_key = '{$wpdb->get_blog_prefix()}capabilities'
ORDER BY {$wpdb->users}.display_name", $per_page, $paged), ARRAY_A);
It display out like This
[roles] => a:1:{s:13:"administrator";b:1;}
How to Unserialize this data. and I want to display the First name too using this query please help me
Finally this helps me.
$input = unserialize($item['roles']);
$result = array();
foreach($input as $key => $value){
$result[] = $key;
}
$userRole = implode(",", $result);
return $userRole;
Try below code:
foreach($this->items as $value){
echo $value->COLUMN_NAME ."<br>";
}
Please change the COLUMN_NAME to whichever column you want to display. If there's a column named e_name, then write "$value->e_name".
Its tried and tested. It works for me. Let me know if it works for you!
I have 3 models Job, Diary, Resource.
Jobs has relation with Diary and Diary has relation with Resource.
I wanted to get all Resource associated with a Job and did this using
public function labourers()
{
return $this->hasManyThrough(Resource::class, Diary::class, 'job_id');
}
On my Job class.
Now I want to group the results by User who's user_id is a column in Resource and then show the total hours.
This is the closest I can get.
$job = Job::where('job_number', 3007)->first();
$labour = $job->labourers()->get();
$results = $labour->groupBy('user_id');
echo $results;
foreach($results as $result)
{
$hours = $result->sum('hours');
echo $result[0]->user_id." - ";
echo $hours.". ";
}
This gets me the user_id and the sum of the hours but I am unable to access the user name through the relationship set up on the resource model
public function user()
{
return $this->belongsTo(User::class);
}
with
$result->user->name;
This produces
Property [user] does not exist on this collection instance.
How can I return a collection which allows me to access the users name and the sum of the hours.
The reason you're not able to access the user like that is because (in this case) groupBy is a method on the collection that returns another collection.
Firstly, eager load the user relationship on so that your code is a bit more efficient:
$labour = $job->labourers()->with('user')->get();
Secondly, since you have a collection you can use first() instead of [0]:
$result->first()->user_id
Lastly, you would have to access the user in the same way you're accessing the user_id:
$result->first()->user
So, you would end up with something like:
$job = Job::where('job_number', 3007)->first();
$labourers = $job->labourers()->with('user')->get();
$results = $labourers->groupBy('user_id');
foreach($results as $result)
{
echo $result->first()->user->name . ' - ' . $result->sum('hours') . '.';
}
You can try this
$job = Job::where('job_number', 3007)->with(['labourers' => function($query){
$query->select('id','user_id', DB::raw('sum(hours) as hours'))->groupBy('user_id');
}, labourers.user])->first();
$results = $job->labourers;
foreach($results as $result){
print_r($result->user);
print_r($result->hours);
}
I have I problem that I hope someone can help me with. I thought this code was right, but it will not work. Below is my code, it is a function for my CakePHP 2.2.2 site, the main aim of the code is to produce a menu system from database results. The problem is with my foreach loop, it will not loop. All $Key does is return the value of 2 (three records within the table at this time). So When I display / echo / debug $Menu, the only result I get is the last result stored within the database.
I know the SQL command is right, if that is debuged / echoed then all three results are displayed. The idea of this loop was to get it to count the results, so that I could run a check on a selected field. Where I am going wrong?
function MenuSystem() {
$this->loadModel('Menu');
$MenuSQL = $this->Menu->find('all', array('conditions' => array('active' => true)));
foreach ($MenuSQL as $Key=>$Value) {
$MenuSystem = $MenuSQL[$Key];
$this->Menu = $MenuSystem;
}
}
Many Thanks,
Glenn.
UPDATE :::
Below is my function, now my foreach loop now works, don't know what I was doing wrong, but I know think its working. You can see the print_r command that I am using for testing, if I use that, then all links from my database are printed / echoed on the screen and all works. But if I try and call the $this->Menu from another controller, then only the last record is echoed on the screen. I have moved the $this->Menu outside of the foreach loop, but it made no difference, with it inside the loop or outside, it still only echoes the last record and not all three. So what I am doing wrong?
function MenuSystem() {
$this->loadModel('Menu');
$SiteBase = '/projects/cake/';
$MenuSQL = $this->Menu->find('all', array('conditions' => array('active' => true)));
foreach ($MenuSQL as $key => $Value) {
$MenuAccessLevel = $MenuSQL[$key]['Menu']['roles_id'];
if ($MenuAccessLevel == 1) {
$Path = $MenuSQL[$key]['Menu']['path'];
$Title = $MenuSQL[$key]['Menu']['title'];
$MenuSys = "<a href=\" " . $SiteBase . $Path . " \">" . $Title ."";
} else {
print ("Admin");
}
//print_r($MenuSys);
} //End of Foreach Loop
$this->Menu = $MenuSys;
} //End of function MenuSystem
So When I display / echo / debug $Menu, the only result I get is the last result stored within the database.
You're setting the value of $this->Menu within the foreach, so when the foreach is complete it will take the last value iterated over.
If you want to find the number of records matching a condition, try:
$menuCount = $this->Menu->find('count', array(
'conditions'=>array('active'=>true)
));
$this->set(compact('menuCount'));
Edit: also, by setting the value of $this->Menu within the foreach, you're overwriting the Menu model variable. This is not a good idea.
Edit2: to get the counts of rows as grouped by some value, try:
$this->Menu->virtualFields = array('count' => 'count(*)');
$counts = $this->Menu->find('all', array(
'group'=>'Role',
'fields'=>array('Role', 'count'),
));
This generates SQL to have the results grouped by the Role column. Returned fields are the name of the role, and the number of rows having that value.
If you wanted to do it with a foreach loop instead, it might look like:
$menus = $this->Menu->find('all', array('fields'=>array('id', 'Role')));
$counts = array('user'=>0, 'admin'=>0);
foreach ($menus as $menu) {
$role = $menu['Menu']['Role'];
$counts[$role] += 1;
}
I saw this answer from a post that is intended to post database data from specific set_id with its following questions and answers. I find it hard to convert it that it has to be separated into models-controllers-views principle of codeigniter. I need some help here
It has 3 tables and came up with this code:
<?php
$this->db->select('s.id as set, s.name as name, q.id as qid, q.question as qu, a.id as aid, a.answer as an, a.points as p')
->from('sets s')
->join('questions q', 'q.set_id = s.id')
->join('answers a', 's.set_id = s.id')
->where('s.id', 'SET ID');
$questions = $this->db->get();
$set = array('questions' => array());
foreach($questions as $s){
$set['id'] = $s->set;
$set['name'] = $s->name;
$set['questions'][$s->qid]['id'] = $q->qid;
$set['questions'][$s->qid]['question'] = $q->qu;
if(!isset($set['questions'][$s->qid]['answers']))
$set['questions'][$s->qid]['answers'] = array();
$set['questions'][$s->qid]['answers'][] = array(
'id' => $q->aid,
'answer' => $q->an',
'points' => $q->p
);
}
echo '<h2>'.$set['name'].'</h2>';
foreach($set['questions'] as $q){
echo '<div class="question">';
echo '<h3>'.$q['question'].'</h3>';
echo '<div class="answers">';
foreach($q['answers'] as $a){
echo '<label for="a'.$a['id'].'">'.$a['answer'].'<input type="checkbox value="'.$a['id'].'" name="q'.$q['id'].'" /></label><br />';
}
echo '</div>';
echo '</div>';
}
MVC pattern is simple once you get used to it . The model component basically handles the database query. you can write simple functions for different query and put them under model class . The Controller basically pulls the model data and puts forward to the View component.
Inside the controller you will define logics how and where to put the data into different View classes . The following link is a good place to check out .
http://kyokasuigetsu25.wordpress.com/2012/01/06/codeigniter-beginner-tutorial-3-playing-with-the-database/
In this instruction there is a problem
$set = $questions->result_array();
In my CakePHP forms_controller I have:
var $uses=array('Form','Field');
// ...
$this->set('retrived',$this->Field->find("all",array('conditions'=>array('Field.formname'=>$formname,))));
and in the view:
<?php foreach ($retrived as $r): ?>
<?php echo $r['Field']['fieldname']; ?><br>
<?php endforeach; ?>
I'm not getting the answer for it
Actually my table fields wil be like:
fieldname
formname
type
value
More details from my forms_controller:
function views()
{
if (!empty($this->params['form']))
{
$this->set('fieldctr',$this->params['form']['formfieldctr']);
$fieldctr=$this->params['form']['formfieldctr'];
if(!empty($this->params['form']['formnameelements']))
{
$this->set('formname',$this->params['form']['formnameelements']);//formname
$this->Form->saveField('name',$this->params['form']['formnameelements']);
}
else
{
$this->set('formname','MyForm');//formname
$this->Form->saveField('name','MyForm');
}
$this->Form->saveField('body',$this->params['form']['formelements']);//inserts into database
$ret = $this->Form->query("Select id from forms order by id DESC LIMIT 1");
$newid=$ret[0]['forms']['id'];echo $newid;
$upd=$this->Form->query("update forms set ctr=$fieldctr where id= $newid");
$formname=$this->params['form']['formnameelements'];
$n="$formname";
$array = $this->params['form']['formfieldnameelements'];
$comma_separated = explode(",", $array);
for($i=0;$i<$fieldctr;$i++)
{
echo $comma_separated[$i];
echo " ";
$n="$comma_separated[$i]";
//insert the fields of each form to the table fields
$this->data['Field']['fieldname'] = $comma_separated[$i];
$this->data['Field']['formname'] = $formname;
$this->Field->saveAll($this->data);
}
The above method is where I'm inserting the formname in my forms table.
And inserting that formname with their fieldsname in the fields table:
function formupdate()
{
$this->set('fieldctr',$this->params['form']['formfieldctr']);
$fieldctr=$this->params['form']['formfieldctr'];
$this->set('formname',$this->params['form']['formnameelements']);//formname
$formname=$this->params['form']['formnameelements'];
$ret = $this->Field->query("SELECT fieldname FROM fields WHERE fields.formname = "."'$formname'"."order by id ASC");
for($q=0;$q<$fieldctr;$q++)
{
$fieldname[$q]=$ret[$q]['fields']['fieldname'];
}
$this->set('retrived',$this->Field->find("all",array('conditions'=>array('Field.formname'=>$formname))));
$array = $this->params['form']['formfieldvalueelements'];
$comma_separated = explode(",", $array);
for($i=0;$i<$fieldctr;$i++)
{
echo $comma_separated[$i];
echo " ";
$n="$comma_separated[$i]";
echo $fieldname[$i];
$this->Field->updateAll(array('Field.value' => "'$comma_separated[$i]'"),array('Field.fieldname' => $fieldname[$i],'Field.formname'=>$formname));
}
$this->set('retrived',$this->Field->find("all",array('conditions'=>array('Field.formname'=>$formname,))));
} // end of function formupdate
In the above formupdate method I'm inserting the values of the corresponding values of that fields in the fields table... All the values are inserted correctly - but in my formupdate.ctp view:
Nothing is displayed in my view... eventhough the content is there in the table..
Please resolve my problem
By the names of your models, I think it's safe to conclude that you're trying to ouput some HTML. Since the question isn't really complete (where is the code?), we can't tell what's wrong with it.
A wild guess would be that something is being stripped there or ignored by your browser.
Aruna,
Please post the code you're using! It's possible that the error is something small, but without knowing what you're doing, it's impossible to help more than dr. Lecter did.
When you say that the fields table is updated correctly, do you mean that you can safely invoke the Model::save() method? Are you then calling Model::read() or Model::find() in the controller, then using the returned values from that to set a variable that can be accessed in the view?