I am trying to simply save a model to the database via a controller without setting the fields directly but instead having them set in the constructor of said object.
Here is the class handling the logic. If the commented out line
//$todoItem->item = $todo; is uncommented, it works fine and saves whatever is entered in $todo in the database. However, I would like to set that value in the constructor of the task object and not need to manually specify it. I found this question: Laravel with Eloquent doesn't save model properties on database suggesting I could set the property as protected and have it work, but that still does not.
NewTodo.php
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class NewTodo extends Controller
{
public function saveTodoItem(Request $request)
{
$todo = $request->input('content');
$todoItem = new \App\Task($todo);
//$todoItem->item = $todo;
$todoItem->save();
return view('testview', ['name' => $todoItem->getItem()]);
}
}
Task.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Task extends Model
{
protected $item = null;
function __construct($newItem)
{
$this->item = $newItem;
}
function getItem()
{
return $this->item;
}
}
Summary, database entry being stored as blank unless $todo->item is manually set when from what I can $todo->item is being set in the constructor.
You don't need to specify these in the constructor. You can use Mass Assignment
Model:
class Task extends Model
{
protected $fillable = ['item'];
}
Controller:
class NewTodo extends Controller
{
public function saveTodoItem(Request $request)
{
$todo = $request->input('content');
$todoItem = new \App\Task::create(['item' => $todo]);
return view('testview', ['name' => $todoItem->getItem()]);
}
}
Related
I’m kind of new to Laravel and the whole API architecture, so my question may seem dumb at first.
My basic setup:
Laravel 8;
PHP 8;
routes\api.php
Route::post('/categories/',[ApiCategoriesInsertController::class, 'insertCategories'], function($insertCategoriesResults) {
return response()->json($insertCategoriesResults);
})->name('api.categories.insert');
\app\Http\Controllers\ApiCategoriesInsertController.php (created with php artisan make:controller)
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
// Custom models.
use App\Models\CategoriesInsert;
class ApiCategoriesInsertController extends Controller
{
private mixed $ciAPI;
public function __construct(Request $req)
{
}
public function insertCategories(Request $req): array
{
$this->ciAPI = new CategoriesInsert(['testing'=>'debug']);
return [‘status’ => ‘OK’];
}
}
\app\Models\CategoriesInsert.php (created with php artisan make:model)
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class CategoriesInsert extends Model
{
use HasFactory;
public function __construct(array $objParameters)
{
}
}
When I make a post to http://localhost:8000/api/categories, Laravel logs the following error:
local.ERROR: Too few arguments to function App\Models\CategoriesInsert::__construct(), 0 passed in … Too few arguments to function App\\Models\\CategoriesInsert::__construct(), 0 passed in …
Anyone knows what’s wrong or missing in my architecture?
Thanks!
Make your model's constructor compatible with parent.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class CategoriesInsert extends Model
{
use HasFactory;
public function __construct(array $attributes = [])
{
parent::__construct($attributes);
}
}
Also, notice, that when you call new CategoriesInsert(['testing'=>'debug']), you do not save the data in your database. Use:
$insert = new CategoriesInsert(['testing'=>'debug']);
$insert->save();
Or:
CategoriesInsert::create(['testing'=>'debug']);
you don't need to pass data to model
change your code to bellow code:
public function insertCategories(Request $req): array
{
CategoriesInsert::create(['testing' => 'debug']);
return [‘status’ => ‘OK’];
}
key of passed array is your filed name in database, and value stored data
also you should define fillable parameter in model
protected $fillable = [
'title',
'slug',
'priority',
];
I'm new to CodeIgniter 4 but I have previously used Laravel - so I do know what I'm doing for the most part. I'm trying to build a simple CRUD app on CI4 and in my UserController, it keeps saying that App\Models\User is not found. And as a result - anything I get from the model class, is NULL.
Here's my Model & Controller code:
<?php
namespace App\Models;
use CodeIgniter\Model;
class User extends Model
{
protected $table = 'users';
protected $primaryKey = 'id';
protected $allowedFields = ['name', 'email'];
public function getUsers()
{
return $this->findAll();
}
}
UserController.php:
<?php
namespace App\Controllers;
use App\Models\User;
class UserController extends BaseController
{
public function index()
{
$model = model(User::class);
$data['users'] = $model->getUsers();
return view('user_view', $data);
}
public function create()
{
return view('add_user');
}
public function store()
{
$model = model(User::class);
$data = [
'name' => $this->request->getVar('name'),
'email' => $this->request->getVar('email')
];
$model->insert($data);
return $this->response->redirect(site_url('users-list'));
}
}
The error is in the index() method. If I use the $model = model() approach - I get "getUsers() is NULL" error. If I use the $model = new User(); approach - I simply get "Model not Found". And as you can see - I already have included the App\Models\User in the header.
What am I missing?
I'm working with too many mysql large views. I don't want to use Eloquent Model for the views.
I created "ViewBalance extends Illuminate\Support\Facades\DB". Everything worked as I wanted.
But i need to set init() method for company scope.
How can I use the global scope without init() method?
ViewModel
<?php
namespace App\Models\Views;
use App\Facades\CoreService;
use Illuminate\Support\Facades\DB;
class ViewBalance extends DB
{
const COMPANY_COLUMN = 'company_id';
const TABLE = 'view_balances';
public static function init()
{
return parent::table(self::COMPANY_COLUMN)
->where(self::COMPANY_COLUMN, CoreService::companyId());
}
}
In Controller
<?php
$data = ViewBalance::init()->get(); // Worked!
I have answered my own question. Because, I don't want to edit my question for more complicate. I want to talk about a solution to this problem.
I added $table_view variable and getView() method in Laravel model. If you want, you can create trait for clean codes.
It can be accessed easily views. Also it is part of the main model.
For example;
Laravel Basic Account Model
class Account extends Model {
protected $table = 'accounts';
protected $table_view = 'view_accounts';
public function getView()
{
return \DB::table($this->table_view)->where('global_scope', 1);
}
}
Laravel Account Controller
class AccountController extends Controller {
public function index()
{
$items = (new Account)->getView()->paginate(20);
}
}
public function scopeActive($query)
{
return $query->where('active', true);
}
or
public function scopeInactive($query)
{
return $query->where('active', false);
}
I create alternative Id filed called alterId in database and use it in some cases instead of id field.
For example, on edit data client send alterId value instead of id...
Because it's part of a code that often repeats itself I extended Illuminate\Database\Eloquent\Model class with this class:
namespace App\NewModel;
use Illuminate\Database\Eloquent\Model;
class NewModel extends Model
{
public function __construct()
{
parent::__construct();
$this->attributes['alterId'] = $this->generateAlterId();
}
public static function convertIdToAlterId($alterId)
{
// some logic to convert if to alterId
}
public static function convertAlterIdToId($id)
{
// some logic to alterId to id
}
public function generateAlterId($tokenSize = 32)
{
// logic to generate alter id ftom time stamp or something like that...
}
}
that generate alterId automatically and has possibility of converting from one to the other.
My problem is when I try to seed some element with this extended model nothing happens, no errors and no inserted data in database.
For seeding I use this model
namespace App;
use Illuminate\Database\Eloquent\Model;
use \App\NewModel;
class TestModel extends NewModel
{
protected $fillable = ['name'];
protected $dates = ['created_at', 'updated_at'];
}
this simple factory:
use Faker\Generator as Faker;
$factory->define(App\TestModel::class, function (Faker $faker) {
return [
'name' => $faker->firstNameMale,
'created_at' => \Carbon\Carbon::now(),
'updated_at' => \Carbon\Carbon::now()
];
});
and seeder:
use Illuminate\Database\Seeder;
use \App\TestModel;
class TestModelsTableSeeder extends Seeder
{
/**
* Run the database seeds.
*
* #return void
*/
public function run()
{
//truncate
TestModel::truncate();
//create
factory(TestModel::class, 100)->create();
}
}
As I said before, nothing happens when I start the command
php artisan migrate:refresh --seed
even a error not showed. But if I change code and modify TestModel to inherits the Model instead of the NewModel then everything works fine, database get inserts!
What did I do wrong in this code?
I haven't tried to run your code, but I think you need to make it fillable:
protected $fillable = ['name','alterId'];
How to write model in Laravel without creating Database and with function getData that returns Json? Something like:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Table extends Model
{
protected $table = 'table';
protected $fillable = [
'atribute1',
'atribute2',
'atribute3',
'atribute4'
];
}
But without database.
I would be grateful for help
You need to extend Model only if you're using Eloquent.
If you just need to get json data from somewhere, create usual class which gets data from somewhere and returns JSON:
class MyModel
{
public function getJsonData()
{
$jsonData = // get json data from somewhere
return $jsonData;
}
}
Register this class in composer.json file, run composer dumpauto and use your class:
$model = new MyModel();
$data = $model->getJsonData();