Delete entrys in Database with foreignkey and pivot relations laravel 8 - php

Hey im searching for a method to delete adn entry which is connected to some other with ManytoMany and belongstoMany Relations, my question is how can i get an query that it finds the relations and checks it, if there are none it should be deleted and if there are some it should not delete it.
this is my Controller:
public function index()
{
$tracks = Track::all();
$seasons = Season::all();
return view('index.track', compact('tracks', 'seasons'));
}
public function create(): \Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View|\Illuminate\Contracts\Foundation\Application
{
$seasons = Season::all();
$topics = Topic::all();
$speakers = Speaker::all();
return view('create.track', compact('topics', 'seasons', 'speakers'));
}
public function store(TrackStore $request): \Illuminate\Http\RedirectResponse
{
$hashedName = Hash::make($request->file('track_data')->getClientOriginalName()) . "." . $request->file('track_data')->getClientOriginalExtension();
$request->track_data->storeAs('public/tracks', $hashedName);
$track = new Track();
$track->title = $request->track_title;
$track->description = $request->track_description;
$track->data = $hashedName;
$track->season_id = $request->season_id;
$track->save();
$track->speakers()->attach($request->input('speakers'));
$track->topics()->attach($request->input('topics'));
if($request->input('moderators')) {
$data = [];
foreach ($request->input('moderators') as $moderatorId) {
$data[$moderatorId] = ['is_moderator' => 1];
};
$track->speakers()->attach($data);
return redirect()->route('admin.trackShow');
} else {
return redirect()->route('admin.trackShow');
}
}
public function delete(Track $id): \Illuminate\Http\RedirectResponse
{
$id->delete();
return redirect()->route('admin.trackShow');
}
public function edit(Track $id)
{
return view('edit.track');
}
This is my Model:
class Track extends Model
{
use HasFactory;
protected $table = 'tracks';
protected $primaryKey = 'id';
protected $fillable = [
'title',
'description',
'data',
'season_id',
];
public function season(): BelongsTo
{
return $this->belongsTo(Season::class);
}
public function speakers(): BelongsToMany
{
return $this->belongsToMany(Speaker::class, 'speakers_tracks', 'track_id', 'speaker_id')->withPivot('is_moderator');
}
public function topics(): BelongsToMany
{
return $this->belongsToMany(Topic::class, 'topics_tracks', 'track_id', 'topic_id');
}
}
This is my migration:
Schema::create('tracks', function (Blueprint $table) {
$table->id('id');
$table->string('title');
$table->string('description');
$table->string('data');
$table->integer('season_id')->unsigned();
$table->timestamps();
$table->softDeletes();
});
As you see the Tracks are connected to many other stuff they are connected via relations. thanks in advance!

It will be easy with count()
if ($supplier->items()->count() == 0) $supplier->delete();
It is not your model. But you will get the idea.

Related

How to restrict delete / destroy method when model has association with another model / id?

