Draven
Draven

Reputation: 1467

Laravel not updating db record (Model->$exists false)

I am trying to update my "Trip Name" (name field in the user_trips table).

I followed the "Laravel From Scratch: Updating Records and Eager Loading" video but it doesn't update, but I do get redirected back and get the session msg "Your trip has been renamed". The only difference I can see is that I am using one page (not an /edit page).

The problem is that the $exists variable in Laravels Model.php class is false so it's returning false in the update() method.

Why is $exists false?

routes.php

<?php

Route::get('/', 'TripBuilderController@index');

Route::post('add_flight', 'FlightController@store');

Route::patch('trip/{trip}', 'TripBuilderController@update');

TripBuilderController

<?php
namespace App\Http\Controllers;

use App\Airport;
use App\UserTrips;
use Illuminate\Http\Request;

/**
 * Class TripBuilderController
 *
 * @package App\Http\Controllers
 */
class TripBuilderController extends Controller
{
    /**
     * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
     */
    public function index()
    {
        $airports=Airport::all();
        $user_trips=UserTrips::whereUserId(1)->with('userflights.flightfrom', 'userflights.flightto')->get();

        return view('welcome', compact('airports', 'user_trips'));
    }

    /**
     * @param Request $request
     * @param UserTrips $user_trips_obj
     */
    public function update(Request $request, UserTrips $user_trips_obj)
    {
        # Returns {"_token":"RANDOM TOKEN","_method":"PATCH","name":"New Trip Name"}
        //return $request->all();

        $user_trips_obj->update($request->all());
        # Returns []
        //return $user_trips_obj;

        # Results below.
        //dd($user_trips_obj);

        return back()->with('msg', 'Your trip has been renamed');
    }
}

UserTrips Model

<?php
namespace App;

use Illuminate\Database\Eloquent\Model;

/**
 * Class UserTrips
 *
 */
class UserTrips extends Model
{
    /**
     * Indicates if the model should be timestamped.
     *
     * @var bool
     */
    public $timestamps=FALSE;
    /**
     * The attributes that are mass assignable.
     *
     * @var array
     */
    protected $fillable=[
        'name',
        'user_id'
    ];

    /**
     * @param UserFlights $user_flights_obj
     * @return Model
     */
    public function addFlight(UserFlights $user_flights_obj)
    {
        return $this->userflights()->save($user_flights_obj);
    }

    /**
     * @return \Illuminate\Database\Eloquent\Relations\HasMany
     */
    public function userflights()
    {
        return $this->hasMany(UserFlights::class);
    }

    /**
     * @return mixed
     */
    public function addTrip()
    {
        # Retrieve the trip by the attributes, or instantiate a new instance...
        $trip_obj=$this->firstOrNew(['user_id'=>1]);
        if(!$trip_obj->id)
        {
            $trip_obj->name='My Trip';
            $trip_obj->save();
        }

        return $trip_obj;
    }
}

welcome.blade.php

@extends('layouts.master')

@section('title', 'Trip Builder')

@section('content')
    <div id="airport_form">
        <form method="POST" action="/add_flight">
            {{ csrf_field() }}
            <div class="form-group">
                <select class="form-control" name="flight_from">
                    @foreach($airports as $airport)
                        <option value="{{ $airport->id }}">{{ $airport->name }}</option>
                    @endforeach
                </select>
            </div>
            <div class="form-group">
                <select class="form-control" name="flight_to">
                    @foreach($airports as $airport)
                        <option value="{{ $airport->id }}">{{ $airport->name }}</option>
                    @endforeach
                </select>
            </div>
            <div class="form-group">
                <button type="submit" class="btn btn-primary">Add Flight</button>
            </div>
        </form>
    </div>
    <div id="trip_info">
        <div id="trip_form">
            <form method="POST" action="/trip/{{ $user_trips[0]->id }}">
                {{ csrf_field() }}
                {{ method_field('PATCH') }}
                <label for="trip_name">Trip Name:</label> <input type="text" name="name" id="trip_name" class="form-control" value="{{ $user_trips[0]->name }}"><button type="submit" class="btn btn-primary">Rename Trip</button>
            </form>
        </div>
        <div id="flight_info">
            <table class="table table-striped table-bordered table-hover">
                <tr>
                    <th>
                        From
                    </th>
                    <th>
                        To
                    </th>
                    <th>
                        Options
                    </th>
                </tr>
                @foreach($user_trips[0]->userflights as $user_flight)
                    <tr>
                        <td>
                            {{ $user_flight->flightfrom->name }}
                        </td>
                        <td>
                            {{ $user_flight->flightto->name }}
                        </td>
                        <td>
                            <a href="#">Remove</a>
                        </td>
                    </tr>
                @endforeach
            </table>
        </div>
    </div>
@stop

dd($user_trips_obj); results

UserTrips {#156 ▼
  +timestamps: false
  #fillable: array:2 [▼
    0 => "name"
    1 => "user_id"
  ]
  #connection: null
  #table: null
  #primaryKey: "id"
  #keyType: "int"
  #perPage: 15
  +incrementing: true
  #attributes: []
  #original: []
  #relations: []
  #hidden: []
  #visible: []
  #appends: []
  #guarded: array:1 [▼
    0 => "*"
  ]
  #dates: []
  #dateFormat: null
  #casts: []
  #touches: []
  #observables: []
  #with: []
  #morphClass: null
  +exists: false
  +wasRecentlyCreated: false
}

Upvotes: 2

Views: 1341

Answers (2)

Texas Tom
Texas Tom

Reputation: 81

One problem I see is that the Laravel's Route Model Binding will not work correctly since you've named the model trip in routes.php. However, in your TripBuilderController class, you've named it $user_trips_obj. It should be renamed to trip or you'll need to explicitly redefine it in routes.php.

So, this

public function update(Request $request, UserTrips $user_trips_obj)

Should be

public function update(Request $request, UserTrips $trip)

because you've defined the trip parameter as trip in routes.php

Route::patch('trip/{trip}', 'TripBuilderController@update');

See Route Model Binding- Laravel Documentation

Upvotes: 3

Ohgodwhy
Ohgodwhy

Reputation: 50767

Don't add the _token or _method from your request.

$user_trips_obj->update($request->except(['_token', '_method']);

My thoughts are that you're failing on a MassAssignemtnException due to those fields not being whitelisted.

Along those lines, make sure you've got your name as a fillable attribute in your model

protected $fillable = ['name'];

Upvotes: 0

Related Questions