Laravel problem response json

0

Witam , robie pewien projekt w laravelu i mam problem taki , że w momencie kiedy chce wczytać dane z metody "ajaxGetReservationData" która jest w moim backend controller wyskakuje mi błąd Failed to load resource: the server responded with a status of 500 (Internal Server Error) , Trying to get property 'room_number' of non-object C:\xampp\htdocs\laravel\app\app\Http\Controllers\BackendController.php#48 / ktos ma jakis pomysł jak to zrobić... poniżej kod z BackendController , BackendRepository oraz admin.js z ajaxem.

<?php

namespace App\Http\Controllers;


use Illuminate\Http\Request;
use App\Systemrezerwacji\Gateways\BackendGateway;
use App\Systemrezerwacji\interfaces\BackendRepositoryInterface;




class BackendController extends Controller
{



    public function __construct(BackendRepositoryInterface $bR, BackendGateway $bG)
    {
        $this->bR = $bR;
        $this->bG = $bG;

    }

    public function index(Request $request)
    {
        $objects = $this->bG->getReservations($request);

        return view('backend.index',['objects'=>$objects]);
    }
    public function ajaxGetReservationData(Request $request)
    {

        $reservation = $this->bR->getReservationData($request);


        return response()->json([
            'room_number' => $reservation->room_number,
            'day_in' => $reservation->day_in,
            'day_out' => $reservation->day_out,
            'FullName' => $reservation->user->FullName,
            'userLink' => route('person', ['id' => $reservation->user->id]),
            'confirmResLink' => route('confirmReservation', ['id' => $reservation->id]),
            'deleteResLink' => route('deleteReservation', ['id' => $reservation->id]),

            'status' => $reservation->status,

            ]);

    }

    public function cities(){
        return view('backend.cities');
    }

    public function myobjects(){
        return view('backend.myobjects');
    }
    public function profile(){
        return view('backend.profile');
    }
    public function saveobject(){
        return view('backend.saveobject');
    }
    public function saveroom(){
        return view('backend.saveroom');
    }
    public function confirmReservation($id)
    {
        return 'to do';
    }
    public function deleteReservation($id)
    {
        return redirect()->back(); /* Lecture 34 */
    }
}

<?php

namespace App\Systemrezerwacji\Repositories;

use App\Systemrezerwacji\interfaces\BackendRepositoryInterface;
use App\Models\{TouristObject, Reservation};


class BackendRepository implements BackendRepositoryInterface {

    public function getOwnerReservations($request)
    {
        return TouristObject::with([

                  'rooms' => function($q) {
                        $q->has('reservations');
                    },

                    'rooms.reservations.user'

                  ])
                    ->has('rooms.reservations')
                    ->where('user_id', $request->user()->id)
                    ->get();
    }

