Using Model name from Variable - laravel

I have a variable which holds the model name like so
$fooTableName = 'foo_defs';
$fooModel = 'FooDefs';
Now I would like to insert in the DB using that model like so
$fooModel::insert([..foo..array...]);
Throws an error
"message": "Parse error: syntax error, unexpected '$fooModel' (T_VARIABLE), expecting identifier (T_STRING)",
Is it possible to do something like that? or will I be forced to use
DB::table('fooTableName')->insert([...foo...array...]);
If I do it in the latter way, the timestamps in the table are wrong. The created_at column is null and the updated_at has the value
EDIT 1
$model = CustomHelper::getNameSpace($this->tableNames[$i]);
// $model => /var/www/html/erp/app/Models/sales/InvoiceDefs
$model::insert($this->tableCollections[$this->tableNames[$i]]);
Most of them said that, it was namespace issue, so I have corrected it, but still it is throw error like
"message": "Class '/var/www/html/erp/app/Models/sales/InvoiceDefs' not
found",

What you are doing wrong is using model name as string, you need to refactor your code as like below :
$fooModel = 'App\Models\FooDefs';

I have a same situation before and i have created the function to do this
function convertVariableToModelName($modelName='',$nameSpace='')
{
//if the given name space iin array the implode to string with \\
if (is_array($nameSpace))
{
$nameSpace = implode('\\', $nameSpace);
}
//by default laravel ships with name space App so while is $nameSpace is not passed considering the
// model namespace as App
if (empty($nameSpace) || is_null($nameSpace) || $nameSpace === "")
{
$modelNameWithNameSpace = "App".'\\'.$modelName;
}
//if you are using custom name space such as App\Models\Base\Country.php
//$namespce must be ['App','Models','Base']
if (is_array($nameSpace))
{
$modelNameWithNameSpace = $nameSpace.'\\'.$modelName;
}
//if you are passing Such as App in name space
elseif (!is_array($nameSpace) && !empty($nameSpace) && !is_null($nameSpace) && $nameSpace !== "")
{
$modelNameWithNameSpace = $nameSpace.'\\'.$modelName;
}
//if the class exist with current namespace convert to container instance.
if (class_exists($modelNameWithNameSpace))
{
// $currentModelWithNameSpace = Container::getInstance()->make($modelNameWithNameSpace);
// use Illuminate\Container\Container;
$currentModelWithNameSpace = app($modelNameWithNameSpace);
}
//else throw the class not found exception
else
{
throw new \Exception("Unable to find Model : $modelName With NameSpace $nameSpace", E_USER_ERROR);
}
return $currentModelWithNameSpace;
}
How To user it:
Arguments
First Argument => Name of the Model
Second Argument => Namespcce of the Model
For Example we have the model name as Post
$postModel = convertVariableToModelName('Post');
dd($postModel::all());
Will returns all the values in the posts table
But in Some Situation You Model Will in the
Custom Namespace such as App\Models\Admin\User
So this function is created to overcome that
$userModel = convertVariableToModelName('User',['App','Models','Admin']);
dd($userModel::all());
You are feel free to customize the function
Hope it helps

Try the below one,
$fooModel = new FooDefs();
and then you can do the following also,
$fooModel->column1 = $value1;
$fooModel->column2 = $value2;
$fooModel->column2 = $value2;
$fooModel->save();
or
$fooModel->save([
'column1' => $value1,
'column2' => $value2,
'column3' => $value3,
])
Edited answer
$path = 'my\project\path\to\Models';
$fooModel = app($path.'\FooDefs');
$fooModel::save([
'column1' => $value1,
'column2' => $value2,
'column3' => $value3,
])
dd($fooModel ::all());
Try my edited answer.

When you have the name of class stored as string you can call method on that class by using the php method call_user_func_array like this
$class_name = "FooDefs";
call_user_func_array(array($class_name, "insert"), $data);
$data is an Array of data which will be past to the called function as arguments.
Just for simple advice It's will be Good if you save in the $class_name variable the FQN Fully Qualified Name of the class which is the __NAMESPACE__ follow by the name of the class. For sample purpose FQN look like Illuminate\Support\Facades\DB which you can get when you save you use User::class I presume you have some User model. That will return the Fully Qualified Name of the User model will will be App\User in case of Laravel.

$requests = $post['request'] // posting the data from view page
$models = "app\models".'\\'.$requests //geting the model
$model = $models::findOne($referenceId) //fetching value from database

