MoFish's avatar

Generic model :: cannot seem to get working correctly.

Hi,

My project has lots of model files which are mostly all the same, with exception of a couple. I had a little idea to create a generic model for any which don't have relationships and are basic. I am therefore trying to pass a $table name parameter into the model and hoping that it would all work itself out in the same way if you change the protected $table inside the model itself, but it seems to be having an issue.

I feel i am close, but clearly missing something.

Any help much appriciated on how this could be achieved.

Too few arguments to function App\Models\Crud::__construct(), 0 passed in

Model

Crud.php

class Crud extends Model
{
      use HasFactory;

      protected $table; // this works if i hardcode this to a value in the model directly
      protected $guarded = [];

      public function __construct($table)
      {
            $this->table = $table;
      }
}

PageController which extends CRUDController (below)

PageController

class PageController extends CRUDController
{

      protected $model;

      /*****************************
       ** CONSTRUCTOR
      *****************************/

      public function __construct()
      {
            $this->model = new Crud('pages'); // this is the table name parameter
      }
}

CrudController

CrudController

class CrudController extends Controller {

      protected $model;
      protected $fields;

      /*****************************
      ** INDEX
      *****************************/

      public function index()
      {
            $result = $this->model::all(); // should be get maybe?
            $data = array(
                  'result' => $result
            );
            return view("index")->with($data);
      }
}
0 likes
11 replies
Sinnbeck's avatar

Laravel has no idea of where to get that $table variable from in the constructor. This is needed as laravel needs to be able to new up models on the fly. So why not just use the property and create an empty model for each? Or maybe just use the query builder if you don't want to use a model for each

$this->query = DB::table('pages');
Sinnbeck's avatar

If you really want to use that method, you could add a setTable() method on the model to allow you to set it in the constructor

MoFish's avatar

@Sinnbeck

I’m sure I tried that but will try that again.

I tried passing $table through as before and using but setTable($table), but I’m sure it was complaining when I tried to use this.

Thanks for getting back to me so quickly.

Sinnbeck's avatar

@MoFish no don't pass it through the constructor at all. Only using the method

$this->model = new Crud;
$this->model->setTable('pages');
MoFish's avatar

@Sinnbeck

I tried this but i am getting the following response.

It appears to be looking for the models filename? cruds

Base table or view not found: 1146 Table 'mofish.cruds' doesn't exist

select * from `cruds`
public function __construct()
      {
            $this->model = new Crud;
            $this->model->setTable('pages');
MoFish's avatar

@Sinnbeck

SQLSTATE[42S02]: Base table or view not found: 1146 Table 'mofish.cruds' doesn't exist
select  * from  `cruds`

Crud.php (Model)

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

class Crud extends Model
{
      use HasFactory;

      protected $table;
      protected $guarded = [];

      public function __construct()
      {
            //$this->table = $table;
      }
}

Page Controller

<?php

namespace App\Http\Controllers;
use App\Models\Crud;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;

class PageController extends CRUDController
{

      protected $model;

      /*****************************
       ** CONSTRUCTOR
      *****************************/

      public function __construct()
      {
            $this->model = new Crud;
            $this->model->setTable('pages');
      }
      
}

Crud Controller

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Database\Eloquent\Model;

class CrudController extends Controller {

    protected $model;

    /*****************************
    ** INDEX
    *****************************/

    public function index()
    {
        $result = $this->model::all();
        $data = array(
            'result' => $result
        );
        return view("index")->with($data);
    }

}
Sinnbeck's avatar
Sinnbeck
Best Answer
Level 102

@MoFish this part is wrong. Call it dynamically

        $result = $this->model::all();
//try
        $result = $this->model->get();
MoFish's avatar

@Sinnbeck

That worked! unbelievable! i knew we must have been close! Thank you very much.

For all my other crud operations will these need to be updated from :: to -> also im assuming?

index
$this->model->get(); // this is now working

store
$this->model::create($request->all());

show/edit
$result = $this->model::findOrFail($id);

update
$item->update($request->all());

destroy
$this->model::destroy($id);
Sinnbeck's avatar

@MoFish Yes, never use :: in those model calls as that is a static call and will try to do new Crud again. Replace it with ->

1 like

Please or to participate in this conversation.