Creating Child Record of Parent Class - php

Having a bit of trouble understanding how to attach my foreign key to my child record when I insert it into my db. I have a casino class that can have many different locations within the casino(Restroom, Restaurant, Valet, Etc.). I am trying to create a new record in my db of the location and include the foreign key(casino_Id) which is the id of the casino table. I am not sure how I would be able to obtain that id unless I pass it in directly from the post by the route which I am doing in my show.blade.php file within my casino views.
<button class="btn btn-primary">Add Location</button>
Not entirely sure if this is a practical/safe way of passing in that info or how to obtain it from my create function. Currently I have it finding the first casino record it can find in the db to see how it inserts it which it does insert into the db but does not include the foreign key on insert.
web.php
//Location Routes
Route::get('/casino/{casino}/location/create', 'LocationController#create');
Route::post('/location', 'LocationController#store');
Route::get('/location/{location}', 'LocationController#show');
Route::get('/location/{location}/edit', 'LocationController#edit');
Route::patch('/location/{location}', 'LocationController#update');
casino.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Casino extends Model
{
public function locations() {
return $this->hasMany(Location::class)->orderBy('title', 'ASC');
}
}
location.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Location extends Model
{
protected $guarded = [];
protected $fillable = ['title'];
public function casino() {
return $this->belongsTo(Casino::class);
}
public function duties() {
return $this->hasMany(Duty::class)->orderBy('title', 'ASC');
}
}
create and store functions in my LocationController.php
public function create() {
return view('locations.create');
}
public function store(Request $request) {
$casino = Casino::find(1);
$request->validate([
'title' => 'required',
]);
$casino->location = new location([
'title' => $request->get('title'),
]);
$casino->location->save();
return redirect("/casino/1");
}

You can change your route from
Route::get('/casino/{casino}/location/create', 'LocationController#create');
Route::post('/location', 'LocationController#store');
to
Route::get('/casinos/{casino}/locations/create', 'LocationController#create');
Route::post('casinos/{casino}/location', 'LocationController#store');
Your create action
public function create(Casino $casino)
{
return view('locations.create', compact('casino'));
}
Your store action
public store(Request $request, Casino $casino)
{
$request->validate(['title' => 'required']);
$casino->location()->create($request->validated());
return redirect("/casino/{$casino->id}");
}
Route Model Binding

Related

Laravel Eloquent persist 1:n

I want to create a laravel crud repository for a model. The model has 1 1:n and 1 n:n relationship.
class Product extends Model
{
protected $table = 'products';
protected $fillable = [
'description', 'merchantId', 'name', 'link', 'pictureUrl', 'ean', 'brand', 'aktPrice', 'affiliatePortal', 'programId'
];
public function prices() {
return $this->hasMany(Price::class);
}
public function categories() {
return $this->hasMany(Categorie::class);
}
}
Now I want to create a repository which has a save method and a controller for a restapi, which calls the save methode. My question is how should a save method looks that the entity is saved correctly and which mapping operations have to be done before that it works. I hope someone can help me and send me a save method, or a crud repository for my case and can help me to design the controller.
A Controller, with all the crud operations, look like this:
<?php
namespace App\Http\Controllers;
use App\Models\Room;
use Illuminate\Http\Request;
class RoomController extends Controller
{
public function index()
{
$rooms = Room::all()->toArray();
return $rooms;
}
public function add(Request $request)
{
$room = new Room;
$room->create($request->all());
return response()->json('The room successfully added');
}
public function getById($id)
{
$room = Room::find($id);
return response()->json($room);
}
public function update($id, Request $request)
{
$room = Room::find($id);
$room->update($request->all());
return response()->json('The room successfully updated');
}
public function delete($id)
{
$room = Room::find($id);
$room->delete();
return response()->json('The room successfully deleted');
}
}

laravel 5.7 data not passed to the view

