this is a task manager web app
i have 3 tables rows, tasks and inputs
the inputs table has order column to choice which column to be shown first
row has many tasks
input has many tasks
so every task has an input and a row
i want to sort the tasks by row_id and then by input.order
first try
App\Row::with(['user', 'tasks', 'tasks.option', 'tasks.input'])
->orderBy('rows.id', 'ASC', 'order', 'ASC')
->get();
it ignores the order
result
[
{
"id": 1,
"user_id": 1,
"created_at": "2018-06-07 18:40:23",
"updated_at": "2018-06-07 18:40:23",
"tasks": [
{
"id": 1,
"row_id": 1,
"input_id": 1,
"option_id": 1,
"value": null,
"input": {
"id": 1,
"name": "assigned to",
"type": 1,
"value": "mario",
"required": 1,
"order": 2,
"user_id": 1,
"created_at": "2018-06-07 18:40:16",
"updated_at": "2018-06-08 10:08:19"
}
},
{
"id": 2,
"row_id": 1,
"input_id": 2,
"option_id": null,
"value": "test new option",
"input": {
"id": 2,
"name": "test new option",
"type": 0,
"value": "test new option",
"required": 0,
"order": 3,
"user_id": 1,
"created_at": "2018-06-07 18:40:44",
"updated_at": "2018-06-08 10:08:19"
}
},
{
"id": 3,
"row_id": 1,
"input_id": 3,
"option_id": null,
"value": "2018-07-01",
"input": {
"id": 3,
"name": "deadline",
"type": 3,
"value": "2018-07-01",
"required": 0,
"order": 4,
"user_id": 1,
"created_at": "2018-06-08 10:07:37",
"updated_at": "2018-06-08 10:08:19"
}
},
{
"id": 4,
"row_id": 1,
"input_id": 4,
"option_id": null,
"value": "",
"input": {
"id": 4,
"name": "priority",
"type": 6,
"value": "",
"required": 0,
"order": 1,
"user_id": 1,
"created_at": "2018-06-08 10:08:19",
"updated_at": "2018-06-08 10:08:19"
}
}
]
}
]
second try
App\Row::with(['user', 'tasks', 'tasks.option', 'tasks.input'])
->orderBy('rows.id', 'ASC')
->orderBy('order', 'ASC')
->get();
but it generated an error
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'order' in 'order clause' (SQL: select * from `rows` order by `rows`.`id` asc, `order` asc)
third try
App\Row::with([
'user',
'tasks',
'tasks.option',
'tasks.input' =>
function($query) {
$query->orderBy('order', 'ASC');
}
])
->orderBy('rows.id', 'ASC')
->get();
it ignores the order result same as first
forth try
return App\Row::with(['user', 'tasks', 'tasks.option', 'tasks.input'])
->join('tasks', 'rows.id', '=', 'tasks.row_id')
->join('inputs', 'inputs.id', '=', 'tasks.input_id')
->orderBy('rows.id', 'ASC')
->orderBy( 'inputs.order', 'ASC')
->get();
it generate row for every column and not row as it suppose to
result
[
{
"id": 4,
"user_id": 1,
"created_at": "2018-06-08 10:08:19",
"updated_at": "2018-06-08 10:08:19",
"row_id": 1,
"input_id": 4,
"option_id": null,
"value": "",
"name": "priority",
"type": 6,
"required": 0,
"order": 1,
"tasks": []
},
{
"id": 1,
"user_id": 1,
"created_at": "2018-06-07 18:40:16",
"updated_at": "2018-06-08 10:08:19",
"row_id": 1,
"input_id": 1,
"option_id": 1,
"value": "mario",
"name": "assigned to",
"type": 1,
"required": 1,
"order": 2,
"tasks": [
{
"id": 1,
"row_id": 1,
"input_id": 1,
"option_id": 1,
"value": null,
"input": {
"id": 1,
"name": "assigned to",
"type": 1,
"value": "mario",
"required": 1,
"order": 2,
"user_id": 1,
"created_at": "2018-06-07 18:40:16",
"updated_at": "2018-06-08 10:08:19"
}
},
{
"id": 2,
"row_id": 1,
"input_id": 2,
"option_id": null,
"value": "test new option",
"input": {
"id": 2,
"name": "test new option",
"type": 0,
"value": "test new option",
"required": 0,
"order": 3,
"user_id": 1,
"created_at": "2018-06-07 18:40:44",
"updated_at": "2018-06-08 10:08:19"
}
},
{
"id": 3,
"row_id": 1,
"input_id": 3,
"option_id": null,
"value": "2018-07-01",
"input": {
"id": 3,
"name": "deadline",
"type": 3,
"value": "2018-07-01",
"required": 0,
"order": 4,
"user_id": 1,
"created_at": "2018-06-08 10:07:37",
"updated_at": "2018-06-08 10:08:19"
}
},
{
"id": 4,
"row_id": 1,
"input_id": 4,
"option_id": null,
"value": "",
"input": {
"id": 4,
"name": "priority",
"type": 6,
"value": "",
"required": 0,
"order": 1,
"user_id": 1,
"created_at": "2018-06-08 10:08:19",
"updated_at": "2018-06-08 10:08:19"
}
}
]
},
{
"id": 2,
"user_id": 1,
"created_at": "2018-06-07 18:40:44",
"updated_at": "2018-06-08 10:08:19",
"row_id": 1,
"input_id": 2,
"option_id": null,
"value": "test new option",
"name": "test new option",
"type": 0,
"required": 0,
"order": 3,
"tasks": []
},
{
"id": 3,
"user_id": 1,
"created_at": "2018-06-08 10:07:37",
"updated_at": "2018-06-08 10:08:19",
"row_id": 1,
"input_id": 3,
"option_id": null,
"value": "2018-07-01",
"name": "deadline",
"type": 3,
"required": 0,
"order": 4,
"tasks": []
}
]
this file is here
the full code is here
Because it searches columns in table rows not in input.
App\Row::with(['user', 'tasks', 'tasks.option', 'tasks.input'=> function ($q){
$q->orderBy('order', 'ASC'); // order from "rows" table
}])
->orderBy('id', 'ASC') // id from "rows" table
->get();
Related
I got a collection but I want to sort that collection. If the two application's cgpa is equal then sort the list collection according to the annual_salary where lower will up at list. Default the collection sort with the cgpa. below is my server response.
Thanks in advance
"applications": [
{
"id": 1,
"name": "Dr. W Khan",
"annual_salary": 5000,
"created_at": "2022-11-07T19:16:01.000000Z",
"updated_at": "2022-11-07T19:16:01.000000Z",
"education": [
{
"id": 1,
"application_id": 1,
"name": "HSC",
"cgpa": 400,
"created_at": "2022-11-07T19:16:01.000000Z",
"updated_at": "2022-11-07T19:16:01.000000Z"
}
]
},
{
"id": 2,
"name": "Dr. M Khan",
"annual_salary": 7000,
"created_at": "2022-11-07T19:16:14.000000Z",
"updated_at": "2022-11-07T19:16:14.000000Z",
"education": [
{
"id": 2,
"application_id": 2,
"name": "HSC",
"cgpa": 350,
"created_at": "2022-11-07T19:16:14.000000Z",
"updated_at": "2022-11-07T19:16:14.000000Z"
}
]
},
{
"id": 3,
"name": "Dr.",
"annual_salary": 5000,
"created_at": "2022-11-07T19:16:28.000000Z",
"updated_at": "2022-11-07T19:16:28.000000Z",
"education": [
{
"id": 3,
"application_id": 3,
"name": "HSC",
"cgpa": 350,
"created_at": "2022-11-07T19:16:28.000000Z",
"updated_at": "2022-11-07T19:16:28.000000Z"
}
]
}
]
This is the query for me.
$application = Application::with(
[
'education' => function ($query) {
$query->orderBy('cgpa', 'desc');
},
]
)
->orderBy('annual_salary', 'asc')
->get();
But ordering the list followed by a second orderBy.
In my case the json will be different every time and i have to make widget like "inputtype": "dropdown", "inputtype": "radiobutton" but if i craete model it don't go as i wants it to.
{
"fields": [
{
"id": 31,
"name": "make",
"isrequired": "required",
"valuetype": "text",
"priority": 1,
"inputtype": "dropdown",
"max_min": [],
"rangeable": "false",
"choices": [
{
"id": 46,
"name": "Samsung",
"categoryextrafield_id": 31,
"created_at": "2021-12-29T01:30:47.000000Z",
"updated_at": "2021-12-29T01:30:47.000000Z",
"priority": 10
},
{
"id": 47,
"name": "Dell",
"categoryextrafield_id": 31,
"created_at": "2021-12-29T01:30:52.000000Z",
"updated_at": "2021-12-29T01:30:52.000000Z",
"priority": 20
},
{
"id": 48,
"name": "IBM",
"categoryextrafield_id": 31,
"created_at": "2021-12-29T01:31:09.000000Z",
"updated_at": "2021-12-29T01:31:09.000000Z",
"priority": 30
},
{
"id": 49,
"name": "Acer",
"categoryextrafield_id": 31,
"created_at": "2021-12-29T01:31:24.000000Z",
"updated_at": "2021-12-29T01:31:24.000000Z",
"priority": 40
}
],
"available": []
},
{
"id": 32,
"name": "model",
"isrequired": "required",
"valuetype": "text",
"priority": 2,
"inputtype": "textfield",
"max_min": [],
"rangeable": "false",
"choices": [],
"available": [
{
"model": "a51"
},
{
"model": "y9s"
},
{
"model": "a31"
},
{
"model": "yS10"
},
{
"model": "Y10S"
},
{
"model": "A551"
},
{
"model": "node8"
},
{
"model": "s9"
},
{
"model": null
},
{
"model": "2021"
},
{
"model": "2020"
},
{
"model": "2010"
},
{
"model": "Civic"
},
{
"model": "2019"
},
{
"model": "Daewooy9"
},
{
"model": "corei5"
},
{
"model": "corei9"
},
{
"model": "corei3"
},
{
"model": "corei11"
}
]
},
{
"id": 29,
"name": "features",
"isrequired": "required",
"valuetype": "text",
"priority": 3,
"inputtype": "checkbox",
"max_min": [],
"rangeable": "false",
"choices": [
{
"id": 41,
"name": "Bluetooth",
"categoryextrafield_id": 29,
"created_at": "2021-12-29T01:19:00.000000Z",
"updated_at": "2021-12-29T01:19:00.000000Z",
"priority": 1
},
{
"id": 42,
"name": "Fingerprint",
"categoryextrafield_id": 29,
"created_at": "2021-12-29T01:19:10.000000Z",
"updated_at": "2021-12-29T01:19:10.000000Z",
"priority": 10
},
{
"id": 43,
"name": "LedDisplay",
"categoryextrafield_id": 29,
"created_at": "2021-12-29T01:19:35.000000Z",
"updated_at": "2021-12-29T01:19:35.000000Z",
"priority": 15
}
],
"available": []
},
{
"id": 30,
"name": "condition",
"isrequired": "required",
"valuetype": "text",
"priority": 4,
"inputtype": "radiobutton",
"max_min": [],
"rangeable": "false",
"choices": [
{
"id": 44,
"name": "Used",
"categoryextrafield_id": 30,
"created_at": "2021-12-29T01:20:31.000000Z",
"updated_at": "2021-12-29T01:20:31.000000Z",
"priority": 10
},
{
"id": 45,
"name": "New",
"categoryextrafield_id": 30,
"created_at": "2021-12-29T01:20:38.000000Z",
"updated_at": "2021-12-29T01:20:38.000000Z",
"priority": 20
}
],
"available": []
}
]
}
I have like this database scheme:
Schema::create('messages', function (Blueprint $table) {
$table->id();
$table->foreignId('user_id')
->constrained()
->onDelete('cascade');
$table->unsignedBigInteger('sender_id');
$table->foreign('sender_id')->references('id')->on('users');
$table->text('message');
$table->foreignId('message_id')
->nullable()
->constrained()
->onDelete('cascade');
$table->tinyInteger('status')->default(0);
$table->tinyInteger('view_status')->default(0);
$table->timestamps();
});
I tried get two user conversation like this:
$user = auth()->user();
$conversations = Message::where([
['user_id', $user->id],
])->orWhere([
['sender_id', $user->id],
])->groupBy('sender_id', 'user_id')->latest()->get();
But result is wrong and not grouping users conversation.
Here is simple data:
My query result currently:
[
{
"id": 3,
"user_id": 1,
"sender_id": 2,
"message": "How are you? 😀",
"message_id": null,
"status": 0,
"view_status": 0,
"created_at": "2021-08-17T08:18:03.000000Z",
"updated_at": "2021-08-17T08:18:03.000000Z",
"user": {
"id": 1,
"name": "John Doe"
},
"sender": {
"id": 2,
"name": "Nicolas Smith"
}
},
{
"id": 2,
"user_id": 2,
"sender_id": 1,
"message": "Hello",
"message_id": null,
"status": 0,
"view_status": 1,
"created_at": "2021-08-17T07:25:18.000000Z",
"updated_at": "2021-08-17T08:19:09.000000Z",
"user": {
"id": 2,
"name": "Nicolas Smith"
},
"sender": {
"id": 1,
"name": "John Doe"
}
},
{
"id": 1,
"user_id": 3,
"sender_id": 2,
"message": "Hi",
"message_id": null,
"status": 0,
"view_status": 0,
"created_at": "2021-08-16T23:44:17.000000Z",
"updated_at": "2021-08-16T23:44:17.000000Z",
"user": {
"id": 3,
"name": "Richard"
},
"sender": {
"id": 2,
"name": "Nicolas Smith"
}
}
]
How I can group by correctly?
i have the following Template model and TestCategory hasMany Test:
class Template extends Model
{
protected $table = 'test_templates';
protected $fillable = [
'customers_id',
'tests_categories_id',
'tests_id'
];
public function customers(){
return $this->belongsTo(Customer::class, 'customers_id');
}
public function testCategories(){
return $this->belongsTo(TestCategory::class, 'tests_categories_id');
}
public function tests(){
return $this->belongsTo(Test::class, 'tests_id');
}
}
And I have the following index method defined in TemplateController
public function index($customerId)
{
$templates = Template::with( 'customers','testCategories','tests')
->where('customers_id', $customerId)->get();
$templates = $templates->groupBy('tests_categories_id');
$templates = json_decode($templates, true);
$templates = array_values($templates);
return response()->json(['Status' => True, 'template' => $templates]);
}
I got the following json output:
{
"Status": true,
"template": [
[
{
"id": 1,
"customers_id": 1,
"tests_categories_id": 1,
"tests_id": 1,
"created_at": "2018-09-10 11:03:44",
"updated_at": "2018-09-10 11:03:44",
"customers": {
"id": 1,
"name": "Queen PVT.Ltd",
"address": "gotham",
"contact_number": "9842********",
"created_at": "2018-09-10 11:03:43",
"updated_at": "2018-09-10 11:03:43"
},
"test_categories": {
"id": 1,
"name": "General Tests",
"created_at": null,
"updated_at": null
},
"tests": {
"id": 1,
"tests_category_id": 1,
"name": "Lamination",
"created_at": null,
"updated_at": null
}
},
{
"id": 2,
"customers_id": 1,
"tests_categories_id": 1,
"tests_id": 2,
"created_at": "2018-09-10 11:03:44",
"updated_at": "2018-09-10 11:03:44",
"customers": {
"id": 1,
"name": "Queen PVT.Ltd",
"address": "gotham",
"contact_number": "984*******",
"created_at": "2018-09-10 11:03:43",
"updated_at": "2018-09-10 11:03:43"
},
"test_categories": {
"id": 1,
"name": "General Tests",
"created_at": null,
"updated_at": null
},
"tests": {
"id": 2,
"tests_category_id": 1,
"name": "Paper Type",
"created_at": null,
"updated_at": null
}
}
],
[
{
"id": 7,
"customers_id": 1,
"tests_categories_id": 2,
"tests_id": 8,
"created_at": "2018-09-10 11:03:44",
"updated_at": "2018-09-10 11:03:44",
"customers": {
"id": 1,
"name": "Queen PVT.Ltd",
"address": "gotham",
"contact_number": "984******",
"created_at": "2018-09-10 11:03:43",
"updated_at": "2018-09-10 11:03:43"
},
"test_categories": {
"id": 2,
"name": "Scratch Test",
"created_at": null,
"updated_at": null
},
"tests": {
"id": 8,
"tests_category_id": 2,
"name": "HRN Visibility",
"created_at": null,
"updated_at": null
}
}
]
]
}
I want to collect all the tests as per the test_categories without reprinting customers and test_categories as following:
{
"Status": true,
"template": [
[
{
"id": 1,
"customers_id": 1,
"tests_categories_id": 1,
"tests_id": 1,
"created_at": "2018-09-10 11:03:44",
"updated_at": "2018-09-10 11:03:44",
"customers": {
"id": 1,
"name": "Queen PVT.Ltd",
"address": "gotham",
"contact_number": "984*****",
"created_at": "2018-09-10 11:03:43",
"updated_at": "2018-09-10 11:03:43"
},
"test_categories": {
"id": 1,
"name": "General Tests",
"created_at": null,
"updated_at": null
},
"tests": {
{
"id": 1,
"tests_category_id": 1,
"name": "Lamination",
"created_at": null,
"updated_at": null
},
{
"id": 2,
"tests_category_id": 1,
"name": "Paper Type",
"created_at": null,
"updated_at": null
}
}
}
],
[
{
"id": 7,
"customers_id": 1,
"tests_categories_id": 2,
"tests_id": 8,
"created_at": "2018-09-10 11:03:44",
"updated_at": "2018-09-10 11:03:44",
"customers": {
"id": 1,
"name": "Queen PVT.Ltd",
"address": "gotham",
"contact_number": "984265*****",
"created_at": "2018-09-10 11:03:43",
"updated_at": "2018-09-10 11:03:43"
},
"test_categories": {
"id": 2,
"name": "Scratch Test",
"created_at": null,
"updated_at": null
},
"tests": {
{
"id": 8,
"tests_category_id": 2,
"name": "HRN Visibility",
"created_at": null,
"updated_at": null
}
}
}
]
]
}
If I understand the problem correctly the tests are being separated into different templates when you are expecting some of them to be related to the same template.
This is because your Template class is storing the test_id that it belongs to and it can only store 1 test per Template. So when you are calling Template::with('tests') it can only return one Test::class.
Because you expect to see that many Tests belongTo one Template, and when you look at the relationship from the Template to Test, you expect that a Template has many Tests. Therefore, your Template class should implement the hasMany relationship like so:
class Template extends Model
{
protected $fillable = [
'customers_id',
'tests_categories_id' // notice the removal of the test_id which should also be removed from the test_templates migration
];
...
public function tests(){
return $this->hasMany(Test::class); //change belongsTo to hasMany
}
...
}
Instead of storing the test_id on the Template class you should be storing the template_id on your Test class and look something like so:
class Test extends Model
{
protected $fillable = [
...
'test_template_id' // This should be added to $fillable and the tests migration
...
];
...
public function template(){
return $this->belongsTo(Template::class, test_template_id);
}
...
}
Now when you call Template::with('tests') it can return many Test::class and should match your expected output.
I work on a laravel application that is a bit like a quiz. You create an exercise, you add questions and each question to answers.
Until then everything is fine.
My interest is to present statistics for each exercise after schoolchildren have answered the tests.
I want to be able to display the answer percentage for each question.
Here is an example of the data structure I have:
[
{
"id": 1,
"exercice_id": 1,
"question": "Lorem ipsum ?",
"responses": [
{
"id": 1,
"exercice_id": 1,
"question_id": 1,
"response_text": "Yes",
},
{
"id": 2,
"exercice_id": 1,
"question_id": 1,
"response_text": "No",
}
],
"choice": [
{
"id": 1,
"exercice_id": 1,
"question_id": 1,
"response_id": 1,
},
{
"id": 2,
"exercice_id": 1,
"question_id": 1,
"response_id": 1,
},
{
"id": 3,
"exercice_id": 1,
"question_id": 1,
"response_id": 2,
}
]
},
{
"id": 2,
"exercice_id": 1,
"question": "fake text ?",
"responses": [
{
"id": 3,
"exercice_id": 1,
"question_id": 2,
"response_text": "A",
},
{
"id": 4,
"exercice_id": 1,
"question_id": 2,
"response_text": "B",
},
{
"id": 5,
"exercice_id": 1,
"question_id": 2,
"response_text": "C",
}
],
"choice": [
{
"id": 4,
"exercice_id": 1,
"question_id": 2,
"response_id": 5,
},
{
"id": 5,
"exercice_id": 1,
"question_id": 2,
"response_id": 3,
}
]
}
]
I tried the groupBy method on several elements. but I have not found the formula yet.
return response()->json(Question::with('responses','choice')
->where('exercice_id',$exo->id)
//->groupBy('choice')
->get(),
200,[], JSON_NUMERIC_CHECK);