Laravel 5 - Namespace + Dynamic Model - php

I have a very basic function to delete stuff on a simple website on Laravel 4.x that works like this:
public function delete()
{
...
$Model = Input::get('Model');
$Action = $Model::find($Id);
...
}
Now on Laravel 5, I'm trying to do the same but so far I can't because the namespaces. Since the $Model is dynamic I don't want to make use for everything.
And something like this:
use App\C\Models as Model;
public function delete()
{
...
$Action = Model\$Model::find($Id);
...
}
Simple do not works. What'd be the right approach to get this to work?

Simply store the namespaced classname as a string first:
$Model = Input::get('Model');
$NamespacedModel = '\\Model\\' . $Model;
$Action = $NamespacedModel::find($Id);

In the same case, My code is like this...
public function FunctionName(Request $request)
{
$modelName = $request->model;
$model = '\\App\\Models\\'.$modelName;
$q = $model::find($request->id);
$q->someColumn = 'someValue';
$q->save();
return back();
}
Note: I am using Laravel 8

Related

Import Model via Ajax Request Laravel - without namespacing the model

I am trying to import a model via an Ajax request without namespacing the model.
public function dataTypeRender(Request $request)
{
$input = request()->all();
$model = $request->input('model'); //this is the model name
$cols = $request->input('cols');
$modelTest = $model::all(); //not working
dd($modelTest);
}
Is there a way to do this? I'm trying to then do something with the model data.
I think without namespace it gonna be a little harder, because your model could be any model, but i think this could help you.
public function example(Request $request){
$data = $request->all(); //get All data request
$namespace = 'App\\'; //set namespace
$modelWithNameSpace = $namespace.$data['model']; //concat namespace and model name
$model = str_replace("'", "", $modelWithNameSpace); //remove quotes (idk if it's the best approach)
return $model::all(); //return the modell with all
}
This seemed to work nicely.
$model = 'App\\' . $request('model'); // adjust for the namespace/folder where you put your models
$data = (new $model)->all();
or
$data = (new $model)->find(1);

Laravel calling a controller function from a model factory

I am building some tests in my Laravel 5.5 project.
In my GalleryFactory I need to generate a 'link', I have written this code inside a function in my GalleriesController like so;
private function generateUrlLink()
{
$generatedLink = str_random(8);
$existingGalleryWithGeneratedLink = Gallery::where('link', $generatedLink)->first();
while (!is_null($existingGalleryWithGeneratedLink)) {
$generatedLink = str_random(8);
$existingGalleryWithGeneratedLink = Gallery::where('link', $generatedLink)->first();
}
return $generatedLink;
}
I don't want to write this code twice in the controller and also the factory as i might want to modify it someday, so im wondering what the best way of going about this would be?
Any help would be fantastic.
Thanks.
The best way to go about this is to write this function in the eloquent model instead of the controller and then calling the function from the model.
public static function generateUrlLink()
{
$generatedLink = str_random(8);
$existingGalleryWithGeneratedLink = Gallery::where('link', $generatedLink)->first();
while (!is_null($existingGalleryWithGeneratedLink)) {
$generatedLink = str_random(8);
$existingGalleryWithGeneratedLink = Gallery::where('link', $generatedLink)->first();
}
return $generatedLink;
}
Hopefully, this works.

Laravel: One Controller for multiple Models

