Laravel eloquent issue with constructor - php

I have a model which contains many methods.
class UserModel extends Eloquent{
private $active;
function __construct() {
$this->active = Config::get('app.ActiveFlag');
}
protected $table = 'User';
protected $fillable = array('usr_ID', 'username');
public function method1(){
//use $active here
}
public function method2(){
//use $active here
}
}
Controller:
$user = new UserModel($inputall);
$user->save();
Without constructor, it works fine. However, with constructor it doesn't save the user (the query which is generated doesn't have any fill attributes or values). The query is as follows:
insert into User() values();
Any inputs please?

Well yes, that's because you override the Eloquent constructor which is responsible to fill the model with values when an array is passed. You have to pass them along to the parent with parent::__construct():
public function __construct(array $attributes = array()){
parent::__construct($attributes);
$this->active = Config::get('app.ActiveFlag');
}

Your model's constructor doesn't accept any parameters - empty (), and you are creating new instance of UserModel in your controller adding $inputall as a parameter.
Try to refactor your contructor according to this:
class UserModel extends Eloquent {
public function __construct($attributes = array()) {
parent::__construct($attributes);
// Your additional code here
}
}
(Answer based on other Eloquent contructor question)

Related

Laravel 5.6 database operations in model

I have a controller called UserController, in that controller i am inserting a row of data to table "user" like this
$user = new UsersModel();
$user->first_name = $request->input('firstName');
$user->last_name = $request->input('lastName');
$user->about = $request->input('userAbout');
$user->join_date = date('Y-m-d');
$user->save();
My Question is, can i write this in my model called UsersModel???
Something Like,
( The insertData($data) is called from controller class.)
class UsersModel extends Model
{
protected $fillable = ['id','first_name','last_name','about','image','join_date','created_at','updated_at'];
protected $table = 'users';
public function insertData($data) {
// nb: $data contains values of fileds
// insert operation
//also return some values
}
}
You don't need to define your own function when you can already do it through Eloquent by simply calling the static method create magically:
$ref = UsersModel::create([
'col' => 'val'
]);
where $ref contains the information about the created data.
No need to reinvent the wheel in this instance.
However, your own custom method is possible too, make sure your function is defined as static to allow you to use without an object reference.
Yes you can
you need to call the function from the controller like this
$data = ['YOUR ARRAY'];
$this->usersModel = new UsersModel();
$this->usersModel->insertData($data);
You can also do with static function
In Model
public static function insertData($data) {
In Controller
UsersModel::insertData($data);
Insert function
UsersModel::insert($data);

How can I make a specific function on action page to handle the form data?

I have a models.php page that contains the specification of form for a specific model.
models.php
$books = [
['Book Name', 'text' ],
['Author', 'text']
];
$vegetables = [
['Name', 'text'],
['Photo', 'file']
]
Now this page is accessed by an admin.php page, which generate an appropriate HTML form on the basis of the given name and input type.
I want to fill the form and send the data into a handle.php and handle the data with the specific function to fill the data into appropriate table.
handle.php
function books(){
// this will fill the details into table of books.
INSERT INTO BOOKS
name = $_POST['book_name']
author $_POST['author']
}
function vegetables(){
// this will fill the details into table of vegetables.
INSERT INTO VEGETABLES
name = $_POST['book_name']
photo = $_FILE['photo']
}
(If there's any other better way of doing this, so please mention, I'll do that way and delete my question.)
Here's my suggestion. As stated in the comments, this is just my way to do such things, it's not necessarily the best solution for every situation.
I have a base model, that defines all methods all model need to have in common. Here's a very simplified version:
class Model {
public $modelName = 'default';
public $id = null;
private $fields = [];
private $tableName = 'default';
private $tableDefinition = [];
private $idField = 'id';
public function insert($dataset) {
// do some database magic by using $this->fields, or $this->tableDefinition
$sql = "INSERT into {$this->tableName} ...";
...
return $id;
}
public function update($id, $dataset) {
// do some more database magic by using $this->fields, or $this->tableDefinition
}
// many more methods. To get data, delete, sort, ..
//...
}
Every model now extends this base model class and sets it's specific params, maybe even overrides some methods or adds special ones:
class Books extends Model {
public $modelName = 'book';
private $fields = ['bookName','Author'];
private $tableName = 'BOOKS';
private $tableDefinition = [
['bookName','varchar'],
['Author','varchar']
];
// private $idField = 'id'; // you can ommit that, if it's the default.
}
If Vegetables behaves different you can simply override a method:
class Vegetables extends Model {
public $modelName = 'vegetable';
// set all other properties...
// override insert() for example
public function insert($dataset) {
// do something that doesn't comply with the standard procedure
}
}
Then in handle.php you can do something like this:
<?php
$modelName = $request; // get it from your form, your url, ..
// & verify this model(file) exists.
$model = new $modelName();
$model->insert($dataSet);
Make a base interface BaseModel.php
which would have the basic signatures of insertion , updation and selection
Make a derived class booksModel.php and vegetablesModel.php that would implement the BaseModel class.
In this way, you have made your code extendable. If there is some common functionality, you can make the base class as Abstract class.
abstract class BaseModel {
abstract function add($dataObject);
abstract function get($dataObject);
}
class BooksModel extends BaseModel {
public function add($dataObject) {
/* Implementation */
}
public function get($dataObject) {
/* Implementation */
}
}
class VegetableModel extends BaseModel {
public function add($dataObject) {
/* Implementation */
}
public function get($dataObject) {
/* Implementation */
}
}

Laravel: Avoid to create instance of a model with a constructor in the controller

I'm following a course for Laravel 4 and the teacher did a code refactoring and introduced a magic method constructor in the controller
class UtentiController extends BaseController {
protected $utente;
public function __construct(Utenti $obj) {
$this->utente = $obj;
}
public function index() {
$utenti = $this->utente->all();
return View::make('utenti.index', ["utenti" => $utenti]);
}
public function show($username) {
$utenti = $this->utente->whereusername($username)->first(); //select * from utenti where username = *;
return View::make('utenti.singolo', ["utenti" => $utenti]);
}
public function create() {
return View::make('utenti.create');
}
public function store() {
if (! $this->utente->Valido( $input = Input::all() ) ) {
return Redirect::back()->withInput()->withErrors($this->utente->messaggio);
}
$this->utente->save();
return Redirect::route('utenti.index');
}
}
Thanks to this code I don't have to create a new instance of the Utenti model every time:
protected $utente;
public function __construct(Utenti $obj) {
$this->utente = $obj;
}
Now I can access the database with this simple approach:
$this->utente->all();
Whereas before, I had to do this:
$utente = new Utente;
$utente::all();
Does this type of technique have a name? (is it a pattern?).
My understanding is that every time the controller is invoked it automatically generates an instance of the User class (model) and applies an alias (reference) attribute $utente
Is that correct?
Also, here is the code for the Utenti model:
class Utenti extends Eloquent {
public static $regole = [
"utente" => "required",
"password" => "required"
];
public $messaggio;
public $timestamps = false;
protected $fillable = ['username','password'];
protected $table = "utenti";
public function Valido($data) {
$validazione = Validator::make($data,static::$regole);
if ($validazione->passes()) return true;
$this->messaggio = $validazione->messages();
return false;
}
}
This is called dependency injection or short DI. When creating a new instance of the Controller, Laravel checks the constructor for type hinted parameters (The ones that have a type defined like __construct(Utenti $obj){) If your controller has any of these Laravel tries to create an instance of the class and injects it into the constructor.
The reason why this is done is that it's becoming very clear what the dependencies of a class (in this case your controller) are. It gets especially interesting if you type hint an Interface instead of a concrete class. You then have to tell Laravel with a binding which implementation of the interface it should inject but you can also easily swap an implementation or mock it for unit testing.
Here are a few links where you can get more information:
Laravel docs IoC container
Method dependency injection in Laravel 5
StackOverflow - What is Inversion of Control?

passing arguments to Model constructor

How can i pass my arguments to the model constructor,i have the following code in my controller
public static function inbox(){
$user=Sentry::getUser();
$results=new Message($user->id);
$inbox=$results->inbox();
return $inbox;
}
And in my modal i am extending the parent modal constructor as follows
class Message extends \Eloquent {
private $user_id;
public function __construct($attributes = array()) {
parent::__construct($attributes); // Eloquent
}}
now i want to pass the $user_id to the Message modal constructor,how do i achieve this
when inserting data to the db using the Eloquent create nothing is being inserted into the database here is the code
Message::create(
array(
'msg_id'=>$result->id,
'subj'=>Input::get('subj'),
'content'=>Input::get('content'),
'sender_id'=>Input::get('sender_id'),
'receivers_id'=>$user->id,
'file'=>Input::get('file')
)
);
its like i have overidden built-in constructor of the Model class
You can use #PeterPopelyshko's approach and override the constructor or just use what Eloquent offers. Mass Assignment.
You can pass in attributes through your constructor by using an associative array:
$results = new Message(array(
'user_id' => $user->id
));
Just make sure to define all the properties, you want to be fillable in the $fillable array in your model:
class Message extends \Eloquent {
protected $fillable = array('user_id');
}
Note that you don't need the private $user_id if this is a database field. Laravel handles them in it's own $attributes array.
class Message extends \Eloquent {
private $user_id;
public function __construct($user_id, $attributes = array()) {
$this->user_id = $user_id;
parent::__construct($attributes); // Eloquent
}}
and then you can use it in your controller
$results=new Message($user->id);
and you can get access to $user_id within model like this $this->user_id

Saving from eloquent constructor in laravel

So, I'm currently working on a browser game in Laravel. So far I love the framework, but I haven't really got much experience, and I just can't get this to work.
Basically I'm trying to update all users whenever they are instantieted, as there is no reason update them when they are not used. But calling this function from the constructor doesn't update the user, it only works when I call the function outside the constructor.
Have I missed anything, or is it just not possible?
Thanks in advance!
<?php
class User extends Eloquent implements UserInterface, RemindableInterface {
use UserTrait, RemindableTrait;
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'users';
/**
* The attributes excluded from the model's JSON form.
*
* #var array
*/
protected $hidden = array('password', 'remember_token');
public function __construct($arguments = array())
{
parent::__construct($arguments);
$this->updateHp();
}
public function updateHp()
{
$this->hp_last = time();
$this->save();
}
}
Eloquent is a static class, data is fetched on query (find, first, get) and when you create a model you have just a blank model, with no data on it. This is, as example, the point where you have some data available:
public static function find($id, $columns = array('*'))
{
if (is_array($id) && empty($id)) return new Collection;
$instance = new static;
return $instance->newQuery()->find($id, $columns);
}
Before one of those query methods, you have void.
So you probably cannot do that during __construct because your model is still blank (all nulls). This is what you can do to make it, somehow, automatic:
First, during boot, create some creating and updating listeners:
public static function boot()
{
static::creating(function($user)
{
$user->updateHp($user);
});
static::updating(function($user)
{
$user->updateHp($user);
});
parent::boot();
}
public function updateHp()
{
$this->hp_last = time();
$this->save();
}
Then, every time you save() a model it will, before saving, fire your method:
$user = User::where('email', 'acr#antoniocarlosribeiro.com')->first();
$user->activation_code = Uuid::uuid4();
$user->save();
If you want to make it somehow automatic for all your users. You can hook it to a login event. Add this code to your global.php file:
Event::listen('user.logged.in', function($user)
{
$user->updateHp();
})
Then in your login method you'll have to:
if ($user = Auth::attempt($credentials))
{
Event::fire('user.logged.in', array($user));
}
In my opinion you shouldn't do that. If you use the code:
$user = new User();
you would like to be run:
$this->hp_last = time();
$this->save();
and what exactly should happen in this case? New user without id should be created with property hp_last ?
I think that's not the best idea.
You should leave it in the function then you can use:
$user = new User();
$user->find(1);
$user->updateHp();
That makes much more sense for me.

Categories