    public function getTouristReservations($request)
    {

       return TouristObject::with([

                    'rooms.reservations' => function($q) use($request) {

                            $q->where('user_id',$request->user()->id);

                    },

                    'rooms'=>function($q) use($request){
                        $q->whereHas('reservations',function($query) use($request){
                            $query->where('user_id',$request->user()->id);
                        });
                    },

                    'rooms.reservations.user'

                  ])

                    ->whereHas('rooms.reservations',function($q) use($request){

                        $q->where('user_id',$request->user()->id);

                    })
                    ->get();
    }
    public function getReservationData($request)
    {

        return Reservation::with('user', 'room')

        ->where('room_id', $request->input('room_id'))
        ->where('day_in', '<=' ,$request->input('date'))
        ->where('day_out', '>=' , $request->input('date'))
        ->first();
    }

function datesBetween(startDt, endDt) {
  var between = [];
  var currentDate = new Date(startDt);
  var end = new Date(endDt);

  while (currentDate <= end) {
    between.push($.datepicker.formatDate('mm/dd/yy', new Date(currentDate)));
    currentDate.setDate(currentDate.getDate() + 1);
  }

  return between;
}

var Ajax = {
  get: function get(url, _success) {
    var data = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : null;

    var _beforeSend = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : null;

    $.ajax({
      cache: false,
      url: base_url + '/' + url,
      type: "GET",
      data: data,
      success: function success(response) {
        App[_success](response);
      },
      beforeSend: function beforeSend() {
        if (_beforeSend) App[_beforeSend]();
      }
    });
  }
};


var App = {
  GetReservationData: function GetReservationData(id, calendar_id, date) {
    App.calendar_id = calendar_id;


    Ajax.get('ajaxGetReservationData?fromWebApp=1', 'AfterGetReservationData', {
      room_id: id,
      date: date
    }, 'BeforeGetReservationData');

  },
  BeforeGetReservationData: function BeforeGetReservationData() {
    $('.loader_' + App.calendar_id).hide();


    $('.hidden_' + App.calendar_id).show();

  },
  AfterGetReservationData: function AfterGetReservationData(response) {
     $('.hidden_' + App.calendar_id + " .reservation_data_room_number").html(response.room_number); 

  }
};

$(document).on('click', '.dropdown', function (e) {
  e.stopPropagation();
});
1

Próbujesz dobrać się do zmiennej która nie jest obiektem.

$this->bR->getReservationData($request);

zwraca NULL.

Do poprawy ta metoda:

    public function getReservationData($request)
    {

        return Reservation::with('user', 'room')

        ->where('room_id', $request->input('room_id'))
        ->where('day_in', '<=' ,$request->input('date'))
        ->where('day_out', '>=' , $request->input('date'))
        ->first();
    }

Po pierwsze, nie możesz zakładać że owe zapytanie zawsze zwróci ci dane. Warunki zapytania nie zawsze muszą być spełnione.

Dlatego warto otoczyć całe zapytanie helper'em (nie wiem jaki jest odpowiednik w j. polskim) optional() która pozwala ominąć błędy i zwraca NULL w przypadku niepowodzenia.

optional(Reservation::with('user', 'room')
        ->where('room_id', $request->input('room_id'))
        ->where('day_in', '<=' ,$request->input('date'))
        ->where('day_out', '>=' , $request->input('date'))
        ->first());

Po drugie, warto by sprawdzić czy wartości z $request->input rzeczywiście cokolwiek zawierają.

Przykładowo:

if (empty($request->input('room_id'))) {
   return false; // lub jakąś inną wartość, przerywasz funkcje, nie wykonujesz zapytania do bazy

Po trzecie, jeśli metoda: $reservation = $this->bR->getReservationData($request); zwróci niepowodzenie (NULL, false, cokolwiek co nie jest obiektem) wówczas warto przekazać odpowiedni komunikat na front:

$reservation = $this->bR->getReservationData($request);

if (!$reservation) {
    return response()->json([
       'error' => 'wystapil blad',
    ]);
}

Podsumowując, projektując jakąkolwiek funkcjonalność musisz przewidzieć możliwe wiele scenariuszy i odpowiednio się na nie przygotować.

0

@N3: Po sprawdzeniu wartości $request->input poprzez if (empty($request->input('room_id'))) {
return false; daje false

1

Sprawdź czy z frontu jest cokolwiek wysyłane pod ten url.

W metodzie kontrolera wrzuć tą linijkę:

var_dump($request->all());

Jeżeli nie będzie nic, wówczas przejdź do frontu i sprawdź przed wysyłką ajax'a czy parametry:

id
date

zawierają cokolwiek. Prawdopodobnie źle przekazujesz wartości z formularza do ajax'a.

Natomiast jeżeli $request->all() zwróci jakieś dane wówczas użyj:

$room_id = data_get($request, 'room_id');
$date = data_get($request, 'date');

aby dobrać się do danych.

    public function getReservationData($request)
    {
        $room_id = data_get($request, 'room_id', 0);
        $date = data_get($request, 'date', 0):

         if (!$room_id || !$date)
            return false;

        return optional(Reservation::with('user', 'room')
        ->where('room_id', $room_id)
        ->where('day_in', '<=' , $date)
        ->where('day_out', '>=' , $date)
        ->first());
    }

Wyjaśnienie jak działa data_get: https://laravel.com/docs/8.x/helpers#method-data-get

0

Wrzuciłem w metodzie kontrolera var_dump($request->all());, i tablica jest pusta, tutaj ponizej przesyłam swój kod i tutaj pod funkcja onSelect wywołuje tą metodę z ajaxa App.GetReservationData({{ $room->id }}, {{ $o.$r }}, date );

``@extends('layouts.backend')

@section('content')

Kalendarz rezerwacji

@foreach( $objects as $o=>$object )

<?php $o++ ?>
    <h3 class="red">{{ $object->name }} obiekt</h3>


    @foreach( $object->rooms as $r=>$room )


        @push('scripts')
        <script>

        var eventDates{{ $o.$r }} = {};
        var datesConfirmed{{ $o.$r }} = [];
        var datesnotConfirmed{{ $o.$r }} = [];


        @foreach($room->reservations as $reservation)

            @if ($reservation->status)
                    datesConfirmed{{$o.$r}}.push(datesBetween(new Date('{{$reservation->day_in}}'), new Date('{{$reservation->day_out}}')));
            @else
                    datesnotConfirmed{{$o.$r}}.push(datesBetween(new Date('{{$reservation->day_in}}'), new Date('{{$reservation->day_out}}')));
            @endif

        @endforeach

        datesConfirmed{{$o.$r}} = [].concat.apply([], datesConfirmed{{$o.$r}});
        datesnotConfirmed{{$o.$r}} = [].concat.apply([], datesnotConfirmed{{$o.$r}});


        for (var i = 0; i < datesConfirmed{{ $o.$r }}.length; i++)
        {
            eventDates{{ $o.$r }}[ datesConfirmed{{ $o.$r }}[i] ] = 'confirmed';
        }

        var tmp{{ $o.$r }} = {};
        for (var i = 0; i < datesnotConfirmed{{ $o.$r }}.length; i++)
        {
            tmp{{ $o.$r }}[ datesnotConfirmed{{ $o.$r }}[i] ] = 'notconfirmed';
        }


        Object.assign(eventDates{{ $o.$r }}, tmp{{ $o.$r }});


        $(function () {
            $(".reservation_calendar" + {{ $o.$r }} ).datepicker({
                onSelect: function (date ) {


                    $('.hidden_' + {{ $o.$r }}).hide();
                    $('.loader_' + {{ $o.$r }}).show();

                    App.GetReservationData({{ $room->id }}, {{ $o.$r }}, date );


                },
                beforeShowDay: function (date)
                {
                    var tmp = eventDates{{ $o.$r }}[ $.datepicker.formatDate('mm/dd/yy', date)];
                //console.log(tmp);
                    if (tmp)
                    {
                        if (tmp == 'confirmed')
                            return [true, 'reservationconfirmed'];
                        else
                            return [true, 'reservationnotconfirmed'];
                    } else
                        return [false, ''];

                }


            });
        });


        </script>
        @endpush



        <h4 class="blue"> Pokój {{ $room->room_number }}</h4>

        <div class="row top-buffer">
            <div class="col-md-3">
                <div class="reservation_calendar{{ $o.$r }}"></div>
            </div>
            <div class="col-md-9">
                <div class="center-block loader loader_{{ $o.$r }}" style="display: none;"></div>
                <div class="hidden_{{ $o.$r }}" style="display: none;">


                    <div class="table-responsive">
                        <table class="table table-striped">
                            <thead>
                                <tr>
                                    <th>Room number</th>
                                    <th>Check in</th>
                                    <th>Check out</th>
                                    <th>Guest</th>

                                    <!-- Lecture 29 -->
                                    @if( Auth::user()->hasRole(['admin','owner']) )
                                    <th>Confirmation</th>
                                    @endif

                                    <th>Delete</th>
                                </tr>
                            </thead>
                            <tbody>
                                <tr>
                                    <td class="reservation_data_room_number"></td>
                                    <td class="reservation_data_day_in"></td>
                                    <td class="reservation_data_day_out"></td>
                                    <td><a class="reservation_data_person" target="_blank" href=""></a></td>
                                    <!-- Lecture 29 -->
                                    @if( Auth::user()->hasRole(['admin','owner']) )
                                    <td><a href="#" class="btn btn-primary btn-xs reservation_data_confirm_reservation keep_pos ">Confirm</a></td>
                                    @endif

                                    <td><a class="reservation_data_delete_reservation keep_pos " href=""><span class="glyphicon glyphicon-remove"></span></a></td>
                                </tr>
                            </tbody>
                        </table>
                    </div>
                </div>

            </div>
        </div>

        <hr>

    @endforeach

@endforeach

@endsection

0

Musisz wybadać czemu we froncie nie są przekazywane dane. Pytanie czy tablica $objects na widoku zawiera cokolwiek? (Aby to sprawdzić użyj var_dump() lub dd())

Następnie, sprawdź czy tutaj:
App.GetReservationData({{ $room->id }}, {{ $o.$r }}, date ); wartości wypluwane z PHP'a nie są NULL'em.

0

@N3: Sprawdziłem , że tablica $objects na widoku nie jest pusta zrobiłem dd

``Illuminate\Database\Eloquent\Collection {#1434 ▼
#items: array:6 [▼
0 => App\Models\TouristObject {#1449 ▼
#connection: "mysql"
#table: "tourist_objects"
#primaryKey: "id"
#keyType: "int"
+incrementing: true
#with: []
#withCount: []
#perPage: 15
+exists: true
+wasRecentlyCreated: false
#attributes: array:5 [▼
"id" => 1
"name" => "enim"
"description" => "Corporis in et enim. Fuga quo dolores qui culpa sit ut. Consequatur iste explicabo id laudantium. Reiciendis aut soluta magnam unde."
"user_id" => 2
"city_id" => 9
]
#original: array:5 [▼
"id" => 1
"name" => "enim"
"description" => "Corporis in et enim. Fuga quo dolores qui culpa sit ut. Consequatur iste explicabo id laudantium. Reiciendis aut soluta magnam unde."
"user_id" => 2
"city_id" => 9
]
#changes: []
#casts: []
#classCastCache: []
#dates: []
#dateFormat: null
#appends: []
#dispatchesEvents: []
#observables: []
#relations: array:1 [▶]
#touches: []
+timestamps: true
#hidden: []
#visible: []
#fillable: []
#guarded: array:1 [▶]
}
1 => App\Models\TouristObject {#1448 ▶}
2 => App\Models\TouristObject {#1447 ▶}
3 => App\Models\TouristObject {#1446 ▶}
4 => App\Models\TouristObject {#1445 ▶}
5 => App\Models\TouristObject {#1444 ▶}
]
}

App.GetReservationData({{ $room->id }}, {{ $o.$r }}, date ); -> a tu niżej na metodzie getReservationData zrobilem dd i wynik ponizej

``public function getReservationData($request)
{
// var_dump($request->all());
dd($request);
$room_id = data_get($request, 'room_id', 0);
$date = data_get($request, 'date', 0);

     if (!$room_id || !$date)
        return false;

    return optional(Reservation::with('user', 'room')
    ->where('room_id', $room_id)
    ->where('day_in', '<=' , $date)
    ->where('day_out', '>=' , $date)
    ->first());
}


     I na tej metodzie ponizej zrobilem dump
``public function getReservationData($request)
{
    // var_dump($request->all());
    dd($request);                     
    $room_id = data_get($request, 'room_id', 0);
    $date = data_get($request, 'date', 0);

     if (!$room_id || !$date)
        return false;

    return optional(Reservation::with('user', 'room')
    ->where('room_id', $room_id)
    ->where('day_in', '<=' , $date)
    ->where('day_out', '>=' , $date)
    ->first());
}

Illuminate\Http\Request {#43 ▼
#json: null
#convertedFiles: null
#userResolver: Closure($guard = null) {#389 ▶}
#routeResolver: Closure() {#399 ▶}
+attributes: Symfony\Component\HttpFoundation\ParameterBag {#45 ▶}
+request: Symfony\Component\HttpFoundation\InputBag {#51 ▶}
+query: Symfony\Component\HttpFoundation\InputBag {#51 ▶}
+server: Symfony\Component\HttpFoundation\ServerBag {#47 ▶}
+files: Symfony\Component\HttpFoundation\FileBag {#48 ▶}
+cookies: Symfony\Component\HttpFoundation\InputBag {#46 ▶}
+headers: Symfony\Component\HttpFoundation\HeaderBag {#49 ▶}
#content: null
#languages: null
#charsets: null
#encodings: null
#acceptableContentTypes: null
#pathInfo: "/admin/ajaxGetReservationData"
#requestUri: "/admin/ajaxGetReservationData"
#baseUrl: ""
#basePath: null
#method: "GET"
#format: null
#session: Illuminate\Session\Store {#449 ▶}
#locale: null
#defaultLocale: "en"
-preferredFormat: null
-isHostValid: true
-isForwardedValid: true
-isSafeContentPreferred: null
basePath: ""
format: "html"
}

0

@Mateusz Mechuła: {{ $o.$r }} -> to klucze z tablic , np taki identyfikator po którym bedzie rozpoznawać, który to kalendarz i w ktorym chce dane jakie wyswietlic App.GetReservationData({{ $room->id }}, {{ $o.$r }}, date ); pierwsza wartosc to id pokoju, druga id kalendarza żeby wiedzieć , którego kalendarza dotyczy w przypadku pobranych rezerwacji, a trzecia data

0

@Mateusz Mechuła: poniżej sprobowałem dodać np id pokoju statycznie bez ajaxa i wczytało id pokoju ,

<div class="row top-buffer">
                <div class="col-md-3">
                    <div class="reservation_calendar{{ $o.$r }}"></div>
                </div>
                <div class="col-md-9">
                    <div class="center-block loader loader_{{ $o.$r }}" style="display: none;"></div>
                    <div class="hidden_{{ $o.$r }}" style="display: none;">


                        <div class="table-responsive">
                            <table class="table table-striped">
                                <thead>
                                    <tr>
                                        <th>Room number</th>
                                        <th>Check in</th>
                                        <th>Check out</th>
                                        <th>Guest</th>

                                        <!-- Lecture 29 -->
                                        @if( Auth::user()->hasRole(['admin','owner']) )
                                        <th>Confirmation</th>
                                        @endif

                                        <th>Delete</th>
                                    </tr>
                                </thead>
                                <tbody>
                                    <tr>
                                        <td class="reservation_data_room_number">{{ $room->room_number }}</td> <------- TUTAJ
                                        <td class="reservation_data_day_in"></td>
                                        <td class="reservation_data_day_out"></td>
                                        <td><a class="reservation_data_person" target="_blank" href=""></a></td>
                                        <!-- Lecture 29 -->
                                        @if( Auth::user()->hasRole(['admin','owner']) )
                                        <td><a href="#" class="btn btn-primary btn-xs reservation_data_confirm_reservation keep_pos ">Confirm</a></td>
                                        @endif

                                        <td><a class="reservation_data_delete_reservation keep_pos " href=""><span class="glyphicon glyphicon-remove"></span></a></td>
                                    </tr>
                                </tbody>
                            </table>
                        </div>
                    </div>

                </div>
            </div>

1 użytkowników online, w tym zalogowanych: 0, gości: 1