Adding records to a relations repository with Laravel - laravel

I’m using laravel 5.5 and andersao/l5-repository. I want to add an answer record with the question repository.
My Question Controller
protected $repository;
public function __construct(QuestionRepository $repository)
{
$this->repository = $repository;
}
public function add_answer(AnswerAddRequest $request)
{
$this->validator->with($request->all())->passesOrFail(ValidatorInterface::RULE_CREATE);
$question = $this->repository->answer->create([
'content' => 'Answer text question',
'user_id' => Auth::user()->id
]);
return question;
}
My Question Model
public function answer()
{
return $this->belongsTo(Answer::class, 'question_id');
}
I tried '$this->repository->answer()'
always error : Undefined property
I think I have to use the with() method, but I don’t want to take all the content. I only need to add content with the relation of the model.

You should add this part of code
public function answer()
{
return $this->belongsTo(Answer::class, 'question_id');
}
into your Question mode, not into your repository.
The Laravel Eloquent class extends the Model class, which has methods like belongsTo that you're using.
--- EDIT ---
If you want to use repository, you could integrate it with Eloquent:
$this->reposotiry->find($request->input('question_id'))->answer()->create([
'content' => 'Answer text question',
'user_id' => Auth::user()->id
]);

Related

How to insert into two table using laravel 8? This is my code

This is my code
I have a table inventory_transactions(id, part_name, part_number) and transaction_logs(id, description, inventory_transaction_id(FOREIGN KEY)). I want to insert the value of id to inventory_transaction_id.
What should I do?
namespace App\Http\Controllers;
use App\Models\Inventory_transaction;
use App\Models\Transaction_log;
use Illuminate\Http\Request;
public function store(Request $request){
$inventory_transaction = $request->validate($this->validation());
$value = Inventory_transaction::create($inventory_transaction);
return $this->respondWithMessage('Transaction added');
}
private function validation()
{
return [
'part_name' => ['required'],
'part_number' => ['required'],
];
}
Assuming that you have relationships defined as
class Inventory_transaction extends Model
{
public function transaction_logs()
{
return $this->hasMany(Transaction_log::class);
}
}
you can use the relation to insert related record
public function store(Request $request)
{
$validated = $request->validate($this->validation());
$transaction = Inventory_transaction::create($validated);
$transaction->transaction_logs()->create(['description' => 'Transaction Added.']);
return $this->respondWithMessage('Transaction added');
}
Having said that you should seriously spend some time going through Laravel docs, it will enable you to understand the basics very well - Laravel has one of the best documentation with lots of code examples for easy understanding of basic
Laravel relations: https://laravel.com/docs/8.x/eloquent-relationships#introduction

How to create Laravel api route endpoint/query parameters?

I would like to be able to filter the json response using some fields in the database e.g. api/v1/user?username=mary but don't know how to do this. My second question is that the route api/v1/user/3 is working but I can't remember how I set this up as I did it some time ago. Can anyone help?
api.php
Route::group(['prefix' => 'v1'], function () {
Route::apiResource('/user', 'UserController');
});
user resource
public function toArray($request)
{
return parent::toArray($request);
}
user controller
public function show(User $user): UserResource
{
return new UserResource ($user);
}
public function index(): UserResourceCollection
{
return new UserResourceCollection(User::orderBy('created_at', 'desc')
->paginate(5)
);
}
public function store(Request $Request)
{
$request->validate([
'first_name' => 'required',
'last_name' => 'required',
'email' => 'required',
]);
$user = User::create($request->all());
\Mail::to($user)->send(new Welcome);
return new UserResourse($user);
}
public function update(User $user, Request $request): UserResource
{
$user->update($request->all());
return new UserResource($User);
}
public function destroy(User $user)
{
$user->delete();
return response()->json();
}
}
UPDATED
I have seen several tutorials with the advice that the user has given below but I don't know how to put it together because I already have a show method above. I tried commenting out the show method and creating another show method for the query string
public function show(User $user): UserResourceCollection
{
$request->input('username');
return new UserResourceCollection(User::orderBy('created_at', 'desc')
->where('username', '=', $username)
->paginate(2)
);
}
and added a GET route
Route::group(['prefix' => 'v1'], function () {
Route::apiResource('/user', 'UserController');
Route::get('/user/{username?}','UserController#show');
});
This is working as an endpoint. The pagination part is working I made it smaller so I know it's calling the method but it is searching by id and i want to search by username. Ideally I want to use a query parameter like api/v1/user?username=mary.
To get json request, you can call $request->input('name') for example.
You can setup the resource action on controller. By example, you can create UserController.show method. So, the GET /user/{id} method will be handled by UserController.show
For more example, you read the documentation.
I don't think it's possible to create api url parameters. I started again using this tutorial
https://www.youtube.com/watch?v=z3YPhYwcbBM.
This way means I always have to know the id (search by product id rather than filtering reviews by query search) which isn't ideal
e.g. http://localhost:8000/api/v1/products/2/reviews
however I can add more endpoints in place of reviews like categories etc.

