Newbie to all the tech I'm using here.
Trying to query a table using Axios in Laravel with Vue.js. Here's what I got:
from my component's <script>
this.axios
.get('http://localhost:8000/api/tasks', {params: {vid: this.properties[0].vid}})
.then(response => {
this.tasks = response.data;
console.log(response)
})
Regardless of what vid is in the params, the response contains ALL of the table's rows.
I do know that this may have something to do with api.php, and the Controller associated with the request. I'll post those to be verbose.
routes/api.php
Route::middleware('api')->group(function () {
Route::resource('vehicles', VehicleController::class);
Route::resource('tasks', TaskController::class);
Route::get('tasks?={vid}', [TaskControler::class, 'search']);
});
Controllers/TaskController.php
class TaskController extends Controller
{
//
public function index() {
$tasks = Task::all()->toArray();
return $tasks;
}
public function store(Request $request){
$task = new Task([
'make' => $request->input('make'),
'model' => $request->input('model'),
'year' => $request->input('year'),
'mileage' => $request->input('mileage'),
'type' => $request->input('type'),
'VIN' => $request->input('VIN')
]);
$task->save();
}
public function show($tid){
$task = Task::find($tid);
return response()->json($task);
}
public function update($tid, Request $request){
$task = Task::find($tid);
$task->update($request->all());
return response()->json('Task Updated!');
}
public function destroy($tid){
$task = Task::find($tid);
$task->delete();
return response()->json('Task Deleted!');
}
}
I tried for a while to mess around with api and the controller, but to no avail. Most of the questions asked here give "just use params" as an answer, but despite my best efforts I don't seem to be able to get away with "just" params (willing to be proven wrong.)
Related
I am using inertia JS.
I created a forum where you can manage your posts and comments (CRUD).
Normally, the one who can modify or delete his post or comment is the one who created it and the administrator.
I was able to set up a policy for the post but for the comment it does not work. I need your help to fix this.
This is my show function for post and comments
public function show(Post $post, Comment $comment)
{
usleep(500000);
$post->incrementReadCount();
$updateableCommentIds = $post->comments
->map(function ($comment) {
if (Auth::user()->can('update', $comment)) {
return $comment->id;
}
})
->filter();
return Inertia::render('Frontend/Forum/Helpers/PostDetails', [
'post' => PostResource::make(
$post->load('user')->loadCount('comments')
),
'comments' => CommentResource::collection(
Comment::where('post_id', $post->id)
->with('user')
->paginate(10)
->withQueryString()
),
'categories' => Category::all(),
'can' => [
'edit' => Auth::check() && Auth::user()->can('edit', $post),
'commentEdit' => $updateableCommentIds
]
]);
}
This's my comment policy
class CommentPolicy
{
use HandlesAuthorization;
public function update(User $user, Comment $comment): bool
{
return $user->is_admin || $user->id === (int) $comment->user_id;
}
}
This's my vue file
<div
v-if="can.commentEdit.includes(comment.id)"
>
//show me this if im the auther of this comment
</div>
I already tried but it doesn't work either
public function show(Post $post)
{
$canUpdateComments = $post->comments->every(function ($comment) {
return Auth::user()->can('update', $comment);
});
// Return the view with the ability to update the comments
return view('posts.show', compact('post', 'canUpdateComments'));
}
I just noticed that I had a commentResource and just with that I found the solution instead of checking each time on the post not directly on the comment...
class CommentResource extends JsonResource
{
public function toArray($request)
{
return [
...
'can' => [
'edit' => Auth::user()->can('update', $this->resource)
]
];
}
}
So I have an API route
Route::group(['prefix' => 'users'], function() {
Route::group(['prefix' => 'seminar'], function() {
Route::get('/{employee_number}', [UserProfileController::class, 'getSeminar']);
Route::post('/{user}', [UserProfileController::class, 'createSeminar']);
Route::put('/{seminar}', [UserProfileController::class, 'updateSeminar']);
Route::delete ('/{seminar}', [UserProfileController::class, 'deleteSeminar']);
});
});
And a controller
public function createSeminar(User $user, Request $request)
{
return $this->allowIfRecordOwner($user->id, function() use ($user, $request) {
$seminar = Seminar::create([
"user_id" => $user->id,
"dates" => $request->dates,
"name" => $request->name,
"certificate_number" => $request->certificate_number
]);
return response()->json($seminar->toArray(), 200);
});
}
And im using that from my angular app
private saveSeminar(index) {
event.preventDefault();
const seminar = this.userSeminars[index];
if (seminar.id) {
this.updateUserSeminar(index);
} else {
this.storeStudentAddress(index);
}
}
private storeStudentAddress(index) {
this.apiService.create('users/seminar', this.userSeminars[index])
.subscribe(
response => {
this.userSeminars[index].edit = false;
this.userSeminars[index].id = response.id;
this.getUserSeminar(index.employee_number);
this.toastr.success('Seminar Successfully saved', 'Success');
});
}
I have done php artisan route:list and found my router here
And I have now been staring at the error for over three hours and can't see why I'm getting the error. Any help would be wonderful
Your API endpoint in Laravel doesn't look like it lines up with your API endpoint in your JavaScript.
You need to hit this endpoint in order to create a seminar: api/users/seminar/{user}, where {user} is the user's ID.
Your line here: this.apiService.create('users/seminar', this.userSeminars[index]) looks like it's instead hitting api/users/seminar, without the user's ID appended to the end.
You just need to change it to this.apiService.create('users/seminar/' + USER_ID, ... where USER_ID is whatever variable you're using to store the user's ID, or alternatively a method which returns it.
I have a problem that all the create-read-delete using Repository Pattern is good but the update function is error. I still have the data but the information is not updated.
This is my code in EventController
public function update(EventRequest $request, $id)
{
$events = $this->repository->update($request->all());
return $this->sendResponse($events->toArray(), 'Successfully updated the Event!!');
}
This is i use DI for inject from the Repository, this is EventRepository.php
public function update($id, array $array) {
$events = $this->model->findOrFail($id);
$events->update($array);
return $events;
}
when i use dd($array) and the result returns [] without anything. Can anyone help me. Did i write anything wrong in this. Or i write the wrong Request
public function rules()
{
// $id = $this->events ? ',' . $this->events->id : '';
return $rules = [
'event_title' => 'required|max:255',
'event_type_id' => 'required|integer|between:1,3',
'from_date' => 'required|date_format:Y-m-d H:i:s',
'to_date' => 'date_format:Y-m-d H:i:s|nullable',
'is_recurring' => 'boolean|required',
'remarks' => 'nullable',
];
}
This method takes two arguments:
public function update($id, array $array) {
However, that's not how you are calling it:
$this->repository->update($request->all());
I take it $request->all() gives you an array, so pass the ID first.
$this->repository->update($id, $request->all());
I'm learning Laravel by creating a recipe website.
The idea is a user creates a recipe which includes a title, description and number of portions (and tags), and then is directed to a new view in which they add the ingredients.
I've got this working, and the user can successfully create the recipe and the ingredients, which are being written to their respective tables, but I'm unable to attach/sync them.
Relevant parts of the models:
Recipe Model:
class Recipe extends Model
{
public function ingredients(){
return $this->hasMany('App\Ingredient', 'recipe_ingredients');
}
}
Ingredient Model:
class Ingredient extends Model
{
public function recipe(){
return $this->belongsTo('App\Recipe', 'recipe_ingredients');
}
}
Ingredients Controller
public function store(Request $request)
{
$this->validate($request, [
'name' => 'required|max:255'
]);
$ingredient = new Ingredient;
$ingredient->name = $request->name;
$ingredient->save();
$recipe = Recipe::find($request->id);
$recipe->ingredients()->attach($recipe_id);
$data = [
'success' => true,
'message'=> 'Your AJAX processed correctly',
'name' => $ingredient->name,
'recipe' => $recipe
] ;
return response()->json($data);
}
If I remove the $recipe->ingredients()->attach($recipe_id); the ingredients save to the ingredients table, but I can't get the recipe_id and ingredient_id to save in the recipe_ingredients table`.
I think I'm using the attach wrong, but I could be wrong.
Note:
Not that I think it makes any difference, but I'm submitting the data via Ajax.
Script:
$(document).ready(function(){
$("#submit").click(function() {
var name = $("#ingredientName").val();
var token = $("#token").val();
$.ajax({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
},
type: "post",
data: "name="+name,
dataType:'json',
url: "{{ route('ingredients.store', ['id' => $recipe->id]) }}",
success:function(data){
console.log(data);
$("#msg").html('<div class="alert alert-success my-0">'+data.name+' added</div>');
$("#msg").toggleClass("invisible")
$("#msg").fadeOut(2000);
$("#ingredientsTable").append('<tr><td scope="col" class="align-middle">'+data.name+'</td></tr>');
}
});
})
})
Revised Controller
public function store(Request $request)
{
$this->validate($request, [
'name' => 'required|max:255'
]);
$ingredient = new Ingredient;
$ingredient->name = $request->name;
$ingredient->save();
$recipe = Recipe::find($request->id);
$recipe->ingredients()->attach($ingredient->id);
$data = [
'success' => true,
'message'=> 'Your AJAX processed correctly',
'name' => $ingredient->name,
'recipe' => $recipe
] ;
return response()->json($data);
}
Table migration
public function up()
{
Schema::create('recipe_ingredients', function (Blueprint $table) {
$table->integer('recipe_id')->unsigned();
$table->foreign('recipe_id')->references('id')->on('recipes');
$table->integer('ingredient_id')->unsigned();
$table->foreign('ingredient_id')->references('id')->on('ingredients');
});
}
You're using the wrong ID when trying to attach the Ingredient to the Recipe:
$ingredient = new Ingredient;
$ingredient->name = $request->name;
$ingredient->save();
$recipe = Recipe::find($request->id);
$recipe->ingredients()->attach($recipe_id);
In the last line, you already have the Recipe, so passing $recipe_id (which I actually don't see defined anywhere) is not the correct logic.
What you need to do is pass the Ingredient you want to attach:
$recipe->ingredients()->attach($ingredient->id);
That should correctly set the relationship.
As shown by the example here: https://laravel.com/docs/5.6/eloquent-relationships#updating-many-to-many-relationships
You should be attaching the ingredients instead of the recipe:
$recipe->ingredients()->attach($ingredient_id);
-- edit --
You also have your Ingredient model as:
class Ingredient extends Model
{
public function ingredient(){
return $this->belongsToMany('App\Recipe', 'recipe_ingredients');
}
}
However, you should have this instead:
public function recipes(){
return $this->belongsToMany('App\Recipe', 'recipe_ingredients');
}
After making lots of little tweaks and changes, the following finally worked for me:
Recipe /model:
class Recipe extends Model
{
public function ingredients(){
return $this->hasMany('App\Ingredient', 'recipe_ingredients', 'recipe_id', 'ingredient_id');
}
Ingredient Model:
class Ingredient extends Model
{
public function recipes(){
return $this->belongsToMany('App\Recipe', 'recipe_ingredients', 'ingredient_id', 'recipe_id');
}
**IngredientsController#Store: **
public function store(Request $request)
{
$this->validate($request, [
'name' => 'required|max:255'
]);
$ingredient = new Ingredient;
$ingredient->name = $request->name;
$ingredient->save();
$recipe = Recipe::find($request->id);
$ingredient->recipes()->attach($recipe->id);
$data = [
'success' => true,
'message'=> 'Your AJAX processed correctly',
'name' => $ingredient->name,
'recipe' => $recipe
] ;
return response()->json($data);
}
As we can read here, we can listen the eloquent events and use it in the AppServiceProvider. It goes like this:
public function boot()
{
User::creating(function ($user) {
Log::create(['message' => 'create method']);
});
User::deleting(function ($user) {
Log::create(['message' => 'delete method']);
});
}
For all my eloquent models, I want to log in the database when it is created and who created it. This would mean that I need to copy paste this snippet 20 times and only change the User::creating part.
Is there a way that I can catch the eloquent events from all models and make something like this:
public function boot()
{
AllModels::creating(function ($model) { // <--- something like this here?
Log::create([
'message' => 'create method',
'model' => get_class($model) // <--- and then get the class name
]);
AllModels::deleting(function ($user) {
/***/
}
});
}
You can try something like this:
$models = ['User', 'Post', 'Comment', ....];
foreach ($models as $model) {
$model::creating(....);
$model::deleting(....);
}
Similar approach worked for me (I used DI instead of facades though).
Another approach I found and bookmarked some time ago:
Event::listen(['eloquent.creating: *'], function() {
....
});