Custom URI routing by query string with CodeIgniter? - php

I am looking to make a custom route using the CodeIgniter framework. I am trying to make the URL like so:
http://localhost/accounts/Auth.dll?signin
So far I have tried adding the following to my routes.php config file:
$route['accounts/Auth.dll?signin'] = "accounts/signin";
but as you would guess, it doesn't work. I have also tried escaping the characters like this:
$route['accounts/Auth\.dll\?signin'] = "accounts/signin";
and that doesn't work either. I've also tried including the leading and trailing slashes .. that didn't work either. Anyone know by chance what could solve my issue?

I highly recommend to use a SEF routing.
But if for any reason you're not eager to, you could check the query string inside the Accounts Controller, and then invoke the proper method, as follows:
Router:
$route['accounts/Auth.dll'] = "accounts";
Controller:
class Accounts extends CI_Controller
{
public function __construct()
{
# Call the CI_Controller constructor
parent::__construct();
# Fetch the query string
if ($method = $this->input->server('QUERY_STRING', TRUE)) {
# Check whether the method exists
if (method_exists($this, $method)) {
# Invoke the method
call_user_func(array($this, $method));
}
}
}
protected function signin()
{
# Your logic here
}
}
This allows you to invoke the methods by query string automatically.

I am not sure, that its okay to use GET-params in routes.php config.
Try such way:
routes.php
$route['accounts/Auth.dll'] = "accounts/index";
accounts.php
public function index() {
if ($this->input->get('signin') != false) {
$this->signin();
}
}
private function signin() {
// some code
}
But, as for me, it's bad way.
I recommend you just use another routing:
/accounts/Auth.dll/signin
And etc.

Related

Laravel singleton not working across controller/ViewComposer

In Laravel, I have a class that I would like to make available to the service controller, make some changes to in the controller action, and then render out with a ViewComposer.
I have done this several times before without issue, but for some reason this time my usual approach is not working - clearly I'm doing something different, and I'm beginning to suspect I've fundamentally misunderstood an aspect of what I am doing.
I have a ServiceProvider with this register() method:
public function register()
{
$this->app->singleton(HelperTest::class, function ($app) {
$pb = new HelperTest();
$pb->test = "jokes on you batman";
return $pb;
});
}
Then in my controller I'm doing the following:
private $helper;
public function __construct(HelperTest $pb)
{
$this->helper = $pb;
$this->helper->test = "hahah";
}
And then I have a viewcomposer doing the following:
private $helper;
public function __construct(HelperTest $pb)
{
$this->helper = $pb;
}
public function compose(View $view)
{
$view->with('output', $this->helper->test);
}
When I call {{ $output }} in the blade view, I expect to see hahah, but instead I get jokes on you batman.
My debugging has shown that all three of these methods are definitely being called. It looks to me like the ViewComposer is for some reason instantiating its own, fresh instance of the class. What am I doing wrong?
Thanks!
Execute php artisan optimize on your console, this will generate an optimized class loader for your application, then check if you can find your class HelperTest registered in services.php inside boostrap/cache. Until HelperTest is not registered there, Laravel IoC can't resolve your class.

Laravel - can I control routes by rule?