I have model called GroupService and it has association with Service. I want to prevent or restrict when deleting GroupService, if GroupService has association with Service. And if GroupService has no association then users can delete it. I've been following these guides but it's not working for me :
[1] Laravel - How to prevent delete when there is dependent field
[2] https://laracasts.com/discuss/channels/laravel/how-to-prevent-the-delete-of-table-row-that-has-its-id-in-another-table
Here's my code :
Model GroupService:
class GroupService extends Model
{
use HasFactory;
protected $table = 't_grup_layanan';
protected $guarded = ['id'];
// protected $fillable = [
// 'bisnis_id',
// 'deskripsi'
// ];
protected $with = ['business'];
public function service(){
return $this->hasMany(Service::class);
}
public function business(){
return $this->belongsTo(Business::class, 'bisnis_id');
}
// protected static function boot(){
// parent::boot();
// static::deleting(function($groupservice) {
// $relationMethods = ['service'];
// foreach ($relationMethods as $relationMethod) {
// if ($groupservice->$relationMethod()->count() > 0) {
// return false;
// }
// }
// });
// }
}
Model Service:
class Service extends Model
{
use HasFactory;
protected $table = 't_layanan';
protected $guarded = ['id'];
// protected $fillable = [
// 'gruplayanan_id',
// 'nama',
// 'deskripsi'
// ];
protected $with = ['groupservice'];
public function groupservice(){
return $this->belongsTo(GroupService::class, 'gruplayanan_id');
}
}
Controller GroupService:
public function destroy(GroupService $groupservice, $id)
{
$groupService = GroupService::find(Crypt::decrypt($id));
if ($groupService->service()->exists())
{
abort('Resource cannot be deleted due to existence of related resources.');
}
$groupService->delete();
return redirect('/dashboard/gruplayanan/')->with('danger', 'Data dihapus !');
}
Migration GroupService:
public function up()
{
Schema::create('t_grup_layanan', function (Blueprint $table) {
$table->id();
$table->foreignId('bisnis_id')->nullable()->index('fk_bisnis_to_group');
$table->text('deskripsi');
$table->timestamps();
});
}
Migration Service:
public function up()
{
Schema::create('t_layanan', function (Blueprint $table) {
$table->id();
$table->foreignId('gruplayanan_id')->index('fk_grup_to_layanan');
$table->text('nama');
$table->text('deskripsi');
$table->timestamps();
});
}
public function up()
{
Schema::table('t_layanan', function (Blueprint $table) {
$table->foreign('gruplayanan_id', 'fk_grup_to_layanan')->references('id')->on('t_grup_layanan')->onUpdate('CASCADE')->onDelete('CASCADE');
});
}
I think problem is here on your relationship function:
public function service(){
return $this->hasMany(Service::class);
}
By Laravel convention, Eloquent will take the table name parent model and suffix it with _id.
So it look for t_grup_layanan_id field in the t_layanan table which currently does not exist.
So if you want to override the default convention, you have to specify it on the 2nd parameter like this.
public function service(){
return $this->hasMany(Service::class, 'gruplayanan_id');
}

laravel 9.0 Eloquent all() method doesn't return relationship

I have two tables Department and InspectionSite.
Department Migration
public function up()
{
Schema::create('departments', function (Blueprint $table) {
$table->id();
$table->string('department_name', 100);
});
}
InspectionSite Migration:
public function up()
{
Schema::create('inspection_sites', function (Blueprint $table) {
$table->id();
$table->string('site_title');
$table->foreignIdFor(\App\Models\Department::class);
$table->timestamps();
});
}
Department Model:
class Department extends Model
{
use HasFactory;
protected $fillable = ['depatment_name'];
public function sites() {
return $this->hasMany(InspectionSite::class);
}
}
InspectionSite Model
class InspectionSite extends Model
{
use HasFactory;
protected $guarded = [];
public function department() {
return $this->belongsTo(Department::class, 'department_id');
}
}
getting data from controller
public function get() {
$selector = ['site_title AS title', 'site_type' ];
$sites = InspectionSite::all();
return response()->json($sites->department, 200);
}
when I call find() method it returns relationship data but not in all() method?
public function get() {
$departments = Department::all();
return response()->json($departments->sites, 200);
}
Error details
all() method returns Collection of models and each model should have department relation.
When you are trying to return this:
return response()->json($sites->department, 200);
You are accessing department property on Collection instance.
Instead you should call it on each model of that collection.
Here you can try solutions, depending what you want to achieve
Solution 1: (recomended)
$sites = InspectionSite::with('department')->get();
return response()->json($sites, 200);
// result
[
{
...
department: ...
}
...
]
Solution 2: (Returns only depertments, not InspectionSite properties)
$sites = InspectionSite::with('department')->get()
->map(function($s) {
return $s->department;
});
return response()->json($sites, 200);
// result
[
{
[department]
}
{
[department]
}
]

Laravel's Eloquent: can't edit values

