Codeigniter not taking arguments from URL - codeigniter

I have a function that needs to pull arguments from the URL like CI is supposed to do. But it's not doing it. My URL is domain.com/lasers/en/acme.
My class Lasers is:
class Lasers extends CI_Controller {
function __construct()
{
parent::__construct();
$this->load->model('products_model');
$this->load->model('common_model');
$this->load->model('select_country_model');
$this->load->model('markets_materials_model');
}
function index($lang = NULL, $laser = NULL)
{
$query = $this->products_model->get_product_content($laser, $lang);
}
The model is loaded in the constructor. The $lang I need is "en" and the $laser I need is "acme". So why isn't this working? The arguments in the function are in the correct order, so I can't see what's wrong.

By default you cant pass arguments to the index method of a controller
if you go to domain.com/lasers/en/acme it is looking in the lasers controller for a method called en.. (which doesn't exist) and trying to pass a single parameter of acme to it
Theres a few solutions, probly the easiest is to use a different method (not index) then use routes to make the URLs work.
add something like this to your config/routes.php
$route['^lasers/(:any)/(:any)'] = "lasers/get_products/$1/$2";
Then use a method like this instead of index:
function get_products($lang = NULL, $laser = NULL) {
$query = $this->products_model->get_product_content($laser, $lang);
}
.. OR you could use _remap to override the default behaviour

Does it work if you write "domain.com/lasers/index/en/acme"?
If you write domain.com/lasers/en/acme, it will look for the "En" function, $lang being "acme", and $laser remaining NULL.

Related

Returning same variable to every controller in laravel

I need to send the same result to almost every view page, so I need to bind the variables and return with every controller.
My sample code
public function index()
{
$drcategory = DoctorCategory::orderBy('speciality', 'asc')->get();
$locations = Location::get();
return view('visitor.index', compact('drcategory','locations'));
}
public function contact()
{
$drcategory = DoctorCategory::orderBy('speciality', 'asc')->get();
$locations = Location::get();
return view('visitor.contact', compact('drcategory','locations'));
}
But as you see, I need to write same code over and over again. How can I write it once and include it any function whenever I need?
I thought about using a constructor, but I cannot figure out how I can implement this.
You are able to achieve this by using the View::share() function within the AppServicerProvider:
App\Providers\AppServiceProvider.php:
public function __construct()
{
use View::Share('variableName', $variableValue );
}
Then, within your controller, you call your view as normal:
public function myTestAction()
{
return view('view.name.here');
}
Now you can call your variable within the view:
<p>{{ variableName }}</p>
You can read more in the docs.
There are a few ways to implement this.
You can go with a service, a provider or, like you said, within the constructor.
I am guessing you will share this between more parts of your code, not just this controller and for such, I would do a service with static calls if the code is that short and focused.
If you are absolutely sure it is only a special case for this controller then you can do:
class YourController
{
protected $drcategory;
public function __construct()
{
$this->drcategory = DoctorCategory::orderBy('speciality', 'asc')->get();
}
// Your other functions here
}
In the end, I would still put your query under a Service or Provider and pass that to the controller instead of having it directly there. Maybe something extra to explore? :)
For this, you can use View Composer Binding feature of laravel
add this is in boot function of AppServiceProvider
View::composer('*', function ($view) {
$view->with('drcategory', DoctorCategory::orderBy('speciality', 'asc')->get());
$view->with('locations', Location::get());
}); //please import class...
when you visit on every page you can access drcategory and location object every time
and no need to send drcategory and location form every controller to view.
Edit your controller method
public function index()
{
return view('visitor.index');
}
#Sunil mentioned way View Composer Binding is the best way to achieve this.

Laravel Backpack - getting current record from crud controller

In my crud controller I am trying to get the name of the person who is currently being edited.
so
http://192.168.10.10/admin/people/93/edit
In the people crud controller
public function setup() {
dd(\App\Models\People::get()->first()->name)
}
This returns the first person not the person currently being edited.
How do I return the current person (with an id of 93 in this example)
Ok, So since you use backpack look into CrudController to see how the method looks:
public function edit($id)
{
$this->crud->hasAccessOrFail('update');
$this->data['entry'] = $this->crud->getEntry($id);
$this->data['crud'] = $this->crud;
$this->data['fields'] = $this->crud->getUpdateFields($id);
$this->data['id'] = $id;
return view('crud::edit', $this->data);
}
So now you can overwrite the edit function and change whatever you want. You can even create a custom edit page if you so wish.
Setup on the other hand is usually used to add things like
$this->crud->addClause(...);
Or you can even get the entire constructor and put it in the setup method because setup call looks like this:
public function __construct()
{
// call the setup function inside this closure to also have the request there
// this way, developers can use things stored in session (auth variables, etc)
$this->middleware(function ($request, $next) {
$this->setup();
return $next($request);
});
}
So you could do something like \Auth::user()->id;
Also it's normal to work like this. If you only use pure laravel you will only have access to the current id in the routes that you set accordingly.
Rahman said about find($id) method. If you want to abort 404 exception just use method findOrFail($id). In my opinion it's better way, because find($id)->name can throw
"Trying to get property of non-object error ..."
findOrFail($id) first fetch user with specified ID. If doesn't exists just throw 404, not 500.
The best answer is:
public function edit($id)
{
return \App\Models\People::findOrFail($id);
}
Good luck.
you need person against id, try below
public function setup($id) {
dd(\App\Models\People::find($id)->name);
}

Laravel policies - passing the class as a variable to $user->can() method doesn't work

I have a route with dynamic model recognition. In other words, I take the desired model as an argument and use it in the controller. I have complex authorization in my app and I need to pass the model class name as a variable to the $user->can() method for using policies, but for some reason it doesn't work. Here's my code:
Policy:
public function view($user, Model $model) {
return $user->model_id == $model_id;
}
public function create($user) {
return $user->isAdmin();
}
Controller:
public function createModel($model) {
$model_class = $model . '::class';
if (Auth::user()->can('create', $model_class)) {
return $model_class::create();
}
return 'invalid_permissions';
}
If I hardcode the model class name it works. For example, if my model is 'Car' and in the controller I put:
if (Auth::user()->can('create', Car::class)) {
Anybody got any ideas why this is so and how to fix it? I hope that it's possible because I would have to change my whole concept if it isn't.
*Note: this is example code, not my actuall classes

Routing with parameters - Laravel

I'm trying to craft a route for a controller that will submit some data to a database. My URL is as follows:
http://example.co.uk/posts/5/edit?type=job
I've tried
Route::post('/posts/{id}/edit?type={role}', 'PostsContoller#store');
but am unsure if this will fly?
Don't add parameters in your route:
Route::post('/posts/{id}/edit', 'PostsContoller#store');
In your controller, just check if parameter exist:
$type = Input::has('type') ? Input::get('type') : null;
Don't worry about HTTP verb, as Input access for all verbs (POST,GET,PUT,DELETE...).
Edit
As pointed out by #Antoine, you can simply specify the default value in the get method
$type = Input::get('type', null);
I don't think that this is the right way to do it.
First way
If you change your route to
Route::post('/posts/{id}/edit/{role?}', 'PostsContoller#store');
You will then call the URL: GET posts/42/edit/job.
your store function in PostsController will be:
public function store($id, $role = null)
{
// some code
}
Second way
You can use another route like:
Route::post('/posts/{id}/edit', 'PostsContoller#store');
You will then call the URL: GET posts/42/edit?type=job
And you can get the type in your store function in PostsController:
public function store($id)
{
// $role will be null if type is not in the URL
$role = Input::get('type', null);
// additional code
}
I would personally go for the second way.

Passing Route Parameters to Filters when Using RESTful Controllers

I have searched around for long but nothing can quite fit my problem.
I am using RESTful controllers on my site. For some controller actions, some filters are needed and with this i do something like (i use the beforeFilter() function in the constructor):
<?php
class PostController extends BaseController {
public function __construct()
{
$this->beforeFilter('auth',array('only'=>array('getCreate','postCreate','getEdit','postEdit','postAddComment')));
$this->beforeFilter('csrf',array('only'=>array('postCreate','postEdit')));
// $this->beforeFilter('auth_post_edit', array('only'=>array('postEdit','getEdit')));
}
public function getIndex
{
$posts = Post::all();
return View::make('home')->with('posts',$posts);
}
public function getCreate()
{
return View::make('posts.create');
}
...
For the commented filter, however, it is meant to ensure that only the author of a post can edit the post, so i need to pass the post_id which is passed as a URI parameter, to the filter(or access it from the filter).
Some link showed how i can access parameters from the filter using the $route->getParameter('param') in the filter, but the problem is that because i have not even named my parameters(they are named in the controller actions), i am not able to access them from the filter using the above method.
So, how can i access route parameters from within the filter, or/and how do i name route parameters in RESTful controllers(not in their actions)?
You could use in your filter the Request::segment()
Route::filter('foo', function()
{
$param=Request::segment(2); //if the parameter is on the 2nd uri fregment.
$post=Post::find($param);
if ($post->author_id != Auth::user()->id)
{
return App::abort('404'); //or whatever
}
});

Resources