Related

Laravel 8.6 firstOrCreate on variable model from URL

In a URL i pass the table name with the where parameters en map this using a JSON. The problem is now is. I use DB::table($table) but this doesn't allow firstOrCreate so i wanted to try it by model, but $table::were doesn't see $table as a model name. Even if i change it from 'establisments' to 'Estalishment'. Maybe i need to put App\ before it? Because the model is not in use. How can i get the object using a model from model names as in the URL?
URL:
&spec_code=CHI&department=surgery&department_code=SUR
JSON:
{
"establishments": { // $table name, but want it to be model)
"from1": "spec_code", // from url
"to1": "abc_id" // to column in database
},
"departments": {
"from1": "department",
"to1": "name",
"from2": "department_code",
"to2": "abc_id"
},
}
Controller:
foreach(JSON as $table => $field){
if(isset($field['from2'])){
$output[$table] = DB::table($table)->where($field['to1'], $request->input($field['from1']))->where($field['to2'], $request->input($field['from2']))->first();
}elseif(isset($field['from1'])){
$output[$table] = DB::table($table)->where($field['to1'], $request->input($field['from1']))->first();
// $output[$table] = $table::where($field['to1'], $request->input($field['from1']))->firstOrCreate(); //i want this.
// $output[$table] = "\App\\".$table::where($field['to1'], $request->input($field['from1']))->firstOrCreate();
}else{
$output[$table] = null;
}
}
If someone knows how i can get it to use the model so i can firstOrCreate(), that would make my code a lot cleaner.
Kind regards,
Jeff
There are many ways to do this.
Create an array using which you can get model
$models = [
'establishments' => \App\Models\Establishment::class,
'departments' => \App\Models\Department::class,
]
Then within loop you can get the model from the array using
foreach(JSON as $table => $field){
$models[$table]::firstOrCreate(/* */)
}
As i said there are many ways to fulfill your requirement. this is one way i would do.
By Default laravel does't have out of the box method to get the Model FQN based on the table name.
Because you can have model under different namespace.
But however you can do a workaround
$tableClassToFind = 'users';
$models = [
\App\Models\User::class,
//add your model(s) here
];
$modelClass = collect($models)
->map(function($eachModelFqn){
return [
'modelClass' => $eachModelFqn,
'tableName' => app($eachModelFqn)->getTable(),
];
})
->mapWithKeys(fn($value) => [$value['tableName'] => $value['modelClass']])
->get($tableClassToFind);
dd($modelClass);
Basically it will get all the table name along with the Model FQN and changing the value of $tableClassToFind will get the appropriate Model class.
Please all the models to $models variable.

How to call a class defined in the config

As the title suggests, I need to call a class.
Example config file within Laravel:
return [
'user' => App\User::class
];
The problem I have is that I need to do run the non-static method and not sure how to do that.
i.e. (new User())->getTable()
If you have this in your config file example_config_file.php:
return [
'user' => App\User::class,
];
You can call it like this using the new command to create an instance of the User model:
$userClass = config('example_config_file.user');
$user = new $userClass(); // blank instance of User model
Or like this if you want to use Eloquent methods:
$userClass = config('example_config_file.user');
$user = $userClass::find(1); // User model with id = 1
You can create a helper class and get any type of model like this:
class ModelHelper
{
public static function getModel($type, $id = null)
{
$modelClass = config("example_config_file.$type");
if($id) {
return $modelClass::find($id);
}
return new $modelClass();
}
}
Then in your code, whenever you need a user instance, call the helper class:
$user = ModelHelper::getModel('user'); // get a blank User model
$post = ModelHelper::getModel('post', 1); // get the post with id = 1

Treating belongsTo() that returns null

