Get a route prefix variable in the abstract base controller - laravel

So we are building a CMS for a school project and we need to make it dynamic in the way that there are multiple organisations. In the prefix of a group I add a $gid variable that represents the ID of this organisation.
Route::middleware('auth')->prefix('{$gid}/admin')->group(function()
So I also created an abstract base controller that every controller in the admin section will inherit.
abstract class BaseAdminController extends Controller
What I want now is the $gid variable from the route and parse it to the base controller in the constructor.
protected $gid;
public function __construct() {
$this->gid = .....;
}
Now I can access this ID everywhere instead of having to parse it to each individual controller and function.

You don't need to "parse" it in every action but you should keep it because otherwise you wouldn't be able to access the routes' other parameters because the first one is missing and Laravel wouldn't be able to assign the next one's correctly. And you don't need the dollar sign at the start of a parameter.
// routes/web.php
// ↓ No dollar sign here
Route::middleware('auth')->prefix('{group}/admin')->group(function() {
// Routes
});
// In any of your Controllers
use Illuminate\Http\Request:
class SomeController extends BaseController
{
public function index(Request $request, Group $group) // you might add more parameters here
{
// Access your $group model
}
}
If you don't need the group model, don't define the type of the parameter and the related data will not be loaded:
public function index(Request $request, $group) // Now $group is just a number

Related

How to know which method is called in Laravel controller

When a request comes to Laravel controller through application router, how can we determine which method is called inside that controller? I mean inside constructor or magic methods of the controller. Is it possible to know?
Consider the method that is called exists. So __call would not be the solution.
I have this Route:
Route::get('exam', [ExamController::class,'index']);
And I want to get index inside ExamController class. maybe in side __construct or ...
public function __construct()
{
// here I want to access the name of called method
}
__call magic method just give the method name if the method is'nt exist:
public function __call($method, $parameters)
{
// I have access to $method name here (index)
}
You can use the __FUNCTION__ or __METHOD__ PHP constants to obtain information about the function or class and function:
class SomeClass
{
public function aFunction()
{
echo __FUNCTION__;
}
public function anotherFunction()
{
echo __METHOD__;
}
}
$obj = new SomeClass();
$obj->aFunction(); // aFunction
$obj->anotherFunction(); // SomeClass::anotherFunction
Update
Let's assume whilst you might not have a function defined for a specific route, you know the name of a route you want to apply a specific middleware to. You can apply middelware to specific functions from the controller constructor:
public function __construct()
{
$this->middleware('auth', ['only' => ['index', 'create']]);
}
Alternatively just specify the middleware required for the route on the route definition.

Inconsistency with 'show' function

I've been working on a project for a few months now and I feel like I am seeing some inconsistency with how the public function show is working
I have a model and controller for a Location that has
public function show(Location $Location)
{
$Loc = Location::with('company:id,name')->findOrFail($Location);
return response()->json($Loc,200);
}
and that works just fine. Note the parameters.
I just made a new model and controller for Asset and it has this:
public function show(Asset $asset)
{
$AssetReturn = Asset::with('location:id,name,address')->findOrFail($asset);
return response()->json($AssetReturn,200);
}
but that does not work. it just returns empty. If i remove the class name from the parameters so its just
public function show($asset)
then it works as intended.
relation from asset model to location:
public function location()
{
return $this->belongsTo(Location::class);
}
According to the documentation, Laravel automatically resolves Eloquent models defined in routes or controller actions whose type-hinted variable names match a route segment name. For example:
Route::get('/assets/{asset}', function (App\Asset $asset) {
$asset->load('location:id,name,address');
return response()->json($asset);
});
Since the $asset variable is type-hinted as the App\Asset Eloquent model and the variable name matches the {asset} URI segment, Laravel will automatically inject the model instance that has an ID matching the corresponding value from the request URI. If a matching model instance is not found in the database, a 404 HTTP response will automatically be generated.
If you don't want this behavior and want to use findOrFail manually:
Route::get('/assets/{asset}', function ($assetId) {
$asset = App\Asset::with('location:id,name,address')->findOrFail($assetId);
return response()->json($asset);
});

recall the construct in codigniter

How to recall the construct as it contains all the required data for the page?
class Abc extends CI_Controller
{
public function __construct()
{
parent::__construct();
$this->load->model('xyz_m');
$this->data['info'] = $this->xyz_m->get(); //get data
}
public function 123()
{
/*view page code*/
}
public function 456()
{
/*insert code here*/
$this->123(); // redirect, need to load 123() with updated data from construct.
}
}
So, how do you make the __construct initiate again so you get a new updated results from database?
You should name your methods with letter first i.e. there is convention for method names uses descriptive words getProducts() or get_books or you will get PHP error for using numbers as method names. So in your case method names should be like a123() or b_456().
Second thing, regarding your need in question, since you assign data from DB using model to array $this->data, you would use it like:
class Abc extends CI_Controller
{
public function __construct()
{
parent::__construct();
$this->load->model('xyz_m');
$this->data['info'] = $this->xyz_m->get(); //get data
}
public function a123()
{
$this->load->view('a123_view', $this->data);//loading file APPPATH . 'a123_view.php' and passing created array to it
}
public function b_456()
{
/*insert code here*/
$this->a123(); // redirect, need to load 123() with updated data from construct.
}
}
In your APPPATH . 'a123_view.php':
<?php var_dump($info);//here you would call key of array you passed from controller as variable ?>
Check basics in CodeIgniter documentations. All this is described in General Topics section.

Laravel 5 : passing a Model parameter to the middleware

I would like to pass a model parameter to a middleware. According to this link (laravel 5 middleware parameters) , I can just include an extra parameter in the handle() function like so :
public function handle($request, Closure $next, $model)
{
//perform actions
}
How would you pass it in the constructor of the Controller? This isn't working :
public function __construct(){
$model = new Model();
$this->middleware('myCustomMW', $model);
}
**NOTE : ** it is important that I could pass different Models (ex. ModelX, ModelY, ModelZ)
First of all make sure that you're using Laravel 5.1. Middleware parameters weren't available in prior versions.
Now I don't believe you can pass an instantiated object as a parameter to your middleware, but (if you really need this) you can pass a model's class name and i.e. primary key if you need a specific instance.
In your middleware:
public function handle($request, Closure $next, $model, $id)
{
// Instantiate the model off of IoC and find a specific one by id
$model = app($model)->find($id);
// Do whatever you need with your model
return $next($request);
}
In your controller:
use App\User;
public function __construct()
{
$id = 1;
// Use middleware and pass a model's class name and an id
$this->middleware('myCustomMW:'.User::class.",$id");
}
With this approach you can pass whatever models you want to your middleware.
A more eloquent way of resolving this problem is to create a constructor method in the middleware, inject the model(s) as dependencies, pass them to class variables, and then utilize the class variables in the handle method.
For authority to validate my response, see app/Http/Middleware/Authenticate.php in a Laravel 5.1 installation.
For middleware MyMiddleware, model $myModel, of class MyModel, do as follows:
use App\MyModel;
class MyMiddleware
{
protected $myModel;
public function __construct(MyModel $myModel)
{
$this->myModel = $myModel;
}
public function handle($request, Closure $next)
{
$this->myModel->insert_model_method_here()
// and write your code to manipulate the model methods
return $next($request);
}
}
You don't need to pass the model to middleware, Because you already have access to model instance inside the middleware!
Lets say we have a route like this:
example.test/api/post/{post}
now in our middleware if we want to have access to that post dynamically we go like this
$post = $request->route()->parameter('post');
now we can use this $post, for example $post->id will give us the id of the post, or $post->replies will give us the replies belong to the post.

Codeigniter updating records in db table

I want to change a specific record in the database using codeigniter. The url should be like this mysite.com/users/edit/10.
Here the user having id=10 is being edited
users is the controller name and edit is a method.
Usually I do in this way
//code of the rest of controller
.....
function edit(){
$uid =$_REQUEST['uid'];
//database update code
}
...
Where a form is being posted deliberately to change the record
You're not clear at all on what you want, I just can give you some pointers.
In CI, you don't need (don't have to) use superglobals to access url parameters. It has a native system to manage uri segments, which became automatically accessible without the need to call them; they're available as arguments of the method you're accessing.
So, in a url like yours, mysite.com/users/edit/10, you'll have
Controller:
class Users extends CI_Controller {
public function edit($uid)
{
// $uid is automatically passed to this method and is already available
// here you do your operations
//for. ex.
$this->load->model('user_model');
$this->user_model->update_user($uid);
}
}
Model:
class User_model extends CI_Model {
function __construct()
{
parent::__construct();
}
function update_user($id)
{
$this->db->where('id',$id);
$fields = array('field1' => 'value1','field2' => 'value2'...);
$this->db->update('users',$fields);
}
}
If you provide further information I could expand my answer.

Resources