I can't figure how to relate these two tables.
I'm new to Laravel and ORM so it's kind of hard to me.
Here's my 2 tables I'm trying to relate:
Tables are called: posts and post_categories
And here are some of the code:
class Post extends Eloquent {
public function categories()
{
return $this->hasOne('PostCategorie');
}
}
class PostCategorie extends Eloquent {
protected $table = 'post_categories';
public function post()
{
return $this->belongsTo('Post', 'pc_id');
}
}
public function postCreate()
{
$validator = Validator::make(Input::all(), Post::$rules);
if ($validator->fails())
{
return Redirect::action('PostsController#getCreate')->withInput()->withErrors($validator);
}
// Else add to DB
$categories = Input::get('categories');
$post = new Post;
$post->user_id = Auth::user()->id;
$post->title = Input::get('title');
$post->text = Input::get('text');
$post->categories()->id_1 = $categories[0];
$post->save();
}
So as you see. I pass values to post and when I save it's ok... but I can't add categories ID to another table...
And also I created dummie entries, and tried to get Post Categories values:
Route::get('/', function()
{
$post = Post::find(5);
echo $post->title;
echo $post->categories()->id_1;
});
But it failed:
Undefined property: Illuminate\Database\Eloquent\Relations\HasOne::$id_1
OK first things first, You dont have to use PostCatagorie as your model name. Laravel features a pretty good pluralization class and can quite happily deal with Category or PostCategorie. Additionally, if you just call pc_id category_id (assuming a table name of category) you wont have to define any foreign keys which will make life a bit simpler until you get to grips with the basics.
When you create any kind of object (e.g $post) you can check if its relations are attached using dd($post); you can drill down further into these relations with:
echo '<pre>';
print_r($post);
echo '</pre>;
This together will allow you to see if what you are trying to do is actually working and view the structure of your result object.
I'm not entirely sure what you mean by "I cant add categories id to another table", and you seem to be saving the data ok... so I'll skip that bit. Please clarify the question if you need more info.
Once you have got the relationships set up and got some data in there you would have to load the two models together like so to get an object with the attached relationship:
$post = Post::with('Category')->find(5);
You will then be able to access your category object as $post->Category and from there any of its properties, e.g. $post->Category->id
Related
I have two tables named posts and categories. these two tables have one-to-many relationship and I wrote them in models like this:
class Post extends Model
{
...
public function category()
{
return $this->belongsTo(Category::class, 'category_id', 'id');
}
...
}
class Category extends Model
{
...
public function posts()
{
return $this->hasMany(Post::class, 'category_id', 'id');
}
...
}
This is work fine when I use $post = Post::find($id) in controller and retrieve one post and use $post->category to get category of this post. but what if I want to retrieve all posts and their categories together?
I mean, let's assume that I have 10 posts in DataBase and I have $posts = Post::get(); to get all posts. now, how I can get categories of each post?
One way is loop! for example:
foreach($posts as $post) {
$post['category'] = $post->category;
}
return response()->json($posts);
Yeah! I want to response in Json and I forgot to say earlier, sorry.
Is there better way to do this? I searched and I got nothing by my search. I'll be appreciated if anyone response to my problem. :)
The easiest way to include categories in each post model with json, is simply including it using with() and it will automatically transform it.
return Post::with('category')->get();
In Laravel you do not have to wrap models or collections in response->json(); it will automatically do that.
I am creating a comment table in my Laravel project so that users can comment on products. I want to make a table which can integrate with my user table (like a one-to-many relationship) in Laravel.
Here is my code:
public function buyproduct($id){
$user = Auth::user();
$users_comment = User::with('comments')->get();
$comments =comments::orderBy('id','desc')->get();
$renimage = Clothes::where('id',$id)->first();
return view('pages.products',[
'renimage'=>$renimage,
'google_avater'=>$user,
'comments'=>$users_comment
]);
}
Here I send my data to the view in my project. I don't understand how to access the data which is in my user table along with the data in the comment table.
First comments::orderBy... should be Comments::orderBy... ,
But you don't need that,
It's so simple to get user comments :
First Method: Using with()
Once the relationship has been defined, we can access the collection of comments by accessing the comments property. Remember, since Eloquent provides "dynamic properties", we can access relationship methods as if they were defined as properties on the model:
$books = App\Book::with('author')->get();
foreach ($books as $book) {
echo $book->author->name;
}
Second Method : Direct
Thankfully, we can use eager loading to reduce this operation to just 2 queries. When querying, you may specify which relationships should be eager loaded using the with method:
$comments = App\Post::find(1)->comments;
foreach ($comments as $comment) {
//
}
In your case :
public function buyproduct($id){
$user = Auth::user();
$users_comment = User::with('comments')->get();
//blow line changed
$comments =$users_comment->comments;
$renimage = Clothes::where('id',$id)->first();
return view('pages.products',[
'renimage'=>$renimage,
'google_avater'=>$user,
'comments'=>$users_comment
]);
}
Hope it helps;)
Suppose I have a User model and a Post model.
class Post extends Eloquent
{
}
There are many users, and each User has many Post. All Post belongs to a User.
class User extends Eloquent
{
public function posts()
{
return $this->hasMany('Post');
}
}
I know that I can get a single User with find().
$user = User::find(1);
I know that from a single User, I can get all their posts().
$posts = User::find(1)->posts;
However, suppose now I have multiple users.
$users = User::all();
I wish to access all the posts that this collection of users have. Something along the lines of
$posts = User::all()->posts;
This, of course, doesn't work. However, in theory, it should be functionally equivalent to
$posts = Post::all()
Is there a way to do something similar to the above in Laravel 4.2?
I do not want to use Post::all(). Reason being that it would not be what I want in a more complicated example that involves constraints on User.
$postsByMaleUsers = User::where('gender', '=', 'male')->posts;
Should get all the posts made by male users.
I am also aware that I could simply use a foreach loop.
foreach($users->posts as $post)
{
// Process result here.
}
However, suppose I am trying to return the results instead of processing the results. For example, I could have a public static function postsByMaleUsers() in the User model, and calling User::postsByMaleUsers() should return a collection of posts by male users only. In which case, the foreach loop would not suit me.
Eager load the posts, then use pluck and collapse to get a flat collection of posts:
$users = User::with('posts')->where('gender', 'male')->get();
$posts = $users->pluck('posts')->collapse();
For example I have:
// Returns all projects
$projects = Projects::all();
To return categories, belonging to project, I use relationships and can do something like:
foreach($projects as $project) { ...show $project->categories... }
I need only specific projects, which are followed by specific user. On my projects_followers table I have user_id and project_id.
To retrieve projects which were followed I have this peace of code:
$projects = Project::rightJoin(DB::raw('(select * from projects_followers group by project_id) projects_followers'),'projects_followers.project_id','=','projects.id')->get();
// Note: This code doesn't include specifuc user_id.
It does retrieve specific rows, but the problem with this code is that laravel relationhips dont work on them. For example $project->categories return empty.
// Relationship
public function categories()
{
return $this->belongsToMany('App\Category');
}
How do I retrieve my model specific rows and make relationships to work?
Actually your question is:
How do I get projects liked/followed by Auth/Logged in User ?
Unfortunately you described it in such a way that it looks something else, anyways. Lets try to find the solution and for this I would like to use something like this:
$projects = Auth::user()->favorite_projects;
So how we can implement this to work, first of all the User Model should contain the method favoriteProjects so lets create it:
public function favoriteProjects()
{
return $this->belongsToMany(
'App\Project',
'projects_followers', // This table already exists as you mentioned
'user_id',
'project_id'
);
}
That's it. You will be able to load the projects followed by the current user and other relationship methods will work on every single project as well.
My workaround:
// I don't know how to create empty collection, so impossible conditions here.
$projects = Project::where('id', 0)->get();
$follows = DB::table('projects_followers')->where('follower_id', Auth::user()->id)->get();
foreach($follows as $follow) {
$project = Project::where('id', $follow->project_id)->first();
$projects = $projects->add($project);
}
I have these tables in DB:
[posts, cats (categories), posts_cats (pivote)]
the relation between posts table and cats is many to many
I declared the relation in the models classes:
//Post.php
public function cats()
{
return $this->belongsToMany('cats');
}
//Cats.php
public function post()
{
return $this->belongsToMany('posts');
}
the question is, How to insert new post with multiple categories?
thanks,
Let's say you know the id of the post then you can attach a single cat like this:
Post::find($post_id)->cats()->attach($cat_id);
Or attach multiple cats like this:
$cat_ids = array(1,2,3,4);
Post::find($post_id)->cats()->attach($cat_ids);
If you got the Post model object in a variable, lets say $post:
$post->cats()->attach($cat_id);
// Or with multiple
$cat_ids = array(1,2,3,4);
$post->cats()->attach($cat_ids);
If you have a single category as an model object in, lets say $model:
$post->cats()->save($model);
Watch out with #Gadoma's answer. Its not wrong, but if you want to add categories to an post that already has categories then you should use attach() instead of sync(). Sync() will delete all others that are not provided to it when used.
edit:
So if you are creating a new Post then you probably are doing something like this:
$post = new Post;
$post->title = 'The title';
$post->something_else = 'Lorem';
$post->save();
//So now you have both the model object (the $post variable) and the id ($post->id).
$post->cats()->attach($cat_ids);
When you insert the post, then itterate over the categories and attach them to the new post. Something like that:
// $categories is an array of the categories to attach
foreach ($category_id in $categories) {
// Get a category object
$category = CategoryModel::find($category_id);
// $post is the new post
$post->cats()->attach($category);
}
I hope it helps you.
From the docs http://laravel.com/docs/eloquent#inserting-related-models
Inserting Related Models (Many To Many)
[...]
You may also use the sync method to attach related models. The sync
method accepts an array of IDs to place on the pivot table. After this
operation is complete, only the IDs in the array will be on the
intermediate table for the model:
And a code example:
$post = new Post(array('field1'=>'value1','fieldN'=>'valueN')) //example create new post
$categoryIds = array(1,3,4,5); //ids of (cats) categories you want the post to go into
$post->cats()->sync($categoryIds); //synchronise pivot table content with $categoryIds