Hi im trying to query my tasks table. A little background information on the tables and how they are related.
Users, create Projects and Tasks, Statuses for projects and tasks can be selected from the status table, users make their own, i plan to have default ones but users may want to create their own.
By default i want to find all the users tasks where the status_name which is held in the statuses table does not equal closed. I decided it would be best to actually create a table called task_status which holds the task_id as well as the status_id. I still want to find the logged in users tasks and then find the status name based on the status_id held in the tasks table, which can be referenced in the statuses table. I then want to only display the any records not equal to closed but the first part which is explained below is trickier than first anticipated.
My table structures can be found below:
Table structure
Users
id | username | email
Tasks
id | user_id | client_id | project_id | status_id | task_name | task_brief
Statuses
id | status_name
Projects
id | user_id | client_id | status_id | type_id | project_name | project_brief
task_status
id | user_id | task_id | status_id
I'm trying to query my db simply first so that I can be sure that the data returned is correct. So I've changed my query to the below:
$user = User::with(array('tasks', 'task.status', 'tasks.taskstatus',
'tasks.clients'))->find(Auth::user()->id);
and I'm trying to return as follows (please bear in mind I also want to query the status table so that I am able to return the name of the status):
#foreach($user->tasks as $task)
{{ $task->task_name }}
#if(!is_null($task->clients))
{{ $task->clients->client_code }}
#endif
#if(!is_null($task->taskstatus))
{{ $task->taskstatus->status_name }}
#endif
#endforeach
My models:
Task.php
public function status(){
return $this->hasOne('Status', 'status_id');
}
public function taskstatus() {
return $this->hasMany('TaskStatus', 'status_id');
}
Status.php
public function tasks()
{
return $this->hasMany('Task');
}
public function taskstatus()
{
return $this->hasMany('TaskStatus', 'status_id');
}
TaskStatus.php
public function tasks()
{
return $this->hasMany('Task', 'task_id');
}
public function status() {
return $this->belongsTo('Status', 'status_id')
}
However using the above returns the following error:
SQLSTATE[42S02]: Base table or view not found: 1146 Table
'imanage.task_statuses' doesn't exist (SQL: select * from `task_statuses`
where `task_statuses`.`status_id` in (?, ?, ?, ?, ?, ?, ?))
(Bindings: array ( 0 => 1, 1 => 2, 2 => 3, 3 => 4, 4 => 5, 5 => 6, 6 => 7, ))
I'm sure that its my relationships that are defined incorrectly but I am not sure how to correct these.Can anyone help?
You can also try this code:
$user = User::whereHas('task.status', function($q)
{
$q->where('status', '!=', 'close');
})
->with('task', 'task.clients')
->where('id', Auth::user()->id)
->first();
Check the eloquent docs on querying relationships.
also remember DO NOT ECHO VIEW, return the view instead.
The error seems related to the fact that Laravel (well, actually Eloquent) is getting the wrong table name: below you have task_statuses instead of task_status. Remember that Eloquent will attempt to pluralize named models to get the table name.
SQLSTATE[42S02]: Base table or view not found: 1146 Table
'imanage.task_statuses' doesn't exist
So either rename your table to match Laravel expectations, or in your model specify a custom table name:
class TaskStatus extends Eloquent {
protected $table = 'task_status';
...
Additionally, this part of your code is unclear to me:
Task.php
public function status(){
return $this->hasOne('Status', 'status_id');
}
public function taskstatus() {
return $this->hasMany('TaskStatus', 'status_id');
}
Does your Task have one status, or does it have many statuses?
Related
So, I have a legacy Database, with a poorly designed structure that has recently been moved to Laravel, but with some hacky nonsense to get it to work with models. Given the following Tables:
|==========================|====|============|===========|
| companies | id | token | name |
|--------------------------|----|------------|-----------|
| people_{companies.token} | id | first_name | last_name |
|==========================|====|============|===========|
The companies table contains multiple records, with an auto-incrementing ID, unique token, and name.
Each Company has its own people_{companies.token} table, instead of a single people table, with an associated client_id.
At first, this meant I couldn't use a standard Company and Person Model/Relationships, as protected $table needs to be static. We got around this with a DynamicBinding Trait:
<?php
namespace App\Models\Traits;
trait DynamicBinding {
protected $connection = null;
protected $table = null;
public function bind(string $connection, string $table) {
$this->setConnection($connection);
$this->setTable($table);
}
public function newInstance($attributes = [], $exists = false) {
$model = parent::newInstance($attributes, $exists);
$model->setTable($this->table);
return $model;
}
}
This allows for setting a table on the fly:
$company = Company::first();
$people = (new Person())->setTable("people_{$company->token}");
$person = $people->first();
This works perfectly fine, returning the first record from the people_{$company->token} table, and facilitating most functionality required. Now, I'd like to make this work with Relationships. Given the following example:
// Person.php
public function company() {
return $this->belongsTo(Company::class);
}
$company = Company::first();
$people = (new Person())->setTable("people_{$company->token}");
$person = $people->first(); // No Issue
$peopleWithCompany = $people->with('company')->first(); // Cannot find table `people`
This returns the error:
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'database.people' doesn't exist (SQL: select * from people limit 1)
Essentially, as soon as ->with() (or other functions, like ->query(), etc) is appended, it tries to perform the query based on the determined table (people from Person) instead of the table set via $people->setTable().
Does anyone have any experience connecting models to this kind of data structure, while allowing use of Eager Loading with Relationships? And sidenote, there is a plan to migrate everything to a single people table, but unfortunately not anytime soon...
Thanks in advance!
I have a Laravel backend and a VueJS frontend.
I'm trying to produce a query on a model with a hasOne relationship but only select specific columns from the relationship, do a sum and a group by.
Models
Contract (CONTRACT_TYPE, CONTRACT_PRICE)
AdditionalInfo (START_DATE)
My Eloquent Query
public function contractsByYear() {
return Contract::where('CONTRACT_TYPE','LIKE','SP-%')->with(['AdditionalInfo' => function($query) {
$query->selectRaw('MONTH(START_DATE) as Month')->whereYear('START_DATE','2019');
}])->sum('CONTRACT_PRICE')->groupBy('Month');
}
Expected Results
MONTH | TOTAL
1 | 500
2 | 233
3 | 800
etc
My issue is the table structure is existing and I can't edit. Why the START_DATe is stored in a separate table is beyond me.
Collection methods will probably do what you want
public function contractsByYear()
{
return Contract::select('id', 'CONTRACT_PRICE') /* Only really need the id (or whatever else is the pk) and the price */
->where('CONTRACT_TYPE','LIKE','SP-%')
->with(['AdditionalInfo' => function($query) {
$query->select('id', 'contract_id') /* Only really need the id (or whatever else is the pk), and the Contract fk*/
->selectRaw('MONTH(START_DATE) as Month') /* Aggregate the month */
->whereYear('START_DATE','2019');
}])
->get()
// From this point on, it's a Collection
->groupBy('AdditionalInfo.*.Month') /* It's either this or 'AdditionalInfo.Month' */
->map(function($item, $key) {
return [
'month' => $key,
'total' => $item->sum('CONTRACT_PRICE')
];
});
}
I have two models: Report and User. This is what I have in my User model
public function userReport() {
return $this->hasMany('App\Report', 'user_id','id');
}
And this is in Report model
public function user() {
return $this->hasOne('App\User', 'id', 'user_id');
}
Controller
public function details( $item_id ){
$report = Item::find($item_id)->report;
return view('details', compact('report'));
}
In view
{!! $report->user->name !!}
In view I show all the users who are reported single Item .. which I query by $item_id.
The problem is that if same user is reported single item 1+ time I see this user 1+ time in the table on the page.
Is it possible to somehow grouped by user_id or count the user_id and show User1 ( 4 time reported ) ...? Where should I group them?
Update: users table
id | username | password
reports table
report_id | id | user_id | date
item table
id | user_id | category | date_added | image
Update2: Image of records in db. Here user with user_id=3 has reported item_id=14 total of 14 times. User with user_id=5 has reported same item_id=14 total of 3 times. So I should see on page user_id=3 ( 14 ) and user_id=3 ( 3 ). Instead I see 17 times user_id=3. Bellow are images
And on page
There should be several ways how to solve your problem
One way is (your controller should look like)
public function details( $item_id ){
$report = Item::find($item_id)->report->unique('user_id');
return view('details', compact('report'));
}
Second way should be to use #foreach in view and there check for unique values.
Third way should be to use foreach in controller and prepare unique data with calculated summarizes inside controller and then pass that prepared data to view.
Which soulution you want to use is just a matter of choice.
Hope it helps you
Just try this. Hope it helps
Report::where('item.id', $item_id)
->select('item.*','users.*',DB::raw('count(reports.report_id) as total'))
->join('item', 'item.id', '=', 'reports.id')
->join('users', 'users.id', '=', 'reports.user_id')
->groupBy('reports.report_id','reports.id')
->get();
I have two tables 1)users
{ id, password }
2)expertise { id, expertise}
the relationship I have is
Models
Expertise.php
function User()
{
$this->hasOne('Expertise');
}
User.php
function Expertise()
{
$this->hasOne('User');
}
So how can I query using Eloquent to get the first 10 users with a certain expertise?
I want to join users.id = expertise.id and get the first 10 people with a specified expertise (Where clause).
Beginner to laravel, I've checked other sources but was not successful
Right now you are having a problem with the way that you modeled your data. If you have a one-to-one relationship the best practice to model it is to have one entity store the id of the other. The Laravel convention for this is to have a column named <model>_id:
Users
| id | password |
Expertises
| id | expertise | user_id |
Then in your models you can do this:
Models
Expertise.php
class Expertise extends Eloquent
{
public function User()
{
// because expertise has a column user_id
// expertise belongs to user
return $this->belongsTo('User');
}
}
User.php
class User extends Eloquent
{
public function Expertise()
{
// because expertise is the one with the column
// user_id, user has one expertise
return $this->hasOne('Expertise');
}
}
The Query
After you have all this set up, to be able to query the first 10 users with a certain expertise you can do this.
$users = User::whereHas('Expertise', function($q)
{
$q->where('expertise', '=', <expertise you are looking for>)
})
->take(10)
->get();
To get a further reading in querying relationships in Laravel please take a look at this:
Laravel - Querying Relationships
Keep in mind
keep in mind that the tables name must be plural, if not then you should specify the name of the table inside the model:
protected $table = 'expertise';
I'm trying to get my head around laravel models & one to many...
I have the following tables
ww_bookings
-----------------------------
booking_id
customer_id
quote_id
ww_quotes
-----------------------------
quote_id
etc
etc
etc
I'm using sentry for my auth and basically on a sucsessful login I want to find the id of the logged in user and then query the ww_bookings data WHERE customer_id = 'logged in user id'.
Once it's good all the bookings for the customer_id it then need to go and query ww_quotes for each booking found and bring back the data.
//Controller
BookingData::find(1)->quotes()->where('quote_id', '=', '1')->get();
//BookingData Model
class BookingData extends Eloquent {
protected $table = 'ww_bookings';
protected $primaryKey = 'customer_id';
public function quotes() {
return $this->hasMany('QuoteData');
}
}
//QuoteData Model
class QuoteData extends Eloquent {
protected $table = 'ww_quotes';
}
I get the following error:
Column not found: 1054 Unknown column 'ww_quotes.booking_data_id' in 'where clause' (SQL: select * from ww_quotes where ww_quotes.booking_data_id = 1 and quote_id = 1)
Can anyone help me out, it's been driving me crazy...
Hope it makes sense..
There are two problems I see:
Wrong relationship
The problem is that ww_quotes schema/table should contain key that refers ww_booking schema/table - exactly in reverse.
Solution to this:
ww_bookings
-----------------------------
customer_id
quote_id
ww_quotes
-----------------------------
quote_id
booking_id
Key will not match
Key names that Eloquent generates and uses for relations will not match existing key names. If you specify them, Eloquent use them instead.
return $this->hasMany('QuoteData', 'booking_id');