Eloquent Injected Multiple Model Relationships

So I learned in JeffreyWay's screencasts that I can use Eloquent to get the associated id from a model injected to another model.
I'm following his series about Laravel 5.4.
Here, I have a one-to-many relationships of user to posts.
App/Post
public function user()
{
return $this->belongsTo(User::class);
}
In my User Model, I have a publish method where the Post Model is injected. The publish method is used to create a post entry into the database.
App/User
public function posts()
{
return $this->hasMany(Post::class);
}
public function publish(Post $post)
{
$this->posts()->save($post);
}
I then have a store method in my PostsController that calls the publish method inside my User Model.
PostsController
class PostsController extends Controller
{
public function __construct()
{
$this->middleware('auth')->except(['index', 'show']);
}
public function store()
{
auth()->user()->publish(
new Post(request(['title', 'body']))
);
}
}
When the publish method is called, the injected Post class automatically sets the user_id to the save method.
My question is, how do I make a relationship like this in a situation where for every posts, there are comments. These comments are associated to the Post and the User that created the comment.
In short, I should have both user_id and post_id when I call the addComment method.
User Model:
public function posts(){
return $this->hasMany(Post::class);
}
public function comments(){
return $this->hasMany(Comments::class);
}
Posts Model
public function user(){
return $this->belongsTo(User::class);
}
public function comments(){
return $this->hasMany(Comments::class);
}
Comments Model
public function post(){
return $this->belongsTo(Post::class);
}
public function user(){
return $this->belongsTo(User::class);
}
Example Problems:
1) Get user comments:
Solution: auth()->user()->comments()->get(); <- collection of user
comments .
2) Get user from the given comment:
Solution: Comment::find($someCommentId)->user()->first()->name; <-
User name from a specific comment.
3) Get all comments for a specific post .
Solution: Post::first()->comments()->get(); or eager load
Post::with('comments')->first(); <- A collection that contains post
information within it u can find a collection of comments for that
post.
4) Load user when loading a comment:
Solution: Comment::with('user')->first(); <- single collection
containing a collection with user info and comment info.
5) Load a specific user post and comments for that post at the same time:
Solution: User::with('posts.comments')->first(); <- Contains a
collection with user info and collection of all user posts with each
post containing comments.
In your question you wrote:
In short, I should have both user_id and post_id when I call the addComment method.
Which is absolutely correct and no problem. You don't have to set these properties through a method like $user->posts()->save($post) - this is just a convenience method that does the job for you (see save($model) and related setForeignAttributesForCreate($model) in the framework code; these methods just set the foreign key property for you).
In fact, the following three ways to create a new post are interchangeable:
// what you did
$user->posts->save(
new Post([
'title' => 'Hello',
'body' => 'World!',
])
);
// equivalent
Post::create([
'user_id' => \Auth::user()->id, // or \Auth::id()
'title' => 'Hello',
'body' => 'World!',
]);
// also equivalent
$post = new Post([
'user_id' => \Auth::user()->id, // or \Auth::id()
'title' => 'Hello',
'body' => 'World!',
]);
$post->save();
When storing a new comment, you will most likely have a controller like this, because a comment always belongs to a post and you therefore will need a reference of the post:
class CommentsController extends Controller
{
public function __construct()
{
$this->middleware('auth')->except(['index', 'show']);
}
public function store(Post $post)
{
$comment = new Comment(request(['body']));
$comment->user_id = \Auth::user()->id;
$comment->post_id = $post->id;
$comment->save();
}
}
You could also abbreviate it and write:
Comment::create(
array_merge(request(['body']), ['user_id' => \Auth::id(), 'post_id' => $post->id])
);

