Getting count of occurrences in Laravel - laravel

I have a backend where I can create a Poll. Within a Poll I can create a PollQuestion. And for a PollQuestion, I can create many PollAnswer's.
If I do something like this in my Controller
$poll = DB::table('poll')->orderBy('id', 'desc')->first();
$question = DB::table('poll_question')->where('poll_id', $poll->id)->first();
$answers = DB::table('poll_answer')->select('answer')->where('question_id', $question->id)->get();
print_r("<pre>");
print_r($answers);
print_r("</pre>");
I can see an output like the following
Array
(
[0] => stdClass Object
(
[answer] => Answer 1
)
[1] => stdClass Object
(
[answer] => Answer 2
)
[2] => stdClass Object
(
[answer] => Answer 3
)
[3] => stdClass Object
(
[answer] => Answer 4
)
)
So, the above Poll was given 4 possible answers to the PollQuestion.
Now I have a frontend which displays the question, and a radio button for each PollAnswer. When they select one and save, I get a PollResponse. If I do something like this
$pollResponses = DB::table('poll_response')->select('response')->where('poll_id', $poll->id)->get();
The output might be something like this
Array
(
[0] => stdClass Object
(
[response] => Answer 1
)
[1] => stdClass Object
(
[response] => Answer 4
)
[2] => stdClass Object
(
[response] => Answer 4
)
[3] => stdClass Object
(
[response] => Answer 2
)
[4] => stdClass Object
(
[response] => Answer 3
)
)
So I can see what people have selected. Now, for each possible PollAnswer, I need to count the number of PollResponse which relate to it. So for the above data, I should get something like
1 = 1
2 = 1
3 = 1
4 = 3
Is there any easy way I can do this in Laravel, or would I need to loop both the Answers and Responses to get the individual counts?

I don't know of any laravel-specific solution, but you can always push the responses to a separate array and then use the php function array_count_values($array) (http://php.net/manual/en/function.array-count-values.php) on the new array.
$newArray = array();
for($i=0; $i < count($pollResponses); $i++){
array_push($newArray, $pollResponses[$i]->response);
};
$count = array_count_values($newArray);
It will return a two dimensional array with the answer as the key and the number of times it occurs as the value.