So I have a Laravel Controller (MainController.php) with the following lines:
...
public function _settings_a(){
return view('_settings_a');
}
public function _settings_b(){
return view('_settings_b');
}
public function _settings_c(){
return view('_settings_c');
}
public function _settings_d(){
return view('_settings_d');
}
public function _staff_a(){
return view('_staff_a');
}
public function _staff_b(){
return view('_staff_b');
}
public function _staff_c(){
return view('_staff_c');
}
...
And my routes.php is as follows:
Route::any('_staff_a''MainController#_staff_a');
Route::any('_staff_b''MainController#_staff_b');
...
etc.
It seems there are a LOT of lines and a LOT of things to change if I change my mind...
I was wondering if I can have some regex in routes.php and an equivalent regex in MainController.php for handling routes that begin with an underscore (_)?
Can any Laravel experts share some tips/suggestions? I'm quite new to the framework.
Sure - just add it as a parameter. E.g. like this:
Route::any('_staff_{version}', 'MainController#_staff');
public function _staff($version) {
return view('_staff_'.$version);
}
I don't think you need to mess with regex. You can use implicit controllers Route::controller() which isn't the BEST solution, but will do what I think you are wanting.
So instead of
Route::any(..)
you can do
Route::controller('url', 'MainController');
So your route to whatever 'url' is will send you to this controller. Follow that with a '/' and then add whichever method in the controller you want to call.
Here is an example:
My url: 'http://www.example.com/users'
// routes.php
Route::controller('users', UserController');
// UserController.php
public function getIndex()
{
// index stuff
}
Now I send a request like: http://www.example.com/users/edit-user/125
// UserController.php
public function getEditUser($user_id)
{
// getEditUser, postEditUser, anyEditUser can be called on /users/edit-user
// and 125 is the parameter pasted to it
}
Doing it this way should allow you to be able to just send a request (post or get) to a url and the controller should be able to call the correct method depending on the url.
Here are some more rules about it: http://laravel.com/docs/5.1/controllers#implicit-controllers

Laravel 4.1 - Controller throw error when I try to load view with layout

I'm trying to load a blade view with layout, but I get this error:
"Attempt to assign property of non-object"
The structure is the following:
Route:
Route::pattern('controller', '\w+');
Route::get('{controller}', function($controller) {
$controllerClass = $controller.'Controller';
App::make($controllerClass)->index();
});
Controller:
class PricesController extends BaseController {
protected $layout = 'layouts.master';
public function index()
{
$this->layout->content = View::make('prices.index');
}
}
The debug says the issue is at line $this->layout->content = View::make('prices.index');
The views are fine... I have layouts folder with master.blade.php and I also have prices folder with index.blade.php.
The content section is exists as well with #stop and the #yield is there in the layout.
In the BaseController there is the setupLayout method:
protected function setupLayout()
{
if ( ! is_null($this->layout))
{
$this->layout = View::make($this->layout);
}
}
What is the problem? Why I get that exception?
Thank you!
I know I helped you in the #laravel irc channel but there are 3 things here for any others with this problem.
This is not a good use of route files. Controller implicit routing is hard to maintain if your app gets larger. Consider using Route::resource instead if you're just trying to save a few lines of code. But I'll give you the benefit of the doubt.
You'll want to use the nest method for your layout, i.e. $this->layout->nest('content', 'prices.index');
The setupLayout() function is not being called because you are calling index() directly on the object. This is not how Laravel normally processes controllers.
I'm not going to walk through the entire routing process but if you look at vendors/laravel/framework/src/Illuminate/Routing/ControllerDisplatcher.php on line 89 you will see:
protected function call($instance, $route, $method)
{
$parameters = $route->parametersWithoutNulls();
return $instance->callAction($method, $parameters);
}
Let's look at vendors/laravel/framework/src/Illuminate/Routing/Controller.php on line 227 and you will see:
public function callAction($method, $parameters)
{
$this->setupLayout();
$response = call_user_func_array(array($this, $method), $parameters);
... irrelevant stuff omitted ...
}
These reason I show these things is show the magic Laravel is doing behind the scenes.
Basically you are skipping that magic and just calling PricesController->index() directly instead of going through the router. This is why setupLayout is never being called and you will get an exception because there is no $this->layout object yet created.

Codeigniter Routing - Using it too much?

I'm new to Codeigniter, and I'm trying to get accustomed to it by converting an old site into CI.
One thing I'm having trouble understand is the routing. If I don't want to have my url structure like /controller/method/id, I have to change it to something like $route['controller/(:num)'] = "controller/method/$1"; in routes.php. It just seems inefficient to me, is there something else I should be doing?
For example, on my site, the urls are /game/4242 and /player/SomeDude
Well, routing is effecient - the alternative is remapping your controllers.
Let's take a look at both possibilities.
An imaginary situtation:
At a later point, you'd like to allow your users to show badges/medals/achievements/something on their profile.
With routing, you can achieve it like this:
$route['player/(:any)/(:any)'] = "player/show_$2/$1";
$route['player/(:any)'] = "player/show_profile/$1";
And your controller could in turn look like this:
class Player extends CI_Controller
{
public function show_profile( $username )
{
// the profile info
}
public function show_badges( $username )
{
// the profiles badges
}
public function show_scores( $username )
{
// the profiles scores
}
}
}
Basically, this allows you to simply add another method in your controller prefixing the method with show_ (like public method show_friends( $username ) )and you can access it instantly by going to /player/SomeDude/friends
Looking at the alternative, remapping your controller would allow you not to use routes, but write a controller like this:
class Player extends CI_Controller
{
public function _remap($username, $params = array())
{
if(empty($username))
show_404();
$this->user = $this->user_model->find($username);
if(count($params) == 0)
$method = 'index';
else
$method = $params[0];
unset($params[0]); //No need to send the method along as a parameter
$method = 'process_'.$method;
if (method_exists($this, $method))
{
return call_user_func_array(array($this, $method), $params);
}
show_404();
}
public method process_index()
{
// the profile info
}
public method process_badges()
{
// the profiles badges
}
public method process_scores()
{
// the profiles scores
}
}
Personally, I like routing. I think it's transparent and makes my controllers look cleaner.

