GroupBy and Count - laravel - php

In my application, i send out surveys and group and count similar and non-similar responses. This is how my group and count is working now
NB: Take this instance as if the survey was answered by 2 clients.
Client 1 and Client 2 both selected Good for question 1
Responses
question Ans
How would you describe my services? Good (2)
How would you describe my services? Good (2)
Gender Male(1)
Gender Female(1)
How can take out the redundancy. the question repeats itself and also, when the answers repeat itself with the count.
Responses
question Name Ans
How would you describe my services? Good (2)
Gender Male(1), Female(1)
Model
public function count_answers()
{
return $this->hasMany(Answer::class)->select('answer', DB::raw('count(*) as counter'))->groupBy('answer');
}
View
#forelse ($data->questions as $item)
#foreach ($item->answers as $answer)
<tr>
<td width="30%">{{ $item->title }}</td>
<td>
#foreach ($item->count_answers as $answer)
<div>{{$answer->answer}} ({{$answer->counter}})</div>
#endforeach
</td>
</tr>
#endforeach
Controller
public function view_survey_response(Survey $data)
{
$data = Survey::where('id', $data->id)->where('user_id', Auth::user()->id)->first();
return view('answer.response', compact('data'));
};

Related

Dynamic column/attribute. Stuck. Need inspiration

i’m looking for a solution to a problem that I’m having for a while now. Maybe you can inspire me to do this better. I’m trying not to make a basic mistake in the planning process therefore I’m asking you for advice.
I’m having a Contact::model which has few fixed attributes like id etc. Additionally I would like to have different attributes created dynamically for the whole Contact::model. Some user will be given the functionality to add attributes like name, email, address to the whole model. I’ve dropped the idea of programmatically updating the table itself by creating/dropping columns (this would introduce different problems). As for now i've created two additional tables. One with the additional column names [Columns::model] and a pivot table to assign the value to a Contact::model and Column::model.
To list all contacts i’m preparing the ContactColumn table as array where the first key is the contact_id and the second is the column_id, therefore i get the value. This introduces the n+1 issue. This would not be that bad, but with this approach it will be extremely hard (or resource consuming) to order the contacts by dynamic column values, filtering, searching etc.
Can you somehow guide me to a better solution. How can i merge the contact collection with the values for given columns so it looks like it was a fixed table?
<table>
<thead>
<tr>
<th>Fixed columns [i.e. ID]</th>
#foreach ($columns as $column)
<th>{{ $column->name }}</th>
#endforeach
</tr>
</thead>
<tbody>
#foreach ($contacts as $contact)
<tr>
<td>{{ $contact->id }}</td>
#foreach ($columns as $column)
<td>
#if (array_key_exists($column->id, $values[$contact->id]))
{{ $values[$contact->id][$column->id] }}
#endif
</td>
#endforeach
</tr>
#endforeach
</tbody>
</table>
And the $value array.
foreach (ColumnContact::all() as $pivot) {
$values[$pivot->contact_id][$pivot->column_id] = $pivot->value;
}
return $values;
Edit: I've solved it like this
$this->contacts = Contact::when($this->dynamicColumnName, function($query) {
$query->join('column_contact', function ($join) {
$join->on('id', '=', 'column_contact.contact_id')
->where('column_contact.column_id', '=', $this->dynamicColumnName->id);
})
->orderBy('value', $this->orderingDirection);
})
(...)
->paginate(self::PER_PAGE);
Apart from the fixed fields, add an extra JSON field in your schema called 'custom_fields'. Have a look into => https://github.com/stancl/virtualcolumn
Separate table for custom fields is not a good idea because then you have to handle model events separately and so on.

How to display array of authors in laravel view file