Assuming that you're using models,you can do this in Laravel
$polls = Poll::with(['questions.answers'])->get();
Your Poll.php file
...
class Poll extends Model{
public function questions(){
return $this->hasMany(Question::class);
}
}
Your Question.php file
...
class Question extends Model{
public function answers(){
return $this->hasMany(Answer::class);
}
}
And then in your view file (assuming it's .blade.php)
#foreach($polls as $poll)
#foreach($poll->questions as $question)
{{ $question->title }}
<ul>
#foreach($question->answers as $answer)
<li>{{ $answer->title }} </li>
#endforeach
</ul>
#endforeach
#endforeach

Related

insert data into laravel 5 blade from array

I'm puzzled over this one..
I have an array of arrays that I'm passing into a blade from a controller
data looks like this
(
[0] => Array
(
[id] => 1
[name] => AAAA
)
[1] => Array
(
[id] => 2
[name] => BBBB
)
[2] => Array
(
[id] => 3
[name] => CCCC
)
[3] => Array
(
[id] => 4
[name] => DDDD
)
)
The controller passes it by calling the view as such
return view('items.pivot', compact('sites'));
and I attempt to display it in the blade like
#foreach($sites as $site)
#if($site != '' || $site != null)
<th class="col1" >{{$site->name}}</th>
#endif
#endforeach
However what I get is the correct number of columns, but with each looking like
<th class="col1" ></th>
What am I doing wrong? I know it must be obvious.. but I can't see it..
You're treating it like an object, while it's an array that you fed into view.
So change your code from $site->name to $site['name']
It is an array and you are treating it as an object. Replace {{$site->name}} with {{$site['name']}}

How to loop collection without looping inside each item?

I have a collection. For each item I want to add a new attribute [users]. When I loop collection with map function or even if foreach, I notice, the code is looping inside each item. So each atribute from collection item is read. Please look at this following
Log $myCollection:
local.INFO: Illuminate\Support\Collection Object
(
[items:protected] => Array
(
[0] => Array
(
[id] => 6
[name] => AAAAA
[code] => D2
[component_id] => 5
)
[1] => Array
(
[id] => 7
[name] => BBBB
[code] => D1
[component_id] => 5
)
[2] => Array
(
[id] => 47
[name] => CCCC
[code] => CR7
[component_id] => 3
)
[3] => Array
(
[id] => 48
[name] => DDDD
[code] => CJ9
[component_id] => 3
)
)
)
$myCollection->map(function ($item) use($users, $role) {
$item = Site::findOrFail($item);
$item->users = $users;
return $item;
});
I get :
SQLSTATE[22P02]: Invalid text representation: 7 ERROR: invalid input syntax for integer: "AAAA". and I think it is because the code loops on name from each item of myCollection.
How do I fix it, please? thanks
The $item contains each object of the collection so you should use the appropriate key.
$myCollection->map(function ($item) use($users, $role) {
$item = Site::findOrFail($item->id); // or $item['id']
$item->users = $users;
return $item;
});
Actually now that I looked at it better, you don't need at all to find the item again. So in your closure just having these two lines is enough.
$item->users = $users;
return $item;

Transforming multidimensional array data returned from database

I am having problems with working with multidimensional array data.
I have 2 tables (maincategories and categories) which I joined.
Table Maincategories:
id, maincategory
Table Categories:
id, maincategory_id, category
$this->db->select('m.id, m.name_en AS maincategory')
->select('c.name_en AS category')
->from('categories AS c')
->join('maincategories AS m', 'c.maincategory_id=m.id', 'left');
$query = $this->db->get();
This results in all 4 categories being listed as below.
[3] => stdClass Object
(
[id] => 7
[maincategory] => Career
[category] => Business Sales
)
[4] => stdClass Object
(
[id] => 1
[maincategory] => Accommodation
[category] => Camping
)
[5] => stdClass Object
(
[id] => 6
[maincategory] => Accommodation
[category] => Hostels
)
[6] => stdClass Object
(
[id] => 7
[maincategory] => Career
[category] => Career Events
)
4 unique categories are in the list while 2 of them belong to maincategory: Accommodaton and the other 2 categories belong to maincategory: Career. What I wanted to achieve is that each maincategory is only listed ONCE and the categories shall fall under that main_category. Something like this:
[6] => stdClass Object
(
[id] => 7
[maincategory] => Career
[category] => array(Career Events, Business Sales, .....)
)
[7] => stdClass Object
(
[id] => 7
[maincategory] => Accommodation
[category] => array(Hostels, Camping, .....)
)
The array dump will maybe/probably look different in its end result but I hope you understand what I am trying to achieve. I read quite a bit about transforming multidimensional arrays. I just can't get my head around it yet. Thanks a lot for any direction!
Try like this:
function fetch_all(){
$data = array();
$first = $this->db->select('id, maincategory')->get('maincategory')->result_array();
if( is_array( $first ) && count( $first ) > 0 ){
foreach( $first as $key => $each ){
$data[$key]['category_id'] = $each['id']; #main category id
$data[$key]['maincategory'] = $each['id']; #main category name
$second = $this->db->select('category')->where_in('maincategory_id', $each['id'])->get('categories')->result_array();
$data[$key]['category'] = $second; #all sub-category(s) array
}
}
}
instead of using so many db calls, try using the underscore.php library http://brianhaveri.github.io/Underscore.php/
I've outlined a few examples of how to use it for this case here: http://codebyjeff.com/blog/2012/08/no-more-machine-gunning-use-underscore-php
Edit

Joomla user management

I got a Joomla ticketing module, that displays at a certain part of the page, the current tickets of the current user. I want to create user groups, in which the group members can view all of the tickets belongin to that group. I thought the easiest way is to create Joomla groups, assign the users to those, and to when a user loges in, it can see all of the tickets in its group. I added my code to the start of the function, but something is wrong... For every user (currently the "Registered" ones) displays the same result, that of the last users tickets, and I don't know why: Here is the code:
function gTickets()
{
$user =& JFactory::getUser();
$user_id = (int) $user->get('id');
//get user_group_id from db based on current users id
{...}
//get all users with that user_group_id
$db1->setQuery($db1->getQuery(true)
->select('*')
->from("#__user_usergroup_map")
->where("group_id = '$groupss'")
);
$groupss1=$db1->loadRowList();
$return1=array();
// for every user_id
foreach ($groupss1 as $keya)
{
$user_id = $keya[0]; // the id of users
$where = "";
if ($this->is_staff)
$where .= " AND t.`staff_id`='".$user_id."'";
else
$where .= " AND t.`customer_id`='".$user_id."'";
$tickets = $this->_getList(
"SELECT t.id, t.subject, t.last_reply_customer, s.name AS status_name FROM
#__rsticketspro_tickets t LEFT JOIN #__rsticketspro_statuses s ON
(t.status_id=s.id) WHERE 1 $where ORDER BY `last_reply` DESC", 0,
$this->params->get('tickets_limit', 3));
print_r($tickets);
return $tickets;
}
I got some questions, that I didn't know how to seach for...
what is the letter dot fieldname in the sql query? eg:
SELECT m.ticket_id, m.message FROM #__ticket_messages m WHERE m.user_id !='".$user_id."
what does the "m" mean before the WHERE?
what does the "1" do here: WHERE 1 $where
Also, I looked in the ACL managers, but could not make it work with this code.
Edit: Thanks for the fast answers! I got 1 more, and I think it's an easy one, but I can't get it to work...
If I print the content of the $ticket array into another array, I get an array with multiple arrays. That is why my code is not working... The array i'm getting is:
Array (
[0] => stdClass Object (
[id] => 1
[subject] => use1
[last_reply_customer] => 1
[status_name] => open
)
)
Array (
[0] => stdClass Object (
[id] => 3
[subject] => use2
[last_reply_customer] => 1
[status_name] => open
)
[1] => stdClass Object (
[id] => 2
[subject] => use2
[last_reply_customer] => 1
[status_name] => open
)
)
I would like the array to look like this:
Array (
[0] => stdClass Object (
[id] => 1
[subject] => use1
[last_reply_customer] => 1
[status_name] => open
)
[1] => stdClass Object (
[id] => 3
[subject] => use2
[last_reply_customer] => 1
[status_name] => open
)
[2] => stdClass Object (
[id] => 2
[subject] => use2
[last_reply_customer] => 1
[status_name] => open
)
)
Thanks!
Edit: is all of this complicated to achieve?
Look into ACL to get that part working, but to answer the 3 questions you posted at the bottom of your question:
1) the letter.field_name in the query represents the table alias.field_name in the query. The alias (m) makes it easier so you don't have to keep typing the full table name each time.
2) The m before the WHERE is actually setting the table alias, but with lazy syntax. It should say:
SELECT m.ticket_id, m.message FROM #__ticket_messages AS m
3) The "WHERE 1" is the SQL way of saying "if (true)". Since they are immediately appending the $where clause afterwards "WHERE 1 $where", the resulting query looks like this:
WHERE 1 AND t.staff_id = '" . $user_id . "'
Did you code this originally? or is it a component that you picked up somewhere? It should be using the query builder instead of direct SQL like it currently is, to make it more portable and more clear as to what it is doing.

