实现地点访问/取消访问功能报错:Trying to get property of non-object
Alright, let's walk through exactly what's causing that error and fix it up step by step. The root issue is that your place_id is coming through as null in the controller, which breaks subsequent code that tries to access properties on a non-existent Place object. Here's how to fix it:
1. Fix the AJAX Parameter Mismatch & Unreliable DOM Selection
First, your JavaScript is sending the parameter as place_id, but your controller is trying to fetch $request['placeId'] (notice the camelCase vs snake_case mismatch). That's why $place_id is null right off the bat.
Also, your current way of grabbing placeId via event.target.parentNode.parentNode is fragile—if the DOM structure changes even a little, this will break. Use jQuery's closest() method to reliably find the parent element with the data-place_id attribute instead.
Here's the corrected AJAX code:
var token = '{{ Session::token() }}'; var urlVisit = '{{ route('visitss') }}'; $('.visit').on('click', function(event){ event.preventDefault(); // Grab the place ID from the closest parent with the data attribute var placeId = $(this).closest('[data-place_id]').data('place_id'); // Add a quick check to avoid sending invalid requests if (!placeId) { console.error("Couldn't find a valid place ID for this button"); return; } $.ajax({ method: 'POST', url: urlVisit, data: { place_id: placeId, // Match the snake_case parameter name the controller expects _token: token } }) .done(function(response) { // Optional: Add UI feedback (e.g., toggle a "visited" class on the button) $(this).toggleClass('visited'); console.log(response.status); }) .fail(function(xhr) { console.error("Toggle visit failed:", xhr.responseText); }); });
2. Fix Controller Logic Errors
Your controller has two critical issues that contribute to the error:
- You're trying to access
$place->ideven when$placeis null (when$place_idis invalid) - You're assigning
Auth::user()directly to$visited->user_id—this should be the user's ID, not the entire user object
Here's the cleaned-up, error-resistant controller code:
use Illuminate\Http\Request; use App\Models\Place; use App\Models\Visit; use Illuminate\Support\Facades\Auth; public function toggleVisit(Request $request) { // Get the place ID from the request (use input() for safer access) $place_id = $request->input('place_id'); // Validate we received a valid place ID first if (!$place_id) { return response()->json(['error' => 'Invalid place ID provided'], 400); } // Find the place—if it doesn't exist, return an error $place = Place::find($place_id); if (!$place) { return response()->json(['error' => 'Place not found'], 404); } // Get the authenticated user (add auth middleware to your route to ensure this isn't null) $user = Auth::user(); if (!$user) { return response()->json(['error' => 'You must be logged in to toggle visits'], 401); } // Check if the user already visited this place $visited = $user->visitors()->where('place_id', $place_id)->first(); if ($visited === null) { // Create a new visit record $visited = new Visit(); $visited->user_id = $user->id; // Assign the user's ID, not the object $visited->place_id = $place->id; $visited->save(); return response()->json(['status' => 'visited']); } else { // Delete the existing visit record $visited->delete(); return response()->json(['status' => 'unvisited']); } }
3. Quick Additional Checks
- Model Fillables: Make sure your
Visitmodel allows mass assignment for the required fields. Add this to yourVisitmodel:protected $fillable = ['place_id', 'user_id']; - Route Middleware: Ensure your
visitssroute uses theauthmiddleware to prevent unauthenticated users from hitting this endpoint. Example route definition:Route::post('/toggle-visit', [YourController::class, 'toggleVisit'])->name('visitss')->middleware('auth'); - Database Table: Double-check your
visitstable (note: table names are typically plural) hasplace_idanduser_idas unsigned integer fields, ideally set as foreign keys toplaces.idandusers.id.
内容的提问来源于stack exchange,提问作者detinu20

