I have three tables.
Customer
Product
Reviews
I have used Eloquent for mapping these tables.
For example,
In Review Model for customer details I have function like
public function customer(){
return $this->belongsTo('Customer', 'customer_id');
}
and for product details I have function like
public function product(){
return $this->belongsTo('Product', 'product_id');
}
Now Querying reviews model like
Review::all()->with(array('customer', 'product'))->get()
returns the values. That is fine. But, if any customer is deleted, then the value for the row is just empty. Instead I need to omit that row. How to do this in laravel.
Try this... Perhaps adding the where clause to your approach works too.
$allReviews = Review::all()
->join('customers', 'reviews.customer_id', '=', 'customers.id')
->join('products', 'reviews.product_id', '=', 'products.id')
->where('customers.firstname','!=','') // given that there is a column firstname in table customers
->get()
You can use has() to filter for models that have at least one related model:
Review::with('customer', 'product')->has('customer')->get();
Related
I have a laravel app with products which can be associated to quotes.
The problem i have is that a quote is almost the same as an order
So when a quote is accepted i dump all the values from quote to order and re-associate all of the items to the order instead of quote.
I planned to make a type field on orders and just change type from quote to order but doing that makes it hard to run eloquent queries on product relationships such as..
To determine if product is sold: Products::has('order');
What is the correct way to implement this design?
You can do this by applying additional constraints on the relationship.
class Product extends Model
{
/**
* Get the orders for the product.
*/
public function orders()
{
return $this->hasMany('App\Order')->where('type', '=', 'order');
}
/**
* Get the quotes for the product.
*/
public function quotes()
{
return $this->hasMany('App\Order')->where('type', '=', 'quote');
}
}
Now you can check quotes and orders for a product using the following code
Product::has('quotes');
Product::has('orders');
If you don't want to write additional constraints in the relation method and only orders() relation is added, then you can use the whereHas() method when needed.
$orders = Product::whereHas('orders', function (Builder $query) {
$query->where('type', '=', 'order');
})->get();
$orders = Product::whereHas('orders', function (Builder $query) {
$query->where('type', '=', 'quote');
})->get();
If you want to keep both, order and quotes, you could create multiple N-N relations or a single N-N polymorphic releation
product 1-N quote N-1 order_data
product 1-N order N-1 order_data
Order_data contains all information about the order. The quote and order table defining the kind of order.
If you plan to also introduce other kinds of customer requests, like credit notes and other additional. You should think about creating a polymorphic relationship.
Product 1-N order_type N-N order_data
Product: contains product information
Order_data: represents different customer inputs
Order_type: different order relationships
You can create order data with multiple releations. So a orderType quote, order and credit can exists at the same time, which is important for documentation.
i have 3 tables with one-to-one relationship. The phone table has one to one relationship with Model table and Model table has a one to one relationship with Manufacturer table.
phone_table
id
imei
image
model_id
model_table
id
name
image
manufracturer_id
manufracturer_table
id
name
logo
how to get a result like this :-
App\Phone{
imei : "356554512522148",
model : "Galaxy S-10",
manufracturer : "Samsung",
}
I would never throw it into the same array / object, i would firstly do that on transformation. If you use default Laravel transformation you can use getters for it. Simple example on how to access these fields into the same context would be.
$phone = Phone::with('model.manufactor')->find(1);
With secures the queries are optimal for accessing it. How to get data into same layer.
[
'imei' => $phone->imei,
'model' => $phone->model->name,
'manufactor' => $phone->model->manufactor->name,
]
For this to work, you need relations in your model too.
Phone.php
public function model()
{
return $this->belongsTo(Model::class);
}
Model.php
public function manufactor()
{
return $this->belongsTo(Manufactor::class);
}
Just join them:
\App\Phone::leftjoin('model_table AS mo', 'mo.id', '=','phone_table.model_id')
->leftjoin('manufracturer_table AS ma', 'ma.id', '='. 'mo.manufracturer_id')
->selectRaw('phone_table.imei, mo.name AS model, ma.name AS manufracturer')
->first()
And sometimes you need to think about why you want to split table to one-to-one relationship.
Is there a table not usually be used, or one of them need to be connected by another tables. is this just for saving space or reduce IO cost.
If there are not any other reason and you always need to get these tables' information, maybe you can merge to one table.
Is there an efficient way of retrieving the name by using select and join clause? I have a Note, NoteType and NoteStatus model. There are type and status field which will be stored as integer (representing the id of its respective model) inside Note model. NoteType and NoteStatus models have id and name fields.
foreach($notes as $note)
{
$type=NoteType::where('id',$note->type)->first();
$note->type=$type->name;
$status=NoteStatus::where('id',$note->status)->first();
$note->status=$status->name;
}
Model Relations
Setting up relations between your models would be the best way as you then don't need to re-invent the wheel each time you need to call the join. It will save you code in the long run.
More info on this here:
Laravel Eloquent Relationships
Query Builder
If you want to do this manually then it would be the same as if you ran the query in raw SQL:
$note = Note::join('NoteType','Note.NoteType_id','NoteType.id')
->select('Note.*','NoteType.Name as NoteName')
->first();
Now you can get all the info from $note
Note id = $note->id
NoteType Name = $note->NoteName
Obviously adjust this to your code but this should help you build your knowledge enough to work it out.
More info can be found here:
Laravel Query Builder Joins
Assume that Your model name is Note.php
assume in your notes table has note_status_id and note_type_id foreign key
Add Relationship in your main model Note.php
public function status()
{
return $this->belongsTo(NoteStatus::class);
}
public function notes()
{
return $this->belongsTo(NoteType::class);
}
You can retrieve data with relationship something like that
Note::with('status','notes')
->get()
For more info regarding laravel relationship Laravel Eloquent: Relationships
The structure of concerning tables is as follows (MySQL):
//Table Name : team
tid PK
team_name (varchar)
//Table Name : fixture
fid PK
home_team_id FK |_ both referenced to 'tid' from 'team' table
away_team_id FK |
My aim is to retrieve the team names. Considering this structure, I think I'll have to retrieve home_team_id and away_team_id and then do something like
Fixture::where('tid','=',$home_team_id)->get();
My question is, is this the correct way to accomplish what I aim to do?
and
should this be done from the controller? (if so, then I'll have to do two queries from same function)
First, rather than having your primary keys be tid and fid, just keep them both as id. This is not only best practice, but will allow you to more easily use Laravel's Eloquent ORM as it by default assumes your primary key column is named id.
Second thing, make sure your table names are in plural form. Although this is not necessary, the example I'm about to give is using Laravel defaults, and Laravel assumes they are in plural form.
Anyway, once you've 'Laravelized' your database, you can use an Eloquent model to setup awesome relationships with very minimal work. Here's what I think you'd want to do.
app/models/Team.php
class Team extends Eloquent {
// Yes, this can be empty. It just needs to be declared.
}
app/models/Fixture.php
class Fixture extends Eloquent {
public function homeTeam()
{
return $this->belongsTo('Team', 'home_team_id');
}
public function awayTeam()
{
return $this->belongsTo('Team', 'away_team_id');
}
}
Above, we created a simple model Team which Laravel will automatically look for in the teams database table.
Second, we created model Fixture which again, Laravel will use the fixtures table for. In this model, we specified two relationships. The belongsTo relationship takes two parameters, what model it is related to, in both cases here they are teams, and what the column name is.
Laravel will automatically take the value in away_team_id and search it against the id column in your teams table.
With just this minimal amount of code, you can then do things like this.
$fixture = Fixture::find(1); // Retrieves the fixture with and id of 1.
$awayTeam = $fixture->awayTeam()->first(); // var_dump this to see what you get.
$homeTeam = $fixutre->homeTeam()->first();
Then you can proceed as normal and access the column names for the tables. So say you have a 'name' column in the teams table. You can echo out the the home team name from the fixture like so.
$fixture = Fixture::find(1); // Get the fixture.
echo $fixture->homeTeam->name;
It's nearly 2AM, so there might be an error or two above, but it should work.
Make sure you check the docs for Eloquent, especially the bits relating to relationships. Remember to name your columns and tables in the way Laravel wants you to. If you don't, there are ways to specify your custom names.
If you want to get even more fancy, you can define the inverse relationship like this on your Team model.
app/models/Team.php
class Team extends Eloquent {
public function fixturesAtHome()
{
return $this->hasMany('Fixture', 'home_team_id');
}
public function fixturesAway()
{
return $this->hasMany('Fixture', 'away_team_id');
}
}
Then to get all of a particular team's home fixtures...
$team = Team::find(1); // Retreive team with id of 1;
$homeFixtures = $team->fixturesAtHome();
in an app i have an entity that contains a list of other entities (let's say an event holding a list of assigned employees)
using objectify - i need to find all the events a particular employee is assigned to.
is there a basic way to filter a query if it contains the parameter - kind of the opposite of the query in
... quick pseudocode
findAll(Employee employee) {
...
return ofy.query(Event.class).filter("employees.contains", employee).list();
}
any help would be greatly appreciated
i tried just doing filter("employees", employee) after seeing this http://groups.google.com/group/objectify-appengine/browse_thread/thread/77ba676192c08e20 - but unfortunately this returns me an empty list
currently i'm doing something really inefficient - going through each event, iterating through the employees and adding them to a new list if it contains the given employee just to have something that works - i know this is not right though
let me add one thing,
the above query is not actually what it is, i was just using that because i did not think this would make a difference.
The Employee and Events are in the same entity group with Business as a parent
the actual query i am using is the following
ofy.query(Event.class).ancestor(businessKey).filter("employees", employee).list();
unfortunately this is still returning an empty list - does having the ancestor(key) in there mess up the filter?
solution, the employees field was not indexed correctly.
I added the datastore-indexes file to create a composite index, but was testing originally on a value that I added before the employees field was indexed, this was something stupid i was doing - simply having an index on the "business" field and the "employees" field fixed everything. the datastore-indexes file did not appear to be necessary, after deleting it and trying again everything worked fine.
Generally, you do this one of two ways:
Put a property of Set<Key<Employee>> on the Event
or
Put a property of Set<Key<Event>> on the Employee
You could also create a relationship entity, but if you're just doing filtering on values with relatively low counts, usually it's easier to just put the set property on one entity or the other.
Then filter as you describe:
ofy.query(Event.class).filter("employees", employee).list()
or
ofy.query(Employee.class).filter("events", event).list()
The list property should hold a Keys to the target entity. If you pass in an entity to the filter() method, Objectify will understand that you want to filter by the key instead.
Example :
/***************************************************/
#Entity
#Cache
public class News {
#Id Long id;
String news ;
#Index List<Long> friend_list = new ArrayList<Long>();
// My friends who can see my news , exemele : friend_list.add(id_f1); friend_list.add(id_f2); friend_list.add(id_f3);
//To make an operation on "friend_list", it is obligatory to index it
}
/*************************************************/
public News(Long id_f){
List<Long> friend_id = new ArrayList<Long>();
friend_id.add(id_f);
Query<Nesw> query = ofy().load().type(News.class).filter("friend_list in",friend_id).limit(limit);
//To filter a list, just after the name of the field you want to filter, add "IN".
//here ==> .filter("friend_list in",friend_id);
// if friend_list contains "id_friend" ==> the query return value
.........
}