multidimensional array

What is the meaning of the following line:
$data[0][$row->parentid]['children'][$row->id] = $row->name
From the function:
function getCategoriesNav(){
$data = array();
$this->db->select('id,name,parentid');
$this->db->where('status', 'active');
$this->db->orderby('parentid','asc');
$this->db->orderby('name','asc');
$this->db->groupby('parentid,id');
$Q = $this->db->get('categories');
if ($Q->num_rows() > 0){
foreach ($Q->result() as $row){
if ($row->parentid > 0){
$data[0][$row->parentid]['children'][$row->id] = $row->name;
}
else{
$data[0][$row->id]['name'] = $row->name;
}
}
}
$Q->free_result();
return $data;
}
Where do the children come from, and what is the meaning of:
$row->parentid or $row->name? I don't have any field 'children' in my table, and it's not declared any where. Please help
Thank you in advance,
Mehdy
Update
Sorry if I didn’t explain the question clearly. My question was: what is the meaning of the following line in this function
$data[0][$row->parentid]['children'][$row->id] = $row->name, from where this children come from, and what actual mean by $row->parentid or $row->name? I don’t have any field 'children' in my table, and it’s not declared anywhere, please help me.
Thank you
mehdy
Read the code. If the row from categories has a parent ID, child IDs are added to the array under the parent ID's children element. This is simply taking the result set and converting it into a hierarchy data structure which eliminates repetition in places and makes it easier to traverse.
Update:
Specifically, what is the following line of code doing:
$data[0][$row->parentid]['children'][$row->id] = $row->name;
Your function is looping through your query result set and checking if the current row specifies a parent ID. If it does it append a hash to your array of arrays (your hierarchy).
foreach ($Q->result() as $row) {
Your query result is a collection of row objects. Each object appears to have an attribute for each column being selected in your SQL query. So for your SELECT fields:
$this->db->select('id,name,parentid');
We have:
$row->id
$row->name
$row->parentid
Going back to the original line of code:
$data[0][$row->parentid]['children'][$row->id] = $row->name;
This line is constructing a structure like this:
Array (
[0] => Array ( // $data[0]
[400] => Array ( // $data[0][$row->parentid]
[children] => Array ( // $data[0][$row->parentid]['children']
[53] => Animal // these are from [$row->id] = $row->name;
[54] => Mineral
[55] => Vegetable
)
)
[401] => Array (
[children] => Array (
[4] => Wood
[6] => Metal
[2] => Plastic
)
)
)
)
You could simplify this structure slightly by removing the first wrapper array $data[0]. So you'd change the code like so:
$data[$row->parentid]['children'][$row->id] = $row->name;
This changes the structure like so:
Array (
[400] => Array ( // $data[$row->parentid]
[children] => Array ( // $data[$row->parentid]['children']
[53] => Animal // these are from [$row->id] = $row->name;
[54] => Mineral
[55] => Vegetable
)
)
[401] => Array (
[children] => Array (
[4] => Wood
[6] => Metal
[2] => Plastic
)
)
)
I hope this clarifies the code for you.
It add a value in a array namely $row->name with the ID $row->id
So what it does is adding a child row to the parent with the ID that is in $row->parentid at that moment. It loops through the loop and add child's to the parent if the parent has child's

Resources