I've written static pages component for my application, where admins can dynamically add/edit/remove static content pages. these are saved in the database.
(e.g. you can create a page called "about" and can visit it at myapplication/about)
This is my routing for these pages:
$page = new StaticPage();
$slugs = $page->find('list', array(
'fields' => array('slug'),
'recursive' => -1,
'order' => 'StaticPage.slug DESC',
));
Router::connect('/:slug',
array('controller' => 'static_pages', 'action' => 'display'),
array(
'pass' => array('slug'),
'slug' => implode($slugs, '|')
)
);
Now i have the problem, that when you create a page which slug matches an existing controller (e.g. users), it overwrites the Route to the UsersController.
so i need something like a blacklist or similar: i began to write a validation rule, where i want to check if that controller exists. for cake 1.3 there was a function "loadController" which return false, if the controller did not exist, but for cake 2.x there is no such an function. am i missing this somehow? does it have a new name or is in a utility library now?
Or are there better ways to solve this?
you should try this : http://www.cleverweb.nl/cakephp/list-all-controllers-in-cakephp-2/
and by getting the list of all controllers you can easily exclude the name of controllers
This is my validation method for now:
$route = Router::parse($check['slug']);
$controllerName = Inflector::camelize($route['controller'] . 'Controller');
$aCtrlClasses = App::objects('controller');
foreach ($aCtrlClasses as $controller) {
if ($controller != 'AppController') {
// Load the controller
App::import('Controller', str_replace('Controller', '', $controller));
// Load the ApplicationController (if there is one)
App::import('Controller', 'AppController');
$controllers[] = $controller;
}
}
if (in_array($controllerName, $controllers)) {
return false;
} else {
return true;
}
Related
I'm trying to use the cache groups, but the examples in the documentation are not very clear for me.
This is my bootstrap:
Cache::config('default', array(
'engine' => $engine,
'duration' => $duration,
'prefix' => $prefix,
'groups' => array('page', 'photo', 'post')
));
We suppose that I have the model, including articles, pages, photos, etc., and in the various actions the data is written to the cache.
For example, PagesController:
public function index() {
$pages = Cache::read($cache = 'pages_index');
if(empty($pages)) {
$pages = $this->Page->find('all');
Cache::write($cache, $pages);
}
$this->set(array(
'pages' => $pages
));
}
This creates the file
tmp/cache/pages_index
The cache is working correctly, the next request will use the cache.
Others actions write the data for the Page model page.
Again PagesController:
public function view($slug = NULL) {
$page = Cache::read($cache = sprintf('pages_view_%s', $slug));
//If the data are not available from the cache
if(empty($page)) {
$page = $this->Page->find('first', array(
'conditions' => array('slug' => $slug)
));
if(empty($page))
throw new NotFoundException(__('Invalid page'));
Cache::write($cache, $page);
}
$this->set(array(
'page' => $page
));
}
This also works correctly.
Now I wish that editing a page being deleted from the cache all the data about pages. The same should happen for the other models (posts, photos, etc).
So, in my Page model:
public function afterSave($created, $options = array()) {
Cache::clearGroup('pages');
}
But this does not work: no files are deleted from the cache.
Where am I doing wrong? What I do not understand?
Thanks!
Because Your group name is 'page', not 'pages'.
I'm using CakePHP v2.42 & would like to have SEO friendly URL in page pagination.
My current pagination is like
http://www.website.com/ubs/page/page:2
What to do to change to
http://www.website.com/ubs/page/2
My Controller is
<?php
class UbsController extends AppController {
public $helpers = array('Html', 'Form');
public function index() {
$this->paginate = array(
'limit' => 100,
);
$ubs = $this->paginate();
$this->set('ubs', $ubs);
}}
My Router is
Router::connect('/ubs', array('controller' => 'ubs', 'action' => 'index'));
Router::connect('/ubs/page/*', array('controller' => 'ubs', 'action' => 'index'));
EDIT - ADD MORE QUESTION
Answer by #kicaj is perfectly correct for the Router & Controller. However, the navigation link only display correctly on the first page.
In the first page navigation link show like this which is correct
http://www.website.com/ubs/
http://www.website.com/ubs/page/2/
http://www.website.com/ubs/page/3/
But navigation link show like this in second/third page page
http://www.website.com/ubs/index/2/
http://www.website.com/ubs/index/2/page:3/
I guess need to edit index.ctp file but not sure what to do.
My current navigation link in index.ctp show like this
$paginator = $this->Paginator;
$paginator->prev("« Prev");
$paginator->numbers(array('modulus' => 200, 'separator' => ' '));
$paginator->next("Next »");
What to change to correct this
Try this:
Router::connect('/ubs/page/:page', array(
'controller' => 'ubs',
'action' => 'index'
), array(
'pass' => array(
'page'
),
'page' => '[\d]+'
));
and in index action in ubs controller add code bellow:
public function index($page = 1) {
// ...
$this->request->params['named']['page'] = $page;
// ...
}
In your Paginator Helper you can choose the right friendly url you want with setting some options
url The URL of the paginating action. ‘url’ has a few sub options as well:
sort The key that the records are sorted by.
direction The direction of the sorting. Defaults to ‘ASC’.
page The page number to display.
There here an example .
$this->Paginator->options(array(
'url' => array(
'sort' => 'email', 'direction' => 'desc', 'page' => 6,
'lang' => 'en'
)
));
the source : Modifying the options PaginatorHelper uses
I am trying to get my CakePHP app to use slugs instead of ids. I have read several tutorials and the CakePHP book about it, but I must be missing something simple.
My table has a "slug" field that I want to use for the URL instead of the default id.
I changed my ItemsController view to this:
public function view($slug = null) {
if (!$this->Item->exists($slug)) {
throw new NotFoundException(__('Invalid item'));
}
$this->set('item', $this->Item->findBySlug($slug));
}
And added this to my routes.php
Router::connect(
'/items/:slug',
array('controller' => 'items', 'action'=>'view'),
array('pass'=>array('slug'))
);
Yet I still get "Invalid Item, requested address not found..." when going to:
mycakeapp/items/slug-value
However, if I change everything from 'slug' to 'id' then the URL:
mycakeapp/items/id-value
works just fine
Can someone help me? Thanks in advance.
Well, read the documentation for Model::exists().
Returns true if a record with particular ID exists.
If $id is not passed it calls Model::getID() to obtain the current
record ID, and then performs a Model::find('count') on the currently
configured datasource to ascertain the existence of the record in
persistent storage.
It expects an id not a slug.
Here is a proper example from a model method to display an artist:
public function view($id = null, $options = array()) {
$defaults = array(
'contain' => array(
/* ... */
),
'conditions' => array(
'OR' => array(
$this->alias . '.' . $this->primaryKey => $id,
$this->alias . '.slug' => $id
)
)
);
$artist = $this->find('first', Hash::merge($defaults, $options));
if (empty($artist)) {
throw new NotFoundException(__('Invalid Artist'));
}
return $artist;
}
The controllers try/catches the exception and sets the exception message to the session by calling Session->setFlasH(). Easy. :)
Here is my test controller :
public function testAdd() {
$data = array(
'Article' => array(
'id' => '1',
'text' => 'blablabla',
),
);
$result = $this->testAction(
'/articles/add',
array('data' => $data, 'method' => 'post')
);
debug($result);
}
So I can access to the current model in the controller ($this->Article) but i can't load other models via loadModel.
Clarification : The code written in the controller works perfectly when i load other models, the problem appears ONLY when i want to test my controller.
Best regards.
I have tried most if not all tutorials for CakePHP 1.3 on their Auth method and non seem to work on CakePHP 2.0.
I can add users, hash the passwords, but the login feature does not work. It just refreshes the page when I click on login. No errors, no nothing.
I would appreciate some tips please and thank you for reading my question.
This my code
public function login()
{
if ($this->request->is('post') )
{
if( $this->Auth->login() )
{
// the redirect() function in the Auth class redirects us
// to the url we set up in the AppController.
return $this->redirect( $this->Auth->redirect());
}
else
{
$this->Session->setFlash(__('Email or password is incorrect',true));
}
}
}
Thanks,
Mahadeva Prasad
First of all check how you have hash the password.Also check the field length in database.
Preferred - varchar(255)
The password will be hash as follows.
class User extends AppModel {
public function beforeSave($options = array()) {
$this->data['User']['password'] = AuthComponent::password($this->data['User']['password']);
return true;
}
}
Also as you are using FormAuthenticate try using this when declaring component.
public $components = array(
'Auth' => array(
'loginAction' => array(
'controller' => 'users',
'action' => 'login',
),
'authenticate' => array(
'Form' => array(
'fields' => array('username' => 'username')
)
)
)
);
For more information refer http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html