I'm using Lumen, trying to edit values, which is the easiest thing to do, for some reason, the updated values aren't being saved
Task.php model
public function taskUsers()
{
return $this->hasMany('App\Models\Tasks\UserTask')->where('role',1);
}
UserTask.php model contains nothing, an empty model
class UserTask extends BaseModel { }
Migrations
class CreateTasksTable extends Migration
{
protected $table = 'tasks';
protected $app_table = true;
public function up()
{
Schema::create($this->getTable(), function (Blueprint $table) {
$table->increments('id');
$table->string('title');
$table->dateTime('submit_date');
$table->dateTime('closed_date')->nullable();
$table->dateTime('due_date')->nullable();
$table->tinyInteger('is_done')->nullable()->default(0);
$table->integer('domain_id')->unsigned()->nullable();
$table->foreign('domain_id')->references('id')
->on(self::getTableName('domains'))->onDelete('cascade');
$table->bigInteger('created_by')->unsigned()->nullable();
$table->foreign('created_by')->references('id')
->on(self::getTableName('auth_users', false))->onDelete('cascade');
$table->bigInteger('closed_by')->unsigned()->nullable();
$table->foreign('closed_by')->references('id')
->on(self::getTableName('auth_users', false))->onDelete('cascade');
$table->timestamps();
});
}
public function down()
{
Schema::drop($this->getTable());
}
}
and
class CreateTaskUsersTable extends Migration
{
protected $table = 'task_user';
protected $app_table = true;
public function up()
{
Schema::create($this->getTable(), function (Blueprint $table) {
$table->increments('id');
$table->integer('task_id')->unsigned()->nullable();
$table->foreign('task_id')->references('id')
->on(self::getTableName('tasks'))
->onDelete('cascade');
$table->bigInteger('user_id')->unsigned()->nullable();
$table->foreign('user_id')->references('id')
->on(self::getTableName('auth_users', false))
->onDelete('cascade');
$table->integer('role');
});
}
public function down()
{
Schema::drop($this->getTable());
}
}
The edit action for example is so simple, if I just want to edit the title, that won't work, without even editing the rest.
class EditTaskAction extends BaseAction
{
protected $verbs = array('POST');
protected $private = true;
protected $inputRules = [
'domain_id' => 'required',
'task_id' => 'required',
'title' => '',
'due_date' => '',
'assignee_id' => '',
'is_done' => '',
'role' => ''
];
public function execute()
{
$title = $this->request->get('title');
$dueDate = $this->request->get('due_date');
$assigneeId = $this->request->get('assignee_id');
$taskId = $this->request->get('task_id');
$isDone = $this->request->get('is_done');
$role = $this->request->get('role');
$userId = \Auth::id();
$domainId = $this->request->get('domain_id');
\DB::beginTransaction();
try {
$task = Task::where('id', $taskId)
->where("domain_id", $domainId) ->first();
$userTask = UserTask::where('task_id', $taskId)->first();
if (isset($title) && !empty($title)) {
$task->title = $title;
}
if (isset($dueDate) && !empty($dueDate)) {
$task->due_date = $dueDate;
}
if (isset($assigneeId) && !empty($assigneeId)) {
$userTask->user_id = $userId;
}
if (isset($role) && !empty($role)) {
if ($role == TaskUserRole::ASSIGNEE) {
$userTask->role = $role;
}
}
if (isset($isDone) && !empty($isDone) ) {
if ($isDone == 0) {
$task->closed_by = null;
$task->closed_date = null;
$task->is_done = 0;
} else if ($isDone == 1) {
$task->closed_by = $userId;
$task->closed_date = Carbon::now();
$task->is_done = 1;
}
}
$task->save();
$userTask->save();
return $this->response->statusOk();
} catch (\Exception $exception) {
\DB::rollBack();
\Log::error($exception);
$this->response->addErrorDialog(self::SOMETHING_WENT_WRONG);
return $this->response->statusFail(self::SOMETHING_WENT_WRONG);
}
\DB::commit();
}
}
Basically all I'm doing
$task = Task::find($taskId); // I tried that too
$task->title = 'something';
$task->save();
It's not working
I think the problem is with your transaction. You're starting it with \DB::beginTransaction(); But the \DB::commit() (to save your changes to the database) will never be run, because you do Return-Statements before, like return $this->response->statusOk();
You could try to save your response to a variable and return it after the \DB::commit();
class EditTaskAction extends BaseAction
{
// ...
public function execute()
{
// ...
$response = null;
\DB::beginTransaction();
try {
// ...
$task->save();
$userTask->save();
$response = $this->response->statusOk();
} catch (\Exception $exception) {
// ...
$response = $this->response->statusFail(self::SOMETHING_WENT_WRONG);
}
\DB::commit();
return $response;
}
}
i thinks the problem in your model do you put your data stored in fillable
Did you set the guarded property on the model? You can completely disable guarding by setting it to an empty array.
protected $guarded = [];
// or check this:
protected $fillable = [...];
Otherwise you might find some error in the logs.

ERROR SQLSTATE[HY000]: General error: 1364 Field 'name' doesn't have a default value (SQL: insert into `favorites` () values ())

