Andrew Vanusi Andrew Vanusi - 2 months ago 7
PHP Question

Call to a member function fill() on string

I got this error after trying to edit my data.
FatalErrorException in CRUDRenderHelper.php line 41: Call to a member function fill() on string

my CarCategoriesController code :

<?php

namespace App\Http\Controllers;

use App\Http\Requests;
use App\Models\CarCategory;
use Illuminate\Http\Request;
use Yajra\Datatables\Datatables;
use App\Http\Controllers\Base\MasterController;
use Route;
use Illuminate\View\View;

class CarCategoriesController extends MasterController
{
protected $indexView = 'CarCategories.index';
protected $createView = 'CarCategories.create';
protected $editView = 'CarCategories.create';
protected $routeBindModel = 'CarCategories'; //Route Model Binding name in RouteServiceProvider
protected $redirectPageWhenFormSuccess = 'CarCategories.index'; //Route Name
protected $title = 'Car Categories';

public function save(Request $request, $obj = null) {

if (!$obj) {
$obj = new CarCategory;
}
return $this->saveHandler($request, $obj);
}

//Must have this method if need datatable;
public function datatableBuilder($obj = null) {
return CarCategory::query();
}
}


CRUDRenderHelper code :

<?php

namespace App\Helpers\Traits;

use App\Helpers\Exceptions\ValidationException;
use App\Helpers\SessionHelper;
use DB;
use Exception;
use Illuminate\Http\Request;
use Laracasts\Flash\flash;
use Yajra\Datatables\Datatables;
use Illuminate\View\View;


trait CRUDRenderHelper
{
public function render(View $view, $route = null, $obj = null, $method = 'POST') {
$title = $this->title;
$appName = $this->appName;
$action = $this->action;
return $view->with(compact('title', 'appName', 'route', 'obj', 'method', 'action'));
}

public function getFormRoute($obj = null) {

if ($obj) {
$route = property_exists($this, 'updateFormRouteName') ?
$this->updateFormRouteName : $this- >routeBindModel.'.update';
return route($route, [$this->routeBindModel => $obj]);
}
$route = property_exists($this, 'saveFormRouteName') ?
$this->saveFormRouteName : $this->routeBindModel.'.store';
return route($route);
}

public function saveHandler(Request $request, $obj) {

try {

DB::beginTransaction();
$obj->fill($request->all());
if (!$obj->save()) {
throw new ValidationException($obj->errors());
}
DB::commit();
return $this->sendSuccessResponse($request);
} catch (ValidationException $e) {
DB::rollback();
\Log::error($e->errors);
return $this->sendErrorResponse($request, $e->errors);
} catch (Exception $e) {
DB::rollback();
\Log::error($e->getMessage());
return $this->sendErrorResponse($request,'Unable to process. Please contact system Administrator');
}

}

public function sendErrorResponse(Request $request, $errors) {

if ($request->ajax()) {
return response($errors, 400);
}
SessionHelper::setMessage($errors, 'danger');
return back()->withInput()->withErrors($errors);

}

public function sendSuccessResponse(Request $request) {

if ($request->ajax()) {
return response('Success', 200);
}

flash('Process Successfully', 'success');

if (property_exists($this, 'redirectPageWhenFormSuccess')) {
return redirect()->route($this->redirectPageWhenFormSuccess);
}

return back();
}

public function save(Request $request) {

return $this->saveHandler($request, $obj);
}

public function delete(Request $request, $obj) {

if (!$obj->delete()) {
throw new ValidationException($obj->errors());
}
return $this->sendSuccessResponse($request);
}

/**
* [datatableBuilder Build model query here]
* @return [Object] [Laravel Eloquent Model]
*/
public function datatableBuilder($obj = null) {}

public function makeDatatable($obj) {

return Datatables::of($obj)
->addColumn('action', function ($model) {
return $this->makeActionButtonsForDatatable($model);
})
->make(true);
}

/**
* [makeActionButtonsForDatatable Make buttons for datatables]
* @param [Object] $model [Eloquent Model]
* @return [string] [HTML script]
*/
public function makeActionButtonsForDatatable($model) {
$routeShow = property_exists($this, 'showRouteName') ?
$this->showRouteName : $this->routeBindModel.'.show';
$routeEdit = property_exists($this, 'editRouteName') ?
$this->editRouteName : $this->routeBindModel.'.edit';
$routeDelete = property_exists($this, 'deleteRouteName') ?
$this->deleteRouteName : $this->routeBindModel.'.destroy';
return '

<a href="'.route($routeEdit, [$this->routeBindModel => $model->id]).'"
class="btn btn-warning btn-xs edit">
<span class="fa fa-pencil"></span> Edit
</a>
<a id="delBtn" data-url="'.route($routeDelete, [$this->routeBindModel => $model->id]).'"
data-toggle="modal" data-target=" #modalDelete" data-title="Confirmation" data-table-name="#datatable" data-message="Do you want to delete this record?"
class="btn btn-danger btn-xs delete" >
<span class="fa fa-trash-o"></span> Delete
</a>';
}

protected function setAction($string) {

$this->action = $string;
return $this;
}

}


any idea ?

Answer

You probably have a route like this:

Route::post('car_category/{id}', 'CarCategoriesController@save');

You are receiving the an id from your route. By default, they are being passed to your controller methods as strings. In your code, you are passing the id, which is a string, to your saveHandler() method. That is why $obj->fill() on line 41 of your CRUDRenderHelper is throwing an exception.

Change your save method to check if $id is not null and if it is, create a new CarCategory and if not, then try to fetch it from the database using the given $id:

public function save(Request $request, $id = null)
{
    $obj = null;

    if ($id === null) {
        $obj = new CarCategory;
    } else {
        $obj = CarCategory::findOrFail($id);
    }

    return $this->saveHandler($request, $obj);
}
Comments