Where provide "morphMap" setting for standalone eloquent usage without laravel

I am using eloquent as standalone module with slim framework (https://www.slimframework.com/docs/cookbook/database-eloquent.html)
My question is - where i can provide polymorphic relations "morphMap" setting?
you should define the morphMap in each function that define in morph or morphToMany:
example::
here is the comments function model:
class comment extends Model
{
public function commentable(){
Relation::morphMap([
'posts' => 'App\post',
'videos' => 'App\video',
]);
return $this->morphTo();
}
}
here is the post function model:
class post extends Model
{
public function comments(){
Relation::morphMap([
'posts' => 'App\post',
]);
return $this->morphMany('App\comment','commentable');
}
}
dont forget to add this namespace:
use Illuminate\Database\Eloquent\Relations\Relation;
To avoid to use morphMap in each model's relation you can override boot method setting there your morphMap:
class Post extends Model
{
protected static function boot(){`
parent::boot();
Relation::morphMap([
'posts' => 'App\post',
]);
}
public function comments(){
return $this->morphMany('App\Comment', commentable);
}
}
Today i searched for the same problem.
Slim4 & Eloquent.
I have to following code in my container boot file and it works.
container.php
// eloquent
$capsule = new \Illuminate\Database\Capsule\Manager;
$capsule->addConnection($dbSettings);
$capsule->setAsGlobal();
$capsule->bootEloquent();
$container->set('db', function ($container) use ($capsule) {
Illuminate\Database\Eloquent\Relations\Relation::morphMap([
App\Models\Order::class
]);
return $capsule;
});
now my database contains order instead of App\Models\Order
Don`t know if this is the correct way.
But this way I only have to write it in one place.

Passing data from controller into Model in Laravel

I have this comment controller:
class CommentsController extends Controller
{
public function store(Article $article){
$comment = new Comment();
$comment->user_id = auth()->id();
$comment->comment = request('comment');
$comment->article_id = $article->id;
$comment->save();
return back();
}
}
And it works. I tried to make my code cleaner by putting that logic into my model. So I changed it like this:
class CommentsController extends Controller
{
public function store(Article $article){
$article->addComment(request('comment'));
return back();
}
}
Meanwhile, in my Comment Model I'm doing like this:
class Article extends Model
{
protected $fillable = ['title','content','user_id'];
public function comments(){
return $this->hasMany(Comment::class);
}
public function user(){
return $this->belongsTo(User::class);
}
public function addComment($comment){
Comment::create([
'comment' => $comment,
'article_id' => $this->id,
'user_id' => auth()->id()
]);
}
}
but when I do this, I'm getting this kind of error:
"SQLSTATE[HY000]: General error: 1364 Field 'user_id' doesn't have a default value (SQL: insert into `comments` (`comment`, `article_id`, `updated_at`, `created_at`) values (Test comment bla bla bla..., 1, 2017-10-16 09:27:27, 2017-10-16 09:27:27)) ◀"
It seems I can't get the user_id in that manner, so how can I pass the user id so i can insert it into my comment tables? Thanks.
You need to add user_id to $fillable array in Comment model, not in Article model to make it work. Your original code works just because you do not use mass assignment there.
Try this:
public function addComment($comment){
Comment::create([
'comment' => $comment,
'article_id' => $this->id,
'user_id' => \Auth::user()->id
]);
}
try
\Auth::id()
instead of
auth()->id()
and go to your database and and make user_id default as NULL
The reason for this kind of error is that laravel protects database fields for mass assignment when you add the following code it makes all fields fillable.
protected $guarded = [];
Another way of doing is to add user_id in comments model. Is this case it will only allow the fields mentioned in the array to be mass assigned.
protected $fillable = [
'user_id'
];

Resources