Laravel 4 relationships - many-to-many

I can't find a way to define relationships. Here is my previous question, you can review it to find what I'm looking for: PHP/Laravel/Bootsrap fetch data
I've defined the relationship for skills like this:
public function skills()
{
return $this->hasMany('Skill', 'player_skills', 'skillid', 'player_id');
}
Still getting the Undefined property: Illuminate\Database\Eloquent\Collection::$players error pointing at $skills->players as $player.

First of all, with the hasMany function, you are setting up a one-to-many relationship, but it looks like you are sending it the name of a pivot table as a parameter, which would only be required for a many-to-many.
I'm going to assume you actually want a many to many relationship and your keys are correct (they are in the question you linked, but skillid is different here, so let's go with skill_id)
Also, the way you are looping through the data is wrong. $players->skills doesn't make any sense because $players doesn't have skills, but $player does.
Here is what I have so far... http://paste.laravel.com/Jp8
With the newest information you have given, I think there might be some confusion about how a many-to-many relationship works in Laravel. Please check this out when you get a chance, it should be pretty close to what you are looking for... http://paste.laravel.com/JqV

Related

When softDeletes() is use with the parent, what is the best way to handle all of its child

I have a table for publications, which has a relationship of one-to-many with the table reviews, each publication has many reviews.
I'm using AngularJS for the frontend and Laravel for the backend and MySQL for the database.
Let's say I would softDeletes() one of the publication, should I also need to use softDeletes() to all of its reviews? When softDeletes() is used with the parent, what is the best way to handle all of its child
Currently this is the solutions that I can think of base on my research but I still have doubts to what is the best way regarding of performance :
1. Only update the deleted_at column in publications table and leave
the reviews table as it is.
2. Create a MySQL trigger to update the deleted_at column in reviews
table when user softDeletes() the publication.
3. Update deleted_at column in table reviews inside laravel controller,
which will use foreach. But I think this has a performance issue assuming
that the publication have hundreds or thousands of reviews.
4. Create a different table for reviews which parent is temporarily inactive.
Separating reviews that are active and inactive, I think this will help in
query performance. I'm not sure.
Sorry if some of my grammar is wrong but if you understand my question I would be happy to hear your thoughts. Thank you.
Do you need to do anything at all?
If you can't access single reviews without going through the parent->child relationship, there's no real reason to do anything with the reviews.
If you can access single reviews, just add a constraint to not fetch reviews where the parent is softdeleted()
But if you don't like that approach, just enable softdeletes on your reviews and when you destroy() a publication:
foreach($publication->reviews as $review) {
$review->delete();
}
Laravel's Eloquent model events are likely the best bet here.
Model::deleted(function ($model) {
$model->children()->update(['deleted_at', $model->deleted_at]);
});
Model::restored(function ($model) {
$model->children()->update(['deleted_at', null]);
});

Neo4j query relationship property

