I know there are a couple of other topics about this subject, but non of them seems to fit my needs.
What I have
example.com/log/
LogsController.php
I have LogsController instead of LogController (plural) because CakePHP wants you to have controllers in plural.
But as you might know/notice, example.com/log/ will never use LogsController because of the missing 's' in the url.
Now, I want to have /log/* being redirected to /logs/*. Works perfectly fine with the following code:
Router::connect ('/log/*', array('controller'=>'logs'));
But, when I try to access example.com/log/actions/foo/bar it doesn't seem to work. So after some Googeling I found this:
Router::connect ('/log/:action/*', array('controller'=>'logs'));
Works great. But now when I'm trying to access example.com/log/ again, it says
Error: LogController could not be found.
Question
So my question is, how do I set up an alias for my url so that /log/ will use LogsController instead of trying to use LogController.
I have a few more Controllers where I'd like to change this, like flight => FlightsController, profile => ProfilesController.
Have a look at this question. It is about the same subject, but slightly different. It might help you in some way.
Ok, with the help of some other people on IRC and stuff like that. I found out the following.
A combination of
Router::connect('/flight/:action/*', array('controller'=>'flights'));
Router::connect('/flight/*', array('controller'=>'flights'));
does the trick. I tried this before, but in a other order, like so:
Router::connect('/flight/*', array('controller'=>'flights'));
Router::connect('/flight/:action/*', array('controller'=>'flights'));
which doesn't work.
So the first 2 lines of code in this post solved it for me. Another guy told me that the solution of Arun Jain isn't a proper solution, because it changes the nameconventions in the core as well. Which will cause problems with the FormsHelper and classes like that. So I think I will prefer the code in this post since this is just an alias instead of a core changing piece of script. Thanks for the help anyway.
To do this with routing the correct approach is as follows.
Router::connect('/flight', array('controller'=>'flights','action'=>'index'));
Router::connect('/flight/:action/*', array('controller'=>'flights'));
This tells the router that when an action is found in the URL to use it, but it no params are found then to default is to use the index action.
I have a slightly different take on all of this. The plural is more often the more accurate way to go with things but in occassions when the plural is just plain wrong, i add an exception into the Inflector class (/lib/Cake/Utility/Inflector).
In your example I would add log to this list of uninflected words. This means that system wide cake will not append the 's'. You'll have your LogController your views would sit in the Log view folder etc...
EDIT
I've come across a much neater way to do this from within app/config/bootstrap.php
Inflector::rules(
'plural',
array(
'uninflected' => array('log')
)
);
This would add log to the uninflected list without having to alter the files within the Core to allow easier version updating.
You can simply do it using following:
class LogsController extends AppController
{
public $name = 'Log';
..... YOUR REMAINING CODE ......
}
Your router connnect code will remain same. Kindly ask if it not worked for you.
Related
I come from the procedural PHP and am learning OOP with Laravel. What I learned so far is very interesting and will ease my developer's life (it's not my job btw).
So, for all my websites, I am using a slug property for all articles, categories, and so on.
I started to use the "str_slug" provided by Laravel which seems to do the job at 99%. The issue I get is when I have such title (in french): "J'ai mangé une pomme", the slug string I get is: "jai-mange-une-pomme" which, in french, is not correct. I would like "j-ai-mange-une-pomme".
It's not really an issue. I can do:
$slug = str_replace('\'','_',$input['name']);
$slug = str_slug($slug, '-');
It suits me well but I wonder how to use anytime I want to use it. I don't want to write it again and again and again.
In procedural, it's easy, I would write a function, such as thePerfectSlug(){} in a helpers.php file (still an example) and will use an include at the top of my index.php. That would do the job.
But in OOP and especially in Laravel (5.1), how can I do that?
Thanks
You still can achieve it with normal function. Laravel uses his own function which are stored in helpers.php file. You can make your own helpers.php file and add it to your main composer.json file at autoload.files.
If you would like to do it in OOP way, create a trait like App\Traits\Sluggify with your method and use it in any class that needs it.
I am working on an API via which I embed images of country flags on my website & several others.
I am taking in 3 parameters i.e
Country (Name of Country - ISO Code or Full Name)
Size (Dimension of Image)
Type (Styles like flat flag, shiny round flag etc...)
Now, have everything setup correctly but stuck in handling URI.
Controller -> flags.php
Function -> index()
What I have now is :
http://imageserver.com/flags?country=india&size=64&style=round
What I want
http://imageserver.com/flag/india/64/round
I went through some articles and made this route but all of them failed
$route['flag/(:any)/(:num)/(:any)'] = "welcome/index/country/$1/size/$2/style/$3";
$route['flag/(:any)/(:num)/(:any)'] = "welcome/index/$1/$2/$3";
$route['flag/(:any)/(:num)/(:any)'] = "welcome/index?country=$1&size=$2&style=$3";
I have also been having trouble with routes while writing my custom cms. Reading through your question, I see a couple issues that might very well be the answer you are looking for.
For starters, let's look at the routes you have tried:
$route['flag/(:any)/(:num)/(:any)'] = "welcome/index/country/$1/size/$2/style/$3";
$route['flag/(:any)/(:num)/(:any)'] = "welcome/index/$1/$2/$3";
$route['flag/(:any)/(:num)/(:any)'] = "welcome/index?country=$1&size=$2&style=$3";
If you want to run the index method from your flags class, which it looks like you do, you don't want to route to the welcome class at all. Currently, however, you are. Your routes should look like:
$route['flag/(:any)/(:num)/(:any)'] = "flags/index";
That way, Codeigniter will run the index method from your flags class. You don't have to worry about the country, size, or style/type in the route. The best option there would be to use the URI segment function like this:
$country = $this->uri->segment(2); //this would return India as per your uri example.
$size = $this->uri->segment(3); //this would return 64 as per your uri example.
$style = $this->uri->segment(4); //this would return round as per your uri example.
You could then use those variables to query your database and get the correct flag or whatever else you need to do with them.
So to restate my answer with a little more explanation as to why:
The routes you have currently are running the welcome controller/class and the index function/method of that controller/class. This, obviously, is not what you want. So you need to make sure your routes are pointing to the correct controller and function like I did above. The extra segments of the URI don't need to be in your route declaration, so you would then just use the uri_segment() function to get the value of each segment and do what you need with them.
I hope this helps you. I may not have found an answer for my problem, but at least I could provide an answer for someone else. If this seems confusing to you, check out the user guide at http://ellislab.com/codeigniter/user-guide. The main links you need for this are:
http://ellislab.com/codeigniter/user-guide/libraries/uri.html
and
http://ellislab.com/codeigniter/user-guide/general/routing.html
Let me know if you need more help or if this helped solve your problem.
I want to override the guestbook functionality. To be exact, I want to override the action_form_save_entry() function on [mysite]/concrete5/core/controllers/blocks/guestbook.php
I've tried to override it these ways:
[mysite]/controllers/blocks/guestbook.php
[mysite]/core/controllers/blocks/guestbook.php
noe of them works. I can't find any way how to override that file. The documentation here and here doesn't show how to override that /core/ directory. Their forum never helps. Google result also just get misled with the 'core' keyword. All the result just take the 'core' meaning as just what's exist on the /concrete5/ directory, not the exact true /concrete5/core
Looks like that /concrete5/core/ directory appear only on the newer version. CMIIW.
Btw, maybe I should also tell you what I want to do with that function. Probably you have another workaround for this instead of simply overriding it. I want to add SMS notification functionality to it. So whenever someone submit a new comment, an SMS would be sent to the admin of a particular page.
Yes, the /concrete/core directory structure is new to 5.6. Tutorials and documentation on c5 can be ... lacking ... but in this case it's just a matter of them being behind a bit.
The "real" guestbook controller is at /concrete/blocks/guestbook/controller.php. You'll notice that it's just a shell of a class:
class GuestbookBlockController extends Concrete5_Controller_Block_Guestbook {}
The file that you referenced defines Concrete5_Controller_Block_Guestbook.
So, the solution is to override the real controller, not whatever it extends (ie, the file that you were looking at). Thinking in this way, it should be clearer that you need to create a file at /blocks/guestbook/controller.php. In fact, just copy the controller.php that I referenced above because you need to keep the (sometimes multiple) classes. Then, you can override the particular function. (Don't forget to call parent::action_save_form_entry()).
I'm trying to learn more about the codeigniter framework by porting an existing website to it -- something that's not too complex, or so I thought.
Currently the site is replicated for its users and presents personalized data based on the url, for example, Joe might have his site at:
www.example.com/joe
www.example.com/joe/random-page.php
And you'd replace "joe" with any given user name. The URLs need to be structured this way: /joe/ isnt FOR joe, its for joe's visitors, so I can't rely on a user login or method of this sort. I could switch to joe.example.com but would rather not.
Is there a way I can make this play nice with Code Igniter?
Currently, it would want to call the joe controller. My initial thought is trying to find a way to have a default controller called when a controller doesn't exist, but if some CI pros have advice on a different, better way to handle this, it would be great.
Upgrade to CodeIgniter 2.0 and use $route['404_override'] = 'controller'; or install Modular Extensions which does the same thing, but for now they use $route['404'] instead.
There are a number of different ways to go about this. Just be warned, both of these solutions require you to edit CI's core files. That means you can't upgrade without breaking these edits. Unfortunately hooks do not suitably address this issue.
The easy way:
line 188-195 in system/vodeigniter/CodeIgniter.php handle the logic for what happens when a controller is not found.
The harder but better way:
There is a hook (http://codeigniter.com/user_guide/general/hooks.html)
pre_controller
But this will not work! The reason is that this is called after the controller has been determined, but before anything is actually executed. In other words, it is too late. The next earlier one
pre_system
is in fact too early, because routing has not been done and anything you do the routing will get overwritten.
So I needed the first controller to look the same, yet end up calling a different controller. The reason was that the page was accessed in a hierarchical way, so that it would be the subsection of a subsection and so on.
What I did was add on line 43 of system/libraries/Controller.php
$this->_ci_initialize();
Basically I had it autoload the libraries BEFORE the controller was called, because I was finding that the libraries were not loaded before the controller was called and I needed it to be done so because I needed to check user access authentication and hook directly into the routing itself.
After I did that, I extended one of the native core libraries that were autoloaded (in this case session, for applicaiton specific reasons) and then executed the rerouting.
$RTR = & load_class( 'Router' );
$this->URI = & load_class( 'URI' );
$this->URI->_fetch_uri_string();
I called this code in the start, then put my logic afterwards. This is a sample of what my rerouting logic looks like
if ( $this->segment( 1 ) == 'institute' )
{
if ( ! in_array( $this->segment( 3 ), $course ) )
{
$RTR->set_class( 'courseClass' );
$RTR->set_method( 'index' );
if ( ! $this->segment( 4 ) )
{
$RTR->set_class( 'course' );
$RTR->set_method( 'index' );
}
else
{
$RTR->set_class( 'course' );
$RTR->set_method( $this->segment( 3 ) );
}
}
The original is much longer. I probably should consider writing some sort of plugin or superior way to handle the rewriting rather than silly spagetti logic. However, I needed extremely fine grain control of the controllers being called based on the URLs. This will literally give you god mode control over your controller based on the URLs. Is it a hack? Yes. Is it inelegant? Absolutely. But I needed it done.
Just remember since this edits the core files, you can't easily upgrade after. I think the Kohana framework has a solution to this.
I kept reading the CI docs after Alex's post and found info on the routes.php file which does exactly what I needed.
It allows you to use regular expressions to rewrite the routes (URLs), much in the same manner as mod_rewrite, so I could strip out the user name and end up passing it as a param.
When I use CakePHP Paging I get an url like this:
http://example.com/php/page:2
What do I have to change in the controller, the view and the routes.php to create a working url like this:
http://example.com/php/2
Oh yes, now I see your question. Well you could do something like:
function index($page){
$this->paginate = array('page'=>$page);
$this->set('stuff', $this->paginate('YourControllerName'));
}
See here for more details:
http://bakery.cakephp.org/articles/view/basic-pagination-overview-3
Also, of course you should do some validation that the page is an actual number and that the page would even exist but that is the basics of it i think.
About the routes and views, I have never tried but have a look at these posts on the cake groups, I think they have a problem similar to yours.
http://www.mail-archive.com/cake-php#googlegroups.com/msg45878.html
Try this link:
http://www.sakic.net/blog/changing-cakephp-pagination-urls/
My guess is that this won't be easy to automate, you'll definitely need to do some tweaking.
For starters, you'll probably have to create your own paginator helper and inherit the default one. By the looks of the code, you'll need to override the link-generating code in PaginatorHelper::__pagingLink(), but probably numbers() and prev() etc.. since they all create links with the page param.
Maybe a better way would be to override your AppHelper::url(), check for the "page" param there and modify the url to accomodate your needs.
But, I haven't tried all this, so no guarantees..