Zend Framework _forward to other action inside same controller

How can i forward to other action inside the same controller avoiding repeat all dispatch proccess ?
Example:
If i point to User Controller the default action is indexAction() inside this funciton i use _forwad('list') ... but all dispatch proccess are repeated.. and i dont that
Whats is the right way ?
Usually, you will install routes to redirect your users to the proper (default) action, instead of the index action (read how to redirect from a given route using Zend_Router). But you can do everything manually if you really want to (however this is called "writing hacker code to achieve something dirty") directly from the controller.
Change your "view script" to be rendered, then call your action method....
// inside your controller...
public function indexAction() {
$this->_helper->viewRenderer('foo'); // the name of the action to render instead
$this->fooAction(); // call foo action now
}
If you tend on using this "trick" often, perhaps you may write a base controller that you extend in your application, which can simply have a method like :
abstract class My_Controller_Action extends Zend_Controller_Action {
protected function _doAction($action) {
$method = $action . 'Action';
$this->_helper->viewRenderer($action);
return $this->$method(); // yes, this is valid PHP
}
}
Then call the method from your action...
class Default_Controller extends My_Controller_Action
public function indexAction() {
if ($someCondition) {
return $this->_doAction('foo');
}
// execute normal code here for index action
}
public function fooAction() {
// foo action goes here (you may even call _doAction() again...)
}
}
NOTE : this is not the official way to do it, but it is a solution.
We Can Also use this Helper To redirect
$this->_helper->redirector->gotoSimple($action, $controller, $module, $params);
$this->_helper->redirector->gotoSimple('edit'); // Example 1
$this->_helper->redirector->gotoSimple('edit', null, null, ['id'=>1]); // Example 2 With Params
If you don't want to re-dispatch there is no reason you can't simply call the action - it's just a function.
class Default_Controller extends My_Controller_Action
{
public function indexAction()
{
return $this->realAction();
}
public function realAction()
{
// ...
}
}
You could also create a route. For example I have in my /application/config/routes.ini a section:
; rss
routes.rss.route = rss
routes.rss.defaults.controller = rss
routes.rss.defaults.action = index
routes.rssfeed.route = rss/feed
routes.rssfeed.defaults.controller = rss
routes.rssfeed.defaults.action = index
Now you only need one action and that is index action but the requess rss/feed also goes there.
public function indexAction()
{
...
}

Categories