I'm currently rebuilding my vanilla-PHP-App with Laravel and I have the following problem.
I have multiple database-tables, that represent word categories (noun, verb, adverb, ...). For each table I created a separate Model, a route::resource and a separate resource-Controller. For example:
NomenController.php
public function show($id)
{
$vocab = Nomen::find($id);
return view('glossarium.vocab_update', compact('vocab'));
}
and
VerbController.php
public function show($id)
{
$vocab = Verb::find($id);
return view('glossarium.vocab_update', compact('vocab'));
}
...which are essentially the same except the Model class.
I don't want to create a separate Controller for each model, that does exactly the same. What would be the most simple and elegant way to solve this?
Should I just create a VocabController.php and add a parameter for the Model-name like:
Route::resource('/vocab/{category}', 'VocabController');
and then add a constructor method in this controller like
public function __construct ($category) {
if ($category == 'nomen') {
$this->vocab = App\Nomen;
}
else if ($category == 'verb') {
$this->vocab = App\Verb;
}
}
I wonder if there is a simpler method to do that. Can I somehow do this with Route Model Binding?
Thanks in advance
Simply create a trait like this in App\Traits, (you can name it anything... Don't go with mine though... I feel its pretty lame... :P)
namespace App\Traits;
trait CommonControllerFunctions {
public function show($id) {
$modelObject = $this->model;
$model = $modelObject::find($id);
return view('glossarium.vocab_update', compact('model'));
}
}
and in your NomenController and VerbController, do this:
use App\Traits\CommonControllerFunctions;
class NomenController {
use CommonControllerFunctions;
protected $model = Nomen::class;
}
and
use App\Traits\CommonControllerFunctions;
class VerbController {
use CommonControllerFunctions;
protected $model = Verb::class;
}
Note: Please note that this example is just a work-around for your particular situation only... Everyone practices code differently, so this method might not be approved by all...
I think the simpliest way it to create only one controller, eg VocabController with methods nomen, verb and whatever you want.
Routes:
Route::get('/vocab/nomen/{nomen}', 'VocabController#item');
Route::get('/vocab/verb/{verb}', 'VocabController#item');
And the model binding:
Route::model('nomen', 'App\Nomen');
Route::model('verb', 'App\Varb');
Then your method shoud look like that:
public function item($item)
{
return view('glossarium.vocab_update', $item);
}
Keep in mind, that $item is already fetched model from the database.

Laravel 5.2 - creating a model from a variable

I am trying to access dynamically models so that I can get the count for each of them depending on which string I pass to the function.
This is what my function in the controller looks like:
public function numberOf(Request $request){
$modelName = $request['option'];
$model = new $modelName;
$data = $model->count();
return json_encode($data);
}
But when I pass a string, like in this case 'Article' I get an error:
Fatal error: Class 'Article' not found
Even though I am calling it in the controller:
use App\Article;
I had to add App to model name, so that my function looks like this now and everything works fine now:
$modelName = 'App\\'.$request['option'];
$model = new $modelName;
$data = $model->count();
return json_encode($data);

Proper way of re-using and passing multiple queries in yii2

My website has Object as the model and ObjectSearch as the searchModel. I realized that I am already having a lot of duplicates in my two different controllers. For example, FirstController has this:
$arr = Yii::$app->db->createCommand('SELECT id, name, address
FROM hosts)->queryAll();
Then at some part of my website SecondController also needs to use that same query.
How can I re-use that query over and over again from different controllers?
I am talking about this:
public function search($params)
{
$query = Host::find();
$dataProvider = new ActiveDataProvider([
'query' => $query,
]
]);
.
.
.
return $dataProvider;
}
I have another question also. I am planning to do different queries. What is the best approach for making another query? Should I use that
public function search($params)
again and maybe add on the parameter like this?
public function search($params, $cond)
{
if ($cond == true) {
$query = *something;
}
else {
$query = *something_else;
}
.
.
.
return $dataProvider;
}
In your root folder, you are having component folder. Inside component folder, create one page like UserInfoComponent.php. This page will be common and can be use anywhere.
This is the Directory Structure
YourProjectFolder
->assets
->commands
->components
->UserInfoComponent.php
.
.
UserInfoComponent.php
<?php
namespace app\components;
use Yii;
use yii\base\Component;
class UserInfoComponent extends Component
{
.
.
public function getUserDetails() {
$arr = Yii::$app->db->createCommand('SELECT id, name, address FROM hosts')->queryAll();
return $arr;
}
.
.
.
}
Now, how to call this function in your controller or view.
Controller or view
<?
$arrValue = Yii::$app->userinfo->getUserDetails();
?>
For common function you can create an helper class
namespace myapp\myhelperdir
class MyQueryHelper
{
public static function mySelectFunction ($param)
{
// your code for function
return $yourResult;
}
then you can refer to these function in every part of your project simply adding
use myapp\myhelperdir\MyQueryHelper
$myResult = MyQueryHelper::mySelectFunction($myParam);

Categories