I'm trying to pass my article data to the single page article named article.blade.php although all the data are recorded into the database but when I tried to return them in my view, nothing showed and the [ ] was empty. Nothing returned.
this is my articleController.php
<?php
namespace App\Http\Controllers;
use App\Article;
use Illuminate\Http\Request;
class ArticleController extends Controller
{
public function single(Article $article)
{
return $article;
}
}
this is my model:
<?php
namespace App;
use Cviebrock\EloquentSluggable\Sluggable;
use Illuminate\Database\Eloquent\Model;
class Article extends Model
{
use Sluggable;
protected $guarded = [];
protected $casts = [
'images' => 'array'
];
public function sluggable()
{
return [
'slug' => [
'source' => 'title'
]
];
}
public function path()
{
return "/articles/$this->slug";
}
public function comments()
{
return $this->morphMany(Comment::class, 'commentable');
}
}
and this is my Route
Route::get('/articles/{articleSlug}' , 'ArticleController#single');
Change your code to
class ArticleController extends Controller
{
public function single(Article $article)
{
return view('article', compact('article'));
}
}
change route to
Route::get('/articles/{article}' , 'ArticleController#single');
And model
public function getRouteKeyName()
{
return 'slug';
}
See docs https://laravel.com/docs/5.7/routing#route-model-binding
You might not be getting any data because you have not specified that you're using title_slug as the route key for model binding in your model.
Add this to your model class and it should give you the data
public function getRouteKeyName()
{
return 'slug';
}
Then you can return the data in json, view or other format.
Depending on what you try to archive, you need to either ...
return $article->toJson(); // or ->toArray();
.. for json response or ..
return view(..., ['article' => $article])
for passing a the article to a certain view

Laravel on delete objects call model event - deleted

Im trying to call model event - deleted. When Im deleting a video, I also want delete all comments which are associated with video, that is working fine. But I have also feeds table and when Im deleting video I want also delete all comments and comments feeds. Now when Im deleting video, I delete - video, video comments, video feed, but I need delete also video comment feeds.
The question is how I can make it possible to delete also comments feeds when Im deleting video?
Check VideoController.php destroy function
Video.php - Model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Cviebrock\EloquentSluggable\Sluggable;
class Video extends Model
{
protected $table = 'videos';
public $timestamps = false;
use Sluggable, RecordsFeed;
public static function boot()
{
parent::boot();
}
public function sluggable()
{
return [
'slug' => [
'source' => 'title'
]
];
}
public function comments()
{
return $this->hasMany('App\VideoComment', 'videoid', 'id');
}
public function member()
{
return $this->belongsTo('App\Member', 'userid', 'member_id');
}
}
VideoComments.php - Model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class VideoComment extends Model
{
protected $table = 'videos_comments';
public $timestamps = false;
protected $fillable = [
'text', 'userid', 'date'
];
use RecordsFeed;
public function videos() {
return $this->belongsTo('App\Video', 'id', 'videoid');
}
public function member() {
return $this->belongsTo('App\Member', 'userid', 'member_id');
}
}
RecordsFeed.php
<?php
namespace App;
use App\Libraries\Portal;
trait RecordsFeed
{
protected static function bootRecordsFeed() {
static::created(function($model) {
$model->recordFeed('created');
});
static::deleted(function($model) {
$model->deleteFeed('deleted');
});
}
public function feeds() {
return $this->morphMany( Feed::class, 'feedable' );
}
protected function recordFeed($event) {
$this->feeds()->create([
'user_id' => (new Portal)->getMemberID(),
'type' => $event.'_'.strtolower(class_basename($this))
]);
}
protected function deleteFeed($event) {
$this->feeds()->delete();
}
}
VideoController.php destroy function
public function destroy($id)
{
$video = Video::findOrFail($id);
$video->comments()->delete();
$video->delete();
Session::flash('success', 'Video deleted');
return redirect()->route('video.index');
}
Why do you not use on delete cascade at the creation of your table ?
In your migration, when you create your foreign key, just specify the on delete action like this :
$table->foreign('your_key')->references('id')->on('your_table')->onDelete('cascade');
It will automatically delete rows which are associated to the parent object.
You can find more details in Laravel documentation just here.
You don't have do anything code, you can set in database and set delete on cascade with relationshiop.