Neo4j newbie here.
I have a graph database with node as Person, edges between nodes are relationship POSTED, POSTED has property "message", now I would like to return relationship with certain message. I wrote query like:
MATCH (ppl) -[p:POSTED]->(s)
WHERE p.message = "How are you?"
RETURN p
It returns nothing.
What is the right way to make relationship queries?
Can I make some queries like:
MATCH (a) -[:KNOWS]->(ppl),
(ppl) -[p:POSTED]->(s)
WHERE p.message = "How are you?"
RETURN p
Creating a lot of same Relations between two nodes is not a good idea if you want to create something like a chat.
In fact, it'll be a lot more easier and faster to create a model like this:
(:User{Foo:"Bar})-[:POSTED]->(:Message{content:"Hello World"})-[:SENT_TO]->(:User{Foo:"blabla"})
This way, you'll be able to store way more thing in your messages and It's easier to do operations with nodes.
You can check this reddit topic to find out the best practices to do what you want.

Laravel 5.1, Eloquent, ManyToMany with comment

I followed Jeffrey Way's ManyToMany tutorial https://laracasts.com/series/laravel-5-fundamentals/episodes/21 and I got everything and everything is working great. However I would like to add another feature to my many to many relation and that is a 'comment' that gives some more info to the object relation.
I have two models:
Article [id, title, text]
Category [id, title]
And this is a many to many relation so I create a pivot table as article_category. This table has two columns article_id and category_id and they are connected via functions in model as:
Article.php:
public function categories()
{
return $this->belongsTo('App\Category');
}
& Category.php
public function articles()
{
return $this->belongsTo('App\Article');
}
However I would like to add another field called comment to the pivot table where I could describe why this Article was added to this specific Category. Adding a column is not a problem but I don't know how to retrieve this comment from, lets say, Article instance:
$articleCategoryComment = Article::find(1)->commentFromPivotTable;
I could always define another oneToMany relation, and create another table to save the comment with fields [artice_id,category_id,comment] but I am wondering is there a better/simpler way.
Also, any good resource on database structuring will be greatly appreciated. I would prefere bunch of examples on how to do stuff right way in MySQL but a book that explains things from scratch is also good recommendation. However, at the moment I won't have time to go too deep but it will be bookmarked for future reading.
Thanks!
You should be using belongsToMany on a Many to Many relationship. If you want additional columns on your pivot table, using the withPivot() method. From the docs:
return $this->belongsToMany('App\Role')->withPivot('column1', 'column2');
You'll find more info here: http://laravel.com/docs/master/eloquent-relationships#many-to-many

How to make a nested query with an Entity that doesn't really exist (many-to-many)

I'm new with Doctrine2 so my question can be easy to answer (I hope so).
First of all, here the SQL query that I'd want :
SELECT *
FROM Document
WHERE id NOT IN (SELECT document_id FROM Documents_Folders)
Pretty simple isn't it ? The porblem is that my table 'Documents_Folders' is not an entity. In fact, it was create because I have a many-to-many relation between my entities 'Document' and 'Folder'.
I tried several queries, but none worked.
Thanks.
It really does look pretty simple, so it's not the problem with your SQL.
So if you want some help, tell us what is the error that you get?
BTW Your database shouldn't care what you use Documents_Folders for - it's just a table. (I don't know Doctrine2, but it's still regular database underneath, isn't it?)
Out of curiosity, What is your business case here.
Are you trying to get orphaned documents?
A Document can be part of Many Folders and a Folder can have many Documents?

Limiting results of System.Data.Linq.Table<T>

I am trying to inherit from my generated datacontext in LinqToSQL - something like this
public class myContext : dbDataContext {
public System.Data.Linq.Table<User>() Users {
return (from x in base.Users() where x.DeletedOn.HasValue == false select x);
}
}
But my Linq statement returns IQueryable which cannot cast to Table - does anyone know a way to limit the contents of a Linq.Table - I am trying to be certain that anywhere my Users table is accessed, it doesn't return those marked deleted. Perhaps I am going about this all wrong - any suggestions would be greatly appreciated.
Hal
Another approach would to be use views..
CREATE VIEW ActiveUsers as SELECT * FROM Users WHERE IsDeleted = 0
As far as linq to sql is concerned, that is just the same as a table. For any table that you needed the DeletedOn filtering, just create a view that uses the filter and use that in place of the table in your data context.
You could use discriminator column inheritance on the table, ie. a DeletedUsers table and ActiveUsers table where the discriminator column says which goes to which. Then in your code, just reference the Users.OfType ActiveUsers, which will never include anything deleted.
As a side note, how the heck do you do this with markdown?
Users.OfType<ActiveUsers>
I can get it in code, but not inline
Encapsulate your DataContext so that developers don't use Table in their queries. I have an 'All' property on my repositories that does a similar filtering to what you need. So then queries are like:
from item in All
where ...
select item
and all might be:
public IQueryable<T> All
{
get { return MyDataContext.GetTable<T>.Where(entity => !entity.DeletedOn.HasValue); }
}
You can use a stored procedure that returns all the mapped columns in the table for all the records that are not marked deleted, then map the LINQ to SQL class to the stored procedure's results. I think you just drag-drop the stored proc in Server Explorer on to the class in the LINQ to SQL designer.
What I did in this circumstance is I created a repository class that passes back IQueryable but basically is just
from t in _db.Table
select t;
this is usually referenced by tableRepository.GetAllXXX(); but you could have a tableRepository.GetAllNonDeletedXXX(); that puts in that preliminary where clause to take out the deleted rows. This would allow you to get back the deleted ones, the undeleted ones and all rows using different methods.
Perhaps my comment to Keven sheffield's response may shed some light on what I am trying to accomplish:
I have a similar repository for most
of my data access, but I am trying to
be able to traverse my relationships
and maintain the DeletedOn logic,
without actually calling any
additional methods. The objects are
interrogated (spelling fixed) by a StringTemplate
processor which can't call methods
(just props/fields).
I will ultimately need this DeletedOn filtering for all of the tables in my application. The inherited class solution from Scott Nichols should work (although I will need to derive a class and relationships for around 30 tables - ouch), although I need to figure out how to check for a null value in my Derived Class Discriminator Value property.
I may just end up extended all my classes specifically for the StringTemplate processing, explicitly adding properties for the relationships I need, I would just love to be able to throw StringTemplate a [user] and have it walk through everything.
There are a couple of views we use in associations and they still appear just like any other relationship. We did need to add the associations manually. The only thing I can think to suggest is to take a look at the properties and decorated attributes generated for those classes and associations.
Add a couple tables that have the same relationship and compare those to the view that isn't showing up.
Also, sometimes the refresh on the server explorer connection doesn't seem to work correctly and the entities aren't created correctly initially, unless we remove them from the designer, close the project, then reopen the project and add them again from the server explorer. This is assuming you are using Visual Studio 2008 with the linq to sql .dbml designer.
I found the problem that I had with the relationships/associations not showing in the views. It seems that you have to go through each class in the dbml and set a primary key for views as it is unable to extract that information from the schema. I am in the process of setting the primary keys now and am planning to go the view route to isolate only non-deleted items.
Thanks and I will update more later.