I have written my cake app to log in registered users and it works great on view pages where there is a db model associated with a User. However, on my main pages that aren't necessarily accessing some model (the PagesController where pages are things like upcoming events, contact us, about, etc), AuthComponent is not available, or at the least, the array returns empty---so i cannot retrieve, say, the username of the person logged in.
I tried creating a model called Page that belongsTo User but that didn't fix my problem.
To explain a little further, my app shows lists of certain lodgings, nightclubs, restaurants and things to do for a given city, all of which is shown whether a user is logged in or not. I don't understand where I am going wrong and why.
Here is my AppController:
<?php
class AppController extends Controller {
public $components = array(
'Session',
'Auth' => array(
'loginRedirect' => array('controller' => 'users', 'action' => 'view'),
'logoutRedirect' => array('controller' => 'pages', 'action' => 'index')
)
);
function beforeFilter() {
$this->Auth->allow('login', 'logout','index', 'view', 'condos', 'houses', 'hotels_and_motels', 'print_all_coupons', 'print_coupon', 'search', 'golf', 'charters', 'events', 'nightlife', 'shopping', 'visitors_info', 'contact_us');
}
}
?>
here is where I access my username in my default page layout:
<?php if(AuthComponent::user('id')) {
echo '<span style="font-variant:small-caps">Hello, '.AuthComponent::user('username').'</span> | ';
?>
I have found the answer, after weeks of beating my head on the wall about this. And oh, you're gonna laugh. For any of you out there up against this problem, the answer is.....make sure there is no white space before or after your tags. That is all. Seriously. Since PHP prints out everything that isn't in a PHP tag, if it finds something to send, it will send out headers before everything else. Once headers are sent, a PHP session cannot be created. So chalk this one up to the head-smacking file!
Without seeing any code my first instinct is to say that you are not loading the component in AppController but in the UsersController only. Are you loading the Auth component in AppController?
UPDATE:
Here is how I would suggest accessing the User information.
$this->Session->read('Auth.User.username');
UPDATE 2
Remove the $components declaration from the Pages Controller. It could be overriding the session.
UPDATE 3
If you have a custom Pages controller, it is probably conflicting with the Core Pages controller. Remove your Pages controller and see if it works correctly. The Core Pages controller will still route to the Views/Pages/ directory for displaying content.
Related
I'd like to force my site's URL to always have a language suffix.
So, if they type www.mysite.com it should take them to www.mysite.com/en.
I have a default language, so that should be used if it's their first time to the site. If it's not, I have a Cookie being set that I can use...but - I don't know where to use it.
I thought about checking to see if there was a "language" parameter in the URL, then if not, redirecting, but - that seems overkill - is there a better way? Can I do this in routes? or bootstrap?
The most efficient way would be through your web server. You can easily check if the request is for / (the home page) and redirect to /en.
Check the docs for what ever web server you are using, they all have something like mod_rewrite or similar.
Edit
You could set up a route like /set_default_language to redirect to in case of /, this controller can access the db and do what ever it needs.
Alternatively you can make it redirect to /your/usual/language_switch with no language specified and allow the code to use the default.
What I did:
I ended up checking in the AppController's beforeFilter() whether or not $this->request->params['langauge'] was set and if not, building the URL accordingly:
//Redirect to same url, but with language parameter
if (empty($this->request->params['language']) &&
empty($this->request->params['admin'])) {
$defaultLanguageCode = Configure::read('Languages.default.code2');
$cookiedLanguage = $this->Language->activeLanguageByCode($this->Cookie->read('lang'));
$languageToRedirectTo = (!empty($cookiedLanguage['code2'])) ? cookiedLanguage['code2'] : $defaultLanguageCode;
$newURL = '/' . $languageToRedirectTo . $this->request->here;
$this->redirect($newURL);
}
Note:
The part I couldn't figure out (until getting help in IRC) was to build the URL using $this->request->here, which is just the URL as a string. Prior to that I tried building out the array using the params array, but had no luck.
My routes (in case they help anyone)
(Keep in mind, I'm a routes noob, so - although they seem to be working for me, I do NOT guarantee they're done well!)
//root URL and root URL w/ language
Router::connect('/', array('controller' => 'pages', 'action' => 'display', 'home')); // eg: www.google.com takes them to pages/display/home
Router::connect('/:language', array('controller'=>'pages', 'action' => 'display', 'home'), array('language'=>'[a-z]{2}')); // eg: /en takes them to pages/display/home and sets language
//pages (eg. /en/r/the_matrix or /r/the_matrix)
Router::connect('/:language/r/:slug/*', array('controller'=>'pages', 'action'=>'display'), array('language'=>'[a-z]{2}', 'pass'=>array('slug')));
Router::connect('/r/:slug/*', array('controller'=>'pages', 'action'=>'display'), array('pass'=>array('slug')));
//adds language to default URL
Router::connect('/:language/:controller/:action/*', array(), array('language'=>'[a-z]{2}'));
//Route prefixes
Configure::write('Routing.prefixes', array('admin'));
//User related
Router::connect('/login', array('controller' => 'users', 'action' => 'login'));
Router::connect('/logout', array('controller' => 'users', 'action' => 'logout'));
Router::connect('/myaccount', array('controller' => 'users', 'action' => 'my_account'));
//
CakePlugin::routes();
require CAKE . 'Config' . DS . 'routes.php';
If you don't want to redirect the requestAction calls from within your controllers or views you should add the following condition to your IF statement
if (empty($this->request->params['language']) &&
empty($this->request->params['admin']) &&
empty($this->request->params['requested'])) {
...
}
Human readable URLs with nested categories like /category/subcategory/n-subcategories/article. I'm using CakePHP 2.2.3 and can't find a proper solution for a routing problem. Using 2 Tables:
articles (could also be products or posts or...)
have just a normal "single" view
an article belongs to one category
categories
nested (Tree behaviour with n-levels)
one category can have many articles
category-view lists all articles, that are related to this category
category view uses paginator for showing article lists
A very common example I guess. But how do I have to define the router now, to get URL-paths with the nested categories like this:
/categoryname1 (showing category view)
/categoryname1/articlename1 (showing article view)
/categoryname2/articlename2 (showing article view)
/categoryname2/subcategoryname1 (showing category view)
/categoryname2/subcategoryname2/articlename4 (showing article view)
/n-categoryname/././...n-subcategoryname (showing category view)
/n-categoryname/././...n-subcategoryname/n-articlename (article view)
I tried to make all routes fix in the routes.php, but that is not very comfortable and I think there should be a dynamic solution.
I also tried to automatically generate all routes out of category- and article-alias and save them in a separate "routes" database table - it worked, but I don't think it's really necessary to define hunderets of single routes?!
I also tried just to define all the categories fix in router, like
Router::connect(
'/any-category-name',
array('controller' => 'categories', 'action' => 'view', 1)
);
and then for the articles
Router::connect(
'/any-category-name/:slug',
array('controller' => 'articles', 'action' => 'view'),
array('pass' => array('slug'))
);
But with this method, all articles are available in all categories, which isn't a good solution. And I thought about using
Router::connect(
'/:slug', ...
but I don't know how to go on, because there are two different controllers and two different views possible (also I don't know if Pagination will still work in this case and what will happen, if I also want to use more controllers/actions in the installation).
I think it shouldn't be so difficult to get nested urls with two controllers (categories and articles) in Cake?! Thanks for any helpful advise!
I think you have to check for two things:
1) Check the number of categories in the url and
2) Check if the last parameter is a category or an article
Handle both checks within a (dynamic) route may be very difficult. I would suggest to create just one route for all these requests and do the checks for 1) and 2) in a controller.
The route may be something like this:
Router::connect(
'/*',
array('controller' => 'outputs', 'action' => 'index')
);
I called the controller for this route OutputController because this will be the controller that handles the output for all these urls.
class OutputController extends AppController
{
public $uses = array('Article', 'Category');
public function index()
{
// Get n parameters from url (1)
$args = func_get_args();
$last_arg = $args[count($args) - 1];
// Check if this is an article (2)
$article = $this->Article->find('first', array(
'conditions' => array('Article.slug' => $last_arg
));
if (!empty($article)) {
$this->set('article', $article);
$this->render('article');
}
// Check if this is an category (2)
$category = $this->Category->find('first', array(
'conditions' => array('Category.slug' => $last_arg
));
if (!empty($category)) {
$this->set('category', $category);
$this->render('category');
}
// Page not found
if (empty($article) and empty($category)) {
throw new NotFoundException();
}
}
// ...
To display an article, the view 'Output/article.ctp' is used. For a category, CakePHP renders 'Output/category.ctp'. In addition you can use the parameters in $args to fetch all the necessary data for your (sub-) categories.
I have created a plugin called movies, I have used custom routes.
I have used pagination limit as '5'.
The first page is fine, but when I click on next or numbers. Those things doesn't works.
URL: something.com/movieslist/2
my Plugin/Movies/Config/routes.php
Router::connect('/movieslist', array('plugin' => 'Movies', 'controller' => 'Movies', 'action' => 'index'));
Router::connect('/movieslist/:page', array('plugin' => 'Movies', 'controller' => 'Movies', 'action' => 'index'));
my action code: Plugin/Movies/Controller/MoviesController.php
public function index() {
$this->Movie->recursive = 0;
$this->paginate = array('limit'=>5);
$this->set('movies', $this->paginate());
}
my view file code: Plugin/Movies/View/Movies/index.ctp
Same one from cakebake console. No changes made here.
Even the sort doesn't works :(
I'm tiered of searching my problems in many places :(
I had previously getting error in links itself and I fixed this after seeing this page:
CakePHP custom route pagination
Links are fixed but the links doesn't works. Pls don't down vote, I'm struggling from long time.
I'm using cakephp 2.0 version.
As a first step I'd swap the order of the router rules, since cakephp stops after the first match found. While the "/movieslist/:page" one will match a url with a page, it only does so for the named parameter page. Without it a url of the form "/movielist/2", might be interpreted as a link to "/movielist" with a normal parameter "2", hence the first router rule triggers.
If that does not work you can always just manually set the named page parameter. paginate just looks to see if it is set, but does not care if cakephp automagically figured it out from the url or if you do it yourself.
public function index($myPage=1) {
$this->Movie->recursive = 0;
$this->paginate = array('limit'=>5);
$this->params["page"] = $myPage;
$this->set('movies', $this->paginate());
}
I'm working on upgrading my project from CakePHP 1.2 to 1.3. In the process, it seems that the "magic" routing for plugins by which a controller name (e.g.: "ForumsController") matching the plugin name (e.g.: "forums") no longer automatically routes to the root of the plugin URL (e.g.: "www.example.com/forums" pointing to plugin "forums", controller "forums", action "index").
The error message given is as follows:
Error: ForumsController could not be found.
Error: Create the class ForumsController below in file: app/controllers/forums_controller.php
<?php
class ForumsController extends AppController {
var $name = 'Forums';
}
?>
In fact, even if I navigate to "www.example.com/forums/forums" or "www.example.com/forums/forums/index", I get the same exact error.
Do I need to explicitly set up routes to every single plugin I use? This seems to destroy a lot of the magic I like about CakePHP. I've only found that doing the following works:
Router::connect('/forums/:action/*', array('plugin' => 'forums', 'controller' => 'forums'));
Router::connect('/forums', array('plugin' => 'forums', 'controller' => 'forums', 'action' => 'index'));
Setting up 2 routes for every single plugin seems like overkill, does it not? Is there a better solution that will cover all my plugins, or at least reduce the number of routes I need to set up for each plugin?
I guess, that topic Configuration-and-application-bootstrapping covers that:
App::build(array(
'plugins' => array('/full/path/to/plugins/', '/next/full/path/to/plugins/')
));
Also take a look at this ticket: http://cakephp.lighthouseapp.com/projects/42648/tickets/750-plugin-route-problem-when-acl-and-auth-components-used#ticket-750-5 (Cake 1.3 had removed magic plugin routes).
You don't have myplugin_app_controller.php in your /app/plugins/myplugin directory.
Just create a file containing following:
<?php
class MypluginAppController extends AppController {
}
?>
And you will have all your plugin's features. :)
I plan to add up a calender function to my system, but i had mess up with the link which not link to the direct address that i want..
i am still new to cakephp, need some help to get understand the code and the correct way for me to point to the correct address i want..
here is some of the code in the controller, other side is not a problem to run just left the pointing address which had make me mad..
when i press to the link, which i want to view my data, it's just jump to the other side that not in my set up.
// here is the declaration which in the original controller that i learn from the net.
$view_base_url = $this->webroot. 'calendars';
//this the original link that i using which cant point to my correct side.
$data[$day] .= 'a href="'.$view_base_url.'/view/'. $v['Calendar']['id'] . '">' . $v['Calendar']['name'] . '</a>';
in the details,
i wanted to link to my side with just the calendars/view/id of the link i point.
but with this code, i will redirect to the app/webroot/view/id side.
can i change the $this->webroot to just link to where i want??
if i not using the $this->webroot, i am not able to redirect while i click other page in the calendar..
it might be a poor explanation, cause i am still new to cakephp.
just any 1 can kindly drop me a comment what i can do?
You should use the Router class to create links to within your application. For example:
Router::url(array('controller' => 'my_controller', 'action' => 'view', $id));
// returns, for example, /my_controller/view/5
Router::url(array('controller' => 'my_controller', 'action' => 'view', $id), true);
// returns, for example, http://example.com/root_directory/my_controller/view/5
This method is used by many functions throughout Cake, for example by the HTML Helper:
echo $html->link('My Link', array('controller' => 'my_controller', 'action' => 'view', $id));
// echos:
My Link
The URLs that Router returns are based on the routes defined in app/config/routes.php. This way you can define handy shortcuts:
Router::connect('/view/*', array('controller' => 'my_controller', 'action' => 'view'));
echo $html->link('My Link', array('controller' => 'my_controller', 'action' => 'view', $id));
// echos:
My Link
This is the way you should handle all links in your Cake application. You shouldn't make links in the Controller, only in the View, using the HTML Helper. In the rare case were you do need links in the Controller, use Router::url().