Laravel form validator error

I want to validate the input fields before storing the data in database so i went through the laravel docs and followed these
php artisan make:request StoreLessons
in StoreLessons
public function rules()
{
return [
'title' => 'required|unique:lesson',
'body' => 'required',
];
}
in my controller
namespace App\Http\Controllers;
use Response;
use App\lesson;
use Illuminate\Http\Request;
use App\Acme\Transformers\LessonTransformer;
use Illuminate\Support\Facades\Input;
use App\Http\Requests\StoreLessons;
class LessonsController extends ApiController
{
protected $lessonTransformer;
function __construct(LessonTransformer $lessonTransformer)
{
$this->lessonTransformer = $lessonTransformer;
}
//fetch all and pass a metadata 'data'
public function index()
{
$lessons = Lesson::all();
return $this->respond([
'data' => $this->lessonTransformer->transformCollection($lessons->all())
]);
}
//add a new lesson to lessons table
public function store(StoreLessons $request)
{
Lesson::create($request->all());
//Lesson::create(input::all());
return $this->respondCreated('Lesson created successfully');
}
}
now i'm getting this error
QueryException in Connection.php line 770:
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'laravel_api.lesson' doesn't exist (SQL: select count(*) as aggregate from `lesson` where `title` = the)
i don't know why it's looking for lesson table i have a lessons table
but the store() function works with default validation
//this works fine but i wan to do the validation
public function store()
{
if (! input::get('title') or ! input::get('body')) {
return $this->respondBadRequest();
}
Lesson::create(input::all());
return $this->respondCreated('Lesson created successfully');
}
Thank You
unique:table,column,except,idColumn
The unique syntax goes as above and the first parameter passed is the table name.
public function rules() {
return [ 'title' => 'required|unique:lesson', 'body' => 'required', ];
}
The unique rule here looks for a table lesson. Try changing that to lessons
Please write below line after related model class name like this.
class xyz extends Model
{
protected $table = 'lessons';
code---
}
Try this.

Add values to pivot table laravel

When I want to save a reaction to a ticket I've three tables (in laravel):
-Tickets
-Reaction
-Reaction_Tickets (pivot table)
When I want to save a reaction I do it like this:
public function addReaction(Request $request, $slug)
{
$ticket = Ticket::whereSlug($slug)->firstOrFail();
$reaction = new reactions(array(
'user_id' => Auth::user()->id,
'content' => $request->get('content')
));
return redirect('/ticket/'.$slug)->with('Reactie is toegevoegd.');
}
But now of course it's not added to the pivot table. And I can't add it because I don't have a model of it. What's the right way of doing this?
EDIT:
-Tickets
public function reactions()
{
return $this->belongsToMany('App\reactions');
}
-Reactions
public function tickets()
{
return $this->hasOne('App\tickets');
}
From the Laravel documentation, you need to save and attach the Reaction to the Ticket:
$reaction = new reactions(array(
'user_id' => Auth::user()->id,
'content' => $request->get('content')
));
$reaction->save(); // Now has an ID
$tickets->reactions()->attach($reaction->id);
In your Ticket model, you need to have the relationship defined:
class Ticket extends Model {
protected $table = "tickets";
public function reactions(){
return $this->belongsToMany("App\Reaction");
}
}
And you should have the inverse defined on Reaction:
class Reaction extends Model {
protected $table = "reactions";
public function tickets(){
return $this->belongsToMany("App\Ticket");
}
}
If your models are set-up like so, you shouldn't have any issue attaching the new Reaction to your existing Ticket via your pivot table.

Categories