I'm trying to display authors.where some books have one author and some books have 2 authors. How to manipulate this scenario
here is my html code
#foreach($books as $book)
<tr>
#if (json_encode($book['author']) !== 1 )
<td>{{{ json_decode(json_encode($book['author'][0]),true) }}} &
{{{ json_decode(json_encode($book['author'][1]),true) }}}</td>
#else
<td>{{{ $book['author'][0] }}}</td>
#endif
</tr>
But It is displaying only 2 authors but not single author.Any help or suggestions that would be appericated
Thanks In advance
I don't know how you have your tables setup but if authors are on a separate table as they should with a hasMany relation you should do this(assuming your relations are well formed)
Book Model, you described a One to Many relation between Books and Authors so you should use something like this:
public function authors()
{
return $this->hasMany('App\Author');
}
#foreach ($books as $book) :
#foreach($book->authors as $author) :
// do whatever you wish with all the authors here
#endforeach
#endforeach

Undefined property in Laravel 5

I've looked at other questions that have answered this same error and I understand I have a property that cannot be defined but not sure how to make it defined. First time using Many-to-Many relationship so I'm assuming this is the issue.
Project Table
id
company
stage
status
date_started
date_finished
timestamps
Employee Table
id
name
department
timestamps
Employee_Project Table
id
employee_id
project_id
In both models, I have belongsToMany and for the show function in the ProjectController, I have:
$projects = Project::find($id);
In the view, I want to show company name ($projects->company) and the employees on that project with their respective departments. These do not work:
$projects->employees->name
$projects->employees->department
How do I access these properties?
--Update--
Jeff's answer works but I set up a table like
<thead><th>PM</th><th>AM</th></thead>
<tbody><td>#if($employee->department == 'Project Manager'){{ $employee->name }}</td>
<td>#else($employee->department == 'Account Manager'){{ $employee->name }}</td></tbody>#endif
and this does not work to show the correct employees in their respective sections. Any ideas how to fix this?
Your problem is that $project->employees is a collection, not an individual instance of an employee. You will need to iterate over the collection in order to access each individual employee's name:
foreach($project->employees as $employee) {
echo $employee->name;
echo $employee->department;
}
Update
It looks like you may need to restructure as below, I think you probably want the entire if construct to be within the same table cell, though I could be wrong:
<tbody>
#foreach($project->employees as $employee)
<tr>
<td>
#if($employee->department == 'Project Manager')
{{ $employee->name }}
#elseif($employee->department == 'Account Manager')
{{ $employee->department }}
#else
<!-- What about non project/account managers? -->
#endif
</td>
</tr>
#endforeach
</tbody>
I could be totally wrong, and maybe you want account managers and project managers in different columns:
<tr>
<td>
#if($employee->department == 'Project Manager')
{{ $employee->name }}
#endif
</td>
<td>
#if($employee->department == 'Account Manager')
{{ $employee->name }}
#endif
</td>
</tr>
Be sure to take a look at the documentation on Blade if statements.
Update 2
If you want to order how the related entities are coming back, you can do something like this (assuming you want the employees ordered by their department:
$project->employees()->orderBy('department', 'DESC')->get();
Notice you're no longer accessing the property, you're calling the relation method employees() so that you can modify the query prior to it being executed.
Here's a link to the documentation on ordering queries, and there is also another StackOverflow question on it.
So I figured out how to show the correct person to show up under their respective departments in the table and I wanted to share.
Thanks to #jeff-lambert I added the foreach loop but I had added to the entire row like in his first update. This did not work because the employees were not showing up in their respective departments. For example, account managers were showing up under the project manager . To resolve this, I had to add a foreach loop to each .
<td>
#foreach($projects->employees as $employee)
#if($employee->department == 'Project Manager')
{{ $employee->name }}
#endif
#endforeach
</td>
Hope this helps explain it.

Laravel 4 - nested results

I am new to php and larval. I have the following database tables questions and answers. Each question can have multiple answers with the corrected one indicated in the correct answer field. I am trying to list out the question with the answers following like this
this is the question....
a. first answer
b. second answer
c. third answer
d. fourth answer
I have the following code:
public static function getMultipleChoiceQuestions($chapter)
{
$data = DB::table('newQuestions')
->join('newAnswers', 'newQuestions.questionId', '=', 'newAnswers.questionId')
->where('chapterId', '=', $chapter)->orderBy('newQuestions.questionId')
->where('questionType', '=', "1")
->get();
$questions = array('questionType' => $questionType, 'data' => $data);
return $questions;
}
question table:
chapterId
questionId
questionText
answer table:
answerId
questionId
answerText
correctAnswer
The following code displays the question for each answer.
<fieldset id="group_1">
<p><div><input type="checkbox" class="checkall"> Check all</div></p>
<div style="width:600px; height:300px; overflow: auto;">
#foreach($questions['data'] as $question)
<p><input name="your_name" value="{{ $question->questionId }}" id="{{ $question->questionId }}" type="checkbox" class="questionsOnPage" />
{{ $question->questionText }}</p>
#endforeach
</div>
</fieldset>
I would like to list question then answers then next question.
Please help!
I think you need to take a further look at Eloquent. You should be able to do something like this.
Here is how you would set up the relationship. Based on this, your answers table name needs to be answers, and it needs a column named question_id. Although, you can go through the docs to learn how to set custom table names and column names.
app/models/Question.php
class Question extends Eloquent {
public function answers()
{
return $this->hasMany('Answer');
}
}
app/models/Answer.php
class Answer extends Eloquent {
public function question()
{
return $this->belongsTo('Question')
}
}
Now, once those relationships are set like that, we can really use Eloquent. You can do something like this in your view quite easily with blade.
The outer foreach will loop through each question. The the inner foreach will display each answer that belongs to that current question, then move on to the next question.
#foreach(Question::all() as $question)
<h3>{{ $question->title }}</h3>
<ul>
#foreach($question->answers->all() as $answer)
<li>{{$answer->text}}</li>
#endforeach
</ul>
#endforeach
The title and text property you see there, simply need to be the column names you have in your database. You should change those to match yours.
Using the example above, you should be able to style it how you want and place it in a form. Right now it will display the question within an h3 tag, then a unordered list with the answers below that.

relationship and blade in laravel

I have 3 table as mentioned below.
Table 1(user):
id username password Name Age
Table 2(tasks):
id task_name description
Table 3(logs)
id user_id task_id date hours
Table Relationships:
user has_many logs
task has_many logs
logs belongs_to user
logs belongs_to task
what i am trying to achieve is to get the logs with the user Name, task Name, date and hours.
Controller:
return View::make('log.index')
->with('logs',log::all());
Blade template
#foreach($logs as $log)
<tr>
<td>{{$log->id}}</td>
<td>{{$log->users()->name}}</td>
<td>{{$log->tasks()->name}}</td>
<tr>
#endforeach
but unable to fetch users Name and Tasks name from the respective table. any help is appreciated.
A better way is to define inverse hasMany relation in your Model, as documented here
So in your logs model, probably you need to define:
class Log extends Eloquent {
protected $table = "logs";
public function user(){
return $this->belongsTo('User');
}
public function task(){
return $this->belongsTo('Task');
}
}
Then in your view you can either use :
$log->user()->first()->name
or even better, by using Dynamic Properties:
$log->user->name
$log->users() and $log->tasks() returns a query object. Below, each call returns the result which is the same as calling $log->users()->get() and $log->tasks()->get(). Because the relationships are many to many, you'll need to iterate over $log->users and $log->tasks to retrieve each record.
#foreach($logs as $log)
<tr>
<td>{{$log->id}}</td>
<td>
#foreach($log->users as $user)
{{$user->name}},
#endforeach
</td>
<td>
#foreach($log->tasks as $task)
{{$task->name}},
#endforeach
</td>
<tr>
#endforeach
If you want a specific user/task attached to a log you'll have to build a query.
#foreach($logs as $log)
<tr>
<td>{{$log->id}}</td>
<td>{{$log->users()->where('id', '=', $userID)->first()->name}} </td>
<td>{{$log->tasks()->where('id', '=', $taskID)->first()->name}} </td>
<tr>
#endforeach

Categories