I have a model (request) that returns customer object base on it's id, it's receiving the id from a different machine so I want to treat non-existent values (i.e. id that doesn't exist returning the eloquent as null).
so for:
public function customer()
{
return $this->belongsTo('App\Customer', 'site_user');
}
I've tried the following:
public function getSiteUserAttribute()
{
if (!$this->relationLoaded('customer')) {
$this->load('customer');
}
return $this->getRelation('customer') ?: $this->nullCustomer();
}
and nullCustomer() :
private function nullCustomer()
{
$nonExist = 'non-exist-customer';
$siteUser = new \Illuminate\Support\Collection;
$siteUser->first_name = $nonExist;
$siteUser->last_name = $nonExist;
$siteUser->email = $nonExist;
return $siteUser;
}
Yet Laravel is returning an error I can't really make sense of:
Undefined property: App\Request::$site_user (View: /../../index.blade.php)`
it's obviously related to getSiteUserAttribute() which extrapolates site_user, but I can't understand what's the issue.
I can isset() for every place that this relation is called, but i'm working with a smart framework, so I doubt that would be the best practice.
Just to reiterate, I'm trying ot treat null belongsTo() that wouldn't break the view.
Rewrite nullCustomer() to return App\Customer not \Illuminate\Support\Collection:
I have not tested it though.
private function nullCustomer()
{
$nonExist = 'non-exist-customer';
$siteUser = new \App\Customer;
$siteUser->first_name = $nonExist;
$siteUser->last_name = $nonExist;
$siteUser->email = $nonExist;
return $siteUser;
}
It seems site_user field and site_user attribute is mixed.
The easiest way to get rid of the confusion, rename the field as site_user_id
As Murat Tutumlu said, you can't have a site_user attribute and a getSiteUserAttribute() accessor at the same time.
You can specify default values with withDefault():
public function customer()
{
return $this->belongsTo('App\Customer', 'site_user')
->withDefault([
'first_name' => 'non-exist-customer',
'last_name' => 'non-exist-customer',
'email' => 'non-exist-customer'
]);
}

Laravel create GUID for specific column

I would like to create a UUID/GUID for a specific column in Laravel 5. So i am using the Library from Webpatser to get an UUID in Laravel5.
I would like to set this as default for a specific column, so i guess i should use attributes, or?
But when i use
protected $attributes = array('guid' => Uuid::generate(4)->string);
ill always get an error with:
syntax error, unexpected '(', expecting ')'
I am not sure, because the syntax looks fine and when ill try
protected $attributes = array('guid' => 'dsadasfasfsaf');
Everything works fine (guid is a varchar(36) field) - and
Uuid::generate(4)->string
returns a string.
Do i need anything else to create a default value for my model? Thanks in advance.
PHP can't parse non-trivial expressions in initializers.
You can do this:
class YourClass
{
protected $attributes;
function __construct()
{
$this->attributes = array('guid' => Uuid::generate(4)->string);
}
}
Or this by using the setter method:
class YourClass
{
protected $attributes;
public function setAttributes($attributes)
{
$this->attributes = $attributes;
}
}
$classInstance = new YourClass;
$classInstance->setAttributes(array('guid' => Uuid::generate(4)->string));

How to delete session in cakephp 3.0?

all code is in one controller
My code goes like this.
public function login()
{
$session = $this->request->session();
$session_event_id = $session->read('Events.event_id');
$session_division_id = $session->read('Events.division_id');
if(!$session_event_id || !$session_division_id) {
$event_table = TableRegistry::get('Events');
$event = $event_table->find('all', ['fields' => ['id'], 'order' => 'id desc'])->first();
$session->write('Events.event_id', $event->id);
$session_event_id = $session->read('Events.event_id');
$division_table = TableRegistry::get('Divisions');
$division = $division_table->find('all',['fields' => ['id'], 'conditions' => ['event_id' => $event->id]])->first();
$session->write('Events.division_id', $division->id);
$session_division_id = $session->read('Events.division_id');
}
}
By above code i am able to write and read session values but while logout i want to delete those session data
public function logout()
{
$session = $this->request->session();
$this->$session->delete();
return $this->redirect($this->Auth->logout());
}
Warning (4096): Object of class Cake\Network\Session could not be
converted to string [APP/Controller/UsersController.php, line 56]
Notice (8): Object of class Cake\Network\Session to string conversion
[APP/Controller/UsersController.php, line 56]
Error: Call to a member function delete() on a non-object File
/var/www/html/MEX/src/Controller/UsersController.php
You're looking for $this->request->session()->destroy();
http://book.cakephp.org/3.0/en/development/sessions.html#destroying-the-session
Just a tip - there's not much of a point for storing a variable $session for a function that small, where the reuse of $session isn't necessary. The only case I'd store $this->request->session(); in a variable is when I'm accessing the session for multiple read and writes all in the same function.
(As far as the error is concerned, #Eagle is correct in that you're referencing '$this' twice by the use of that stored variable.)
Thank You for your supports and help finally i found solution of my problem by myself
$session = $this->request->session();
$session->delete('Events.event_id');
$session->delete('Events.division_id');
by doing so, i am able to clear session data. Thank you

Resources