I am trying to copy a station from the station repository and add it to my favorite repository. I am in a laravel rest API. Thanks for the help!
Here is my controller:
class FavoriteController extends Controller
{
private $favoriteRepository;
private $stationRepository;
public function __construct(FavoriteRepository $favoriteRepository, StationRepository $stationRepository)
{
$this->favoriteRepository = $favoriteRepository;
$this->stationRepository = $stationRepository;
}
public function store(int $station_id)
{
$favorite = array();
$favorite[] = $this->stationRepository->findByField("id", $station_id);
$this->favoriteRepository->create($favorite);
return response()->json($favorite, 201);
}
}
Here is the database for the favorites:
public function up()
{
Schema::create('favorites', function (Blueprint $table) {
$table->string('name');
$table->string('city');
$table->foreign('city')->references('name')->on('cities');
$table->integer('station_id')->unsigned();
$table->foreign('station_id')->references('id')->on('stations')->onDelete('cascade');
$table->integer('user_id')->unsigned();
$table->foreign('user_id')->references('id')->on('users')->onDelete('cascade');
#$table->boolean('is_private');
});
}
Here is my Favorite model
class Favorite extends Model
{
protected $fillable = ['station_id', 'user_id', 'updated_at', 'name', 'city'];
public $timestamps = false;
}
And I have both these methods in my repos:
function model()
{
return "App\\Station";
}
Try this
public function store($station_id)
{
$favorite = $this->stationRepository->where("id", $station_id)->first()->toArray();
$this->favoriteRepository->create($favorite);
return response()->json($favorite, 201);
}
}

Laravel Eloquent after save id becomes 0

It's a table migrated from https://github.com/lucadegasperi/oauth2-server-laravel
In the table oauth_clients, the field data type of id is varchar(40), not int.
$name = Input::get('name');
$id = str_random(40);
$secret = str_random(40);
$client = new oauthClient;
$client->name = $name;
$client->id = $id;
$client->secret = $secret;
$client->save();
After save(); the $client->id become '0', not the string I assigned.
That makes the following relation table save fail.
$endpoint = new OauthClientEndpoint(array('redirect_uri' => Input::get('redirect_uri));
$client->OauthClientEndpoint()->save($endpoint);
I checked the $client->id: after save, it becomes 0 and I get an error including this one:
(SQL: insert into `oauth_client_endpoints` (`redirect_uri`, `client_id`, `updated_at`, `created_at`) values (http://www.xxxxx.com, 0, 2014-09-01 11:10:16, 2014-09-01 11:10:16))
I manually saved an endpoint to prevent this error for now. But how do I resolve this issue?
Here's my model:
class OauthClient extends Eloquent {
protected $table = 'oauth_clients';
public function OauthClientEndpoint(){
return $this->hasOne('OauthClientEndpoint', 'client_id', 'id');
}
}
class OauthClientEndpoint extends Eloquent {
protected $table = 'oauth_client_endpoints';
protected $fillable = array('redirect_uri');
public function OauthClient(){
return $this->belongsTo('OauthClient', 'client_id', 'id');
}
}
class CreateOauthClientsTable extends Migration {
public function up() {
Schema::create('oauth_clients', function (Blueprint $table) {
$table->string('id', 40);
$table->string('secret', 40);
$table->string('name');
$table->timestamps();
$table->unique('id');
$table->unique(array('id', 'secret'));
});
}
public function down() {
Schema::drop('oauth_clients');
}
}
class CreateOauthClientEndpointsTable extends Migration {
public function up() {
Schema::create('oauth_client_endpoints', function (Blueprint $table) {
$table->increments('id');
$table->string('client_id', 40);
$table->string('redirect_uri');
$table->timestamps();
$table->foreign('client_id')
->references('id')->on('oauth_clients')
->onDelete('cascade')
->onUpdate('cascade');
});
}
public function down() {
Schema::table('oauth_client_endpoints', function ($table) {
$table->dropForeign('oauth_client_endpoints_client_id_foreign');
});
Schema::drop('oauth_client_endpoints');
}
}
When you are setting your own ID and not using auto_increment be sure to add public $incrementing = false; to that model. In your case you want:
class OauthClient extends Eloquent {
public $incrementing = false;
protected $table = 'oauth_clients';
public function OauthClientEndpoint(){
return $this->hasOne('OauthClientEndpoint', 'client_id', 'id');
}
}
This is a tiny red block in the huge Laravel documentation:
Note: Typically, your Eloquent models will have auto-incrementing keys. However, if you wish to specify your own keys, set the incrementing property on your model to false.

Categories