form action linking to wrong controller - cakephp

I have a a controller referral_medium_controller.php with the following content
<?php
class ReferralMediumsController extends AppController
{
var $name = 'ReferralMediums';
function admin_index()
{
//Checking that only super administrators can actually add new interest options
if ($this->Auth->user('user_type_id') != ConstUserTypes::Admin) {
$this->cakeError('error404');
}
$this->pageTitle = __l('Referral Mediums');
$this->ReferralMediums->recursive = 0;
$this->set('ReferralMediums', $this->paginate());
}
function admin_view($id = null)
{
//Checking that only super administrators can actually add new interest options
if ($this->Auth->user('user_type_id') != ConstUserTypes::Admin) {
$this->cakeError('error404');
}
$this->pageTitle = __l('Referral Mediums?');
if (is_null($id)) {
$this->cakeError('error404');
}
$referralMedium = $this->ReferralMediums->find('first', array(
'conditions' => array(
'ReferralMedium.id = ' => $id
) ,
'fields' => array(
'ReferralMedium.id',
'ReferralMedium.created',
'ReferralMedium.modified',
'ReferralMedium.referral_medium',
'ReferralMedium.is_active',
) ,
'recursive' => -1,
));
if (empty($referralMedium)) {
$this->cakeError('error404');
}
$this->pageTitle.= ' - ' . $referralMedium['ReferralMedium']['id'];
$this->set('ReferralMediums', $referralMedium);
}
function admin_add()
{
//Checking that only super administrators can actually add new interest options
if ($this->Auth->user('user_type_id') != ConstUserTypes::Admin) {
$this->cakeError('error404');
}
$this->pageTitle = __l('Add Referral Medium');
if (!empty($this->data)) {
$this->ReferralMedium->create();
if ($this->ReferralMedium->save($this->data)) {
$this->Session->setFlash(__l('Referral Medium has been added') , 'default', null, 'success');
$this->redirect(array(
'action' => 'index'
));
} else {
$this->Session->setFlash(__l('Referral Medium could not be added. Please, try again.') , 'default', null, 'error');
}
}
}
function admin_edit($id = null)
{
//Checking that only super administrators can actually add new interest options
if ($this->Auth->user('user_type_id') != ConstUserTypes::Admin) {
$this->cakeError('error404');
}
$this->pageTitle = __l('Edit Referral Medium');
if (is_null($id)) {
$this->cakeError('error404');
}
if (!empty($this->data)) {
if ($this->ReferralMedium->save($this->data)) {
$this->Session->setFlash(__l('Referral Medium has been updated') , 'default', null, 'success');
$this->redirect(array(
'action' => 'index'
));
} else {
$this->Session->setFlash(__l('Referral Medium could not be updated. Please, try again.') , 'default', null, 'error');
}
} else {
$this->data = $this->ReferralMedium->read(null, $id);
if (empty($this->data)) {
$this->cakeError('error404');
}
}
$this->pageTitle.= ' - ' . $this->data['ReferralMedium']['id'];
}
function admin_delete($id = null)
{
//Checking that only super administrators can actually add new interest options
if ($this->Auth->user('user_type_id') != ConstUserTypes::Admin) {
$this->cakeError('error404');
}
if (is_null($id)) {
$this->cakeError('error404');
}
if ($this->ReferralMedium->del($id)) {
$this->Session->setFlash(__l('Referral Medium deleted') , 'default', null, 'success');
$this->redirect(array(
'action' => 'index'
));
} else {
$this->cakeError('error404');
}
}
}
?>
a model referral_model.php with the following content
<?php
class ReferralMedium extends AppModel
{
var $name = 'ReferralMedium';
var $useTable="referral_mediums";
//$validate set in __construct for multi-language support
//The Associations below have been created with all possible keys, those that are not needed can be removed
var $hasOne = array(
'UserProfile' => array(
'className' => 'UserProfile',
'foreignKey' => 'referral_medium_id',
'dependent' => false,
'conditions' => '',
'fields' => '',
'order' => ''
)
);
var $hasMany = array(
'UserProfile' => array(
'className' => 'UserProfile',
'foreignKey' => 'referral_medium_id',
'dependent' => false,
'conditions' => '',
'fields' => '',
'order' => '',
'limit' => '',
'offset' => '',
'exclusive' => '',
'finderQuery' => '',
'counterQuery' => ''
)
);
function __construct($id = false, $table = null, $ds = null)
{
parent::__construct($id, $table, $ds);
$this->validate = array(
'referral_medium' => array(
'rule' => 'notempty',
'allowEmpty' => false,
'message' => __l('Required')
) ,
);
}
}
?>
a add view referral_mediums/admin_add.ctp with the following code
<?php /* SVN: $Id: $ */ ?>
<div class="referralMedium form">
<?php echo $form->create('ReferralMedium', array('class' => 'normal'));?>
<fieldset>
<h2><?php echo __l('Add Referral Medium');?></h2>
<?php
echo $form->input('referral_medium');
echo $form->input('is_active');
?>
</fieldset>
<div class="submit-block clearfix">
<?php echo $form->submit(__l('Add'));?>
</div>
<?php echo $form->end();?>
</div>
Now all works fine except if I click on the add button in the add form I get redirected to admin/referral_media/add instead of admin/referral_medium/add and I can't find the problem. I would be greatful I someone could help me with this.

the plural of medium is media, not mediums. The controller name is plural, so it's referral_media. So you'll need to change your controller name (and the file name).

Or change Config/bootstrap.php so it won't make controller names plural anymore.

Related

cakephp search plugin basic use

I hope you can help me. I've done all steps like here "cakephp basic help to use cakedc search plugin" but the searcher doesn't anything.
My project is about one User's List and I want to filter for the fields 'apellidos' or 'dni'.
In my Controller I've the component declared and this:
public function index() {
$this->Prg->commonProcess();
$this->paginate = array(
'conditions' => $this->User->parseCriteria($this->passedArgs));
$this->set('users', $this->paginate());
$this->User->recursive = 0;
$this->User->order = 'User.cod_cliente';
$this->User->conditions = 'User.nombre';
if($this->Session->read('Auth.User.group_id')==5)
{
//$this->set('categorias', $this->User->find('all',array('fields'=>array('group_id','cod_cliente','nombre','apellidos','dni','id'))));
}else
{
$this->User->conditions = array('User.cod_centro'=>$this->Session->read('Auth.User.cod_centro'));
//$this->set('categorias', $this->User->find('all',array('fields'=>array('group_id','cod_cliente','nombre','apellidos','dni','id'),'conditions'=>array('User.cod_centro'=>$this->Session->read('Auth.User.cod_centro')))));
}
$this->set('categorias', $this->Paginator->paginate());
$this->set('title_for_layout', __('Listado de usuarios')." - ".__('Administración'));
}
public $presetVars = array(
array('field' => 'apellidos', 'type' => 'value'),
array('field' => 'dni', 'type' => 'value'),);
public $actsAs = array('Containable','Search.Searchable','Acl' => array('type' => 'requester'));
public $filterArgs = array(
array('name' => 'apellidos', 'type' => 'query', 'method' => 'filterApellidos'),
array('name' => 'dni', 'type' => 'query', 'method' => 'filterDni'),
);
and here are also the functions:
public function filterApellidos($data, $field = null) {
if (empty($data['apellidos'])) {
return array();
}
$apellidosField = '%' . $data['apellidos'] . '%';
return array(
'OR' => array(
$this->alias . '.apellidos LIKE' => $apellidosField,
));
}
public function filterDni($data, $field = null) {
if (empty($data['dni'])) {
return array();
}
$dniField = '%' . $data['dni'] . '%';
return array(
'OR' => array(
$this->alias . '.dni LIKE' => $dniField,
));
}
// Built a list of search options (unless you have this list somewhere else)
public function __construct($id = false, $table = null, $ds = null) {
$this->statuses = array(
'' => __('All', true),
0 => __('Bid', true),
1 => __('Cancelled', true),
2 => __('Approved', true),
3 => __('On Setup', true),
4 => __('Field', true),
5 => __('Closed', true),
6 => __('Other', true));
parent::__construct($id, $table, $ds);
}
Finally, in the View I have this:
<div><?php
echo $this->Form->create('Usuario', array(
'url' => array_merge(array('action' => 'index'), $this->params['pass'])
));
echo $this->Form->input('apellidos', array('div' => false, 'empty' => true)); // empty creates blank option.
echo $this->Form->input('dni', array('div' => false, 'empty' => true));
echo $this->Form->submit(__('Search', true), array('div' => false));
echo $this->Form->end();
?>
</div>
Could you tell me what I'm doing wrong, please? Thanks a lot!!
Belén

rawurlencode() expects parameter 1 to be string, array given [CORE\Cake\Routing\Route\CakeRoute.php, line 506]

I am new in CakePHP. I wanted to create menu in cakePHP 2.3.9 but when I run the application it gives following warning "rawurlencode() expects parameter 1 to be string, array given [CORE\Cake\Routing\Route\CakeRoute.php, line 506]"
I am giving the complete code here. I can not understand how to eliminate the warning message above.
At first I have created this file at /app/Model/menu.php. Which looks like this
<?php
class Menu extends AppModel {
var $name = 'Menu';
var $useTable = false;
function main ($selected = 'home') {
return array(
'divClass' => 'menu',
'ulClass' => 'menu',
'tabs' => array(
array(
'controller' => 'pages',
'action' => '',
'params' => '',
'aClass' => $selected == 'home' ? 'selected' : '',
'liClass' => '',
'text' => 'Home'
),
array(
'controller' => 'pages/service',
'action' => '',
'params' => '',
'aClass' => $selected == 'Service' ? 'selected' : '',
'liClass' => '',
'text' => 'Service'
),
array(
'controller' => 'pages/user',
'action' => '',
'params' => '',
'aClass' => $selected == 'users' ? 'selected' : '',
'liClass' => '',
'text' => 'Users'
),
)
); // end return
} // end Main
} // end class Menu
?>
Then I have created this file at /app/Controller/MenusController.php. Which looks like this
<?php
class MenusController extends AppController {
var $name = 'Menus';
private $menus;
function beforeFilter () {
parent::beforeFilter();
$this->menus[] = array(
'name' => 'main',
'selected' => 'users'
);
// $this->set('menuList', $this->menus);
}
function index() {
$this->menus[] = array(
'name' => 'users',
'selected' => 'users'
);
$this->set('menuList', $this->menus);
}
function menus($menus) {
$output = array();
foreach ($menus as $menu):
$output[] = $this->Menu->{$menu['name']}($menu['selected']);
endforeach;
return $output;
}
}
?>
Then, this file I have created at /app/View/Elements/menu.ctp, which looks like this
<?php
if (empty($menuList)):
$menuList = array(
array(
'name' => 'main',
'selected' => 'home'
)
);
endif;
$menus = $this->requestAction(
array(
'controller' => 'menus',
'action' => 'menus'
),
array('pass' => array( $menuList))
);
if (! empty($menus)):
foreach ($menus as $menu):
$tabs = '';
foreach ($menu['tabs'] as $tab):
$url = array(
'controller' => $tab['controller'],
'action' => $tab['action']
);
if (! empty($tab['params'])):
$url[] = $tab['params'];
endif;
$tabs .= $this->html->tag(
'li',
$this->html->link(
$tab['text'],
$url,
array('class' => $tab['aClass'])),
array('class' => $tab['liClass'])
);
endforeach;
echo '<div class="' . $menu['divClass'] . '">
<div class="container_12">
<div class="grid_12">' . $this->html->tag('ul', $tabs, array('class' =>
$menu['ulClass'])) . '</div></div></div>';
endforeach;
endif;
?>
accept my advance gratitude for help
Your framework might have a default helper function which uses php's rawurlencode() function by default too. You might want to check the parameters you should pass for $this->html->link() since php's rawurlencode() function accepts only a string as a parameter.
Although the documentation says requestAction now supports 'array based cake style URLs' which 'bypass the usage of Router::url()', try passing a string as the first parameter to request action.
For example where you currently have:
array(
'controller' => 'menus',
'action' => 'menus'
),
Try:
'menus/menus',

CakePHP login by Username Or Email using Auth component

In my present system I need to login using username or email and password.
can anybody knows how to achieve this ?
My Form:
<?php echo $this->Form->create('User', array('action' => 'login'));
echo $this->Form->input('username', array('class' => 'TextField js-user-mode'));
echo $this->Form->input('password', array('class' => 'TextField'));
?>
MY AppController:
public $components = array(
'Email'=>array(),
'Auth' => array(
'loginAction' => array(
'admin' => false,
'controller' => 'users',
'action' => 'login'
),
'authError' => 'Your session has ended due to inactivity. Please login to continue.',
'authenticate' => array(
'Form' => array(
'fields' => array('username' => array('username','email')),
),
'all' => array(
'userModel' => 'User',
'scope' => array('User.status' =>array('active'))
)
)
)
);
Let me know what else i need to do..??
I'm not sure what the etiquette is on posting answers to old questions but here's what I did for this.
In my login function
$username = $this->data['User']['username'];
$password = $this->request->data['User']['password'];
$user = $this->User->findByUsername($username);
if (empty($user)) {
$user = $this->User->findByEmail($username);
if (empty($user)) {
$this->Session->setFlash(__('Incorrect Email/Username or Password'));
return;
}
$this->request->data['User']['username'] = $user['User']['username'];
}
I found following code from this url. I think this is the best in sense of simplicity. Use following code on your login action:
public function login() {
if($this->request->is('post')&&!empty($this->request->data)) {
App::Import('Utility', 'Validation');
if( isset($this->data['User']['username']) && Validation::email($this->request->data['User']['username'])) {
$this->request->data['User']['email'] = $this->request->data['User']['username'];
$this->Auth->authenticate['Form'] = array('fields' => array('username' => 'email'));
}
if($this->Auth->login()) {
/* login successful */
$this->redirect($this->Auth->redirect());
} else {
/* login unsuccessful */
}
}
}
And also use following code for login.ctp :
<?php
echo $this->form->create('User');
echo $this->form->input('username');
echo $this->form->input('password');
echo $this->form->end('Submit');
?>
Simply we can do this before your Auth login action:
$emailUsername = #$this->request->data['User']['email'];
if (!filter_var($emailUsername, FILTER_VALIDATE_EMAIL)) {
$emailFromUsername = $this->User->find('first', array('conditions' => array('User.username' => $emailUsername), 'recursive' => -1, 'fields' => array('email')));
//pr($emailFromUsername );
if (!empty($emailFromUsername)) {
$emailFromUsernameDB = $emailFromUsername['User']['email'];
} else {
$emailFromUsername = '';
}
$this->request->data['User']['email'] = $emailFromUsername;
}
Assuming you have username and email both fields in your users table
In your AppController.php
public function beforeFilter() {
if ($this->request->is('post') && $this->action == 'login') {
$username = $this->request->data['User']['username'];
if (filter_var($username, FILTER_VALIDATE_EMAIL)) {
$this->Auth->authenticate['Form']['fields']['username'] = 'email';
$this->request->data['User']['email'] = $username;
unset($this->request->data['User']['username']);
}
}
}
This code will work for CakePHP 2.x, not tested on version 3.x, you should have email field in your user's table.
You can leverage the MultipleColumn Auth adapter:
https://github.com/ceeram/Authenticate/blob/master/Controller/Component/Auth/MultiColumnAuthenticate.php
Update:
New version # https://github.com/dereuromark/cakephp-tools/blob/master/src/Auth/MultiColumnAuthenticate.php
I found this solution useful.
I have created two classes that extend FormAuthenticate:
app/Controller/Component/Auth/ClassNameAuthenticate.php and
<?php
App::uses('FormAuthenticate', 'Controller/Component/Auth');
class ClassNameAuthenticate extends FormAuthenticate {
}
app/Controller/Component/Auth/ClassNameEmailAuthenticate.php
<?php
App::uses('FormAuthenticate', 'Controller/Component/Auth');
class ClassNameEmailAuthenticate extends FormAuthenticate {
}
then in my Controller added Auth Component to $components
public $components = array(
'Session',
'Auth' => array(
'authenticate' => array(
'ClassName' =>array(
'userModel'=>'ClassName',
'fields' => array(
'username' => 'username',
),
'scope' => array('ClassName.active' => 1)
),
'ClassNameEmail' =>array(
'userModel'=>'ClassName',
'fields' => array(
'username' => 'email',
),
'scope' => array('ClassName.active' => 1)
)
)
),
);
login view: login.ctp
<div class="form">
<?php echo $this->Form->create('ClassName'); ?>
<fieldset>
<legend><?php echo __('Login'); ?></legend>
<?php
echo $this->Form->input('username');
echo $this->Form->input('password');
?>
</fieldset>
<?php echo $this->Form->end(array('label'=>__('Login'))); ?>
</div>
and login() action:
public function login(){
if ($this->Auth->loggedIn()) {
return $this->redirect($this->Auth->redirect());
}
if ($this->request->is('post')) {
//Need to duplicate field email for ClassNameEmail Auth
$this->request->data['ClassName']['email'] = $this->request->data['ClassName']['username'];
if ($this->Auth->login()) {
return $this->redirect($this->Auth->redirect());
}
$this->Session->setFlash(__('Invalid username/email or password, try again'));
}
}
I hope someone will find this useful.
this is my solution to solve that problem
public function login(){
if($this->request->is('post')){
$this->User->set($this->request->data);
if($this->User->validates()){
if(Validation::email($this->data['User']['username'])){
$this->Auth->authenticate['Form'] = array_merge($this->Auth->authenticate['Form'],array('fields'=>array('username'=>'email')));
$this->request->data['User']['email'] = $this->request->data['User']['username'];
unset($this->request->data['User']['username']);
}
if($this->Auth->login()){
$this->User->id = $this->Auth->user('id');
$this->User->saveField('last_login',time());
if($this->data['User']['remember']){
unset($this->request->data['User']['remember']);
$this->request->data['User']['password'] = Security::hash($this->request->data['User']['password'],'blowfish');
$this->Cookie->write('rememberMe',$this->request->data['User'],true,'2 days');
}
$this->redirect($this->Auth->loginRedirect);
}
$this->Session->setFlash('Invalid Username or Password entered, please try again.','default',array('class'=>'alert alert-warning'),'warning');
}
}
$this->set('title','Login Page');
}

hasMany through Join Model not saving to database

When a user enters data into my form it isn't saving to the database, this is the structure of my tables
Invoice - id, sender_id, receiver_id, template_id
Field - id, name, description, default_value, template_id
fields_invoices - id, invoice_id, field_id, entered_value
here is the invoice model
class Invoice extends AppModel{
var $name='Invoice';
var $hasMany = array(
'FieldsInvoice');
here is the field model
var $hasMany = array(
'FieldsInvoice'
);
and here is the fieldsInvoice model
<?php
class FieldsInvoice extends AppModel {
public $belongsTo = array(
'Field' => array(
'className' => 'Field',
'foreignKey' => 'field_id',
'conditions' => '',
'fields' => '',
'order' => ''
),
'Invoice' => array(
'className' => 'Invoice',
'foreignKey' => 'invoice_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
}
here is the create function in the invoices controller
public function create($id)
{
$this->set('title_for_layout', 'Create Invoice');
$this->set('stylesheet_used', 'homestyle');
$this->set('image_used', 'eBOXLogoHome.png');
$this->layout='home_layout';
if (!is_numeric($id)) throw new BadMethodCallException('I need an ID');
$this->Invoice->id = $id;
if (!$this->Invoice->exists()) throw new NotFoundException('Invalid ID');
$this->set('invoice_id',$id);
$names = $this->Invoice->find('list',array(
'fields'=>array('template_id'),
'conditions'=>array('id'=>$id)));
$fields = $this->Field->find('all', array(
'conditions'=>array(
'template_id'=>$names)));
$this->set(compact('fields'));
$this->set(compact('invoice_id'));
$this->set('name',$names);
$this->Invoice->create();
if(empty($this->data)){
$this->data= $this->Field->read($id);
}
else{
if($this->request->is('post'))
{
$this->Invoice->create();
if($this->FieldsInvoice->save($this->request->data, array('deep'=>true)));
{
$this->Session->setFlash('The field has been updated');
$this->redirect(array('controller'=>'invoices', 'action'=>'index'));
}
//else{
$this->Session->setFlash('Could not be saved');
//}
}
}
}
here is the view for the create function
<?php echo $this->Form->create('FieldsInvoice'); ?>
<?php foreach ($fields as $field): ?>
<?php echo $this->Form->hidden('Invoice.id'); ?>
<?php echo $this->Form->hidden($field['Field']['id']); ?>
<?php echo $this->Form->Input($field['Field']['name'], array('default' =>$field['Field']['default_value'])); ?>
<?php endforeach ;?>
<?php echo $this->Form->End('Submit');?>
when debugging the view this is the output received
array(
'Invoice' => array(
'id' => ''
),
'FieldsInvoice' => array(
(int) 5 => '',
'amount' => 'test',
(int) 6 => '',
'description' => 'test1',
(int) 7 => '',
'totalacctowing' => 'test2',
(int) 8 => '',
'pmtinfo' => 'test3'
)
)
Instead of:
$this->Invoice->save($this->request->data);
in your if condition use the following syntax;
$this->Invoice->save($this->request->data, array('deep' => true));
This link will guide you to save associated data.
Have you tried debugging? Try viewing your form data and see if all fields are ok. Use debug() or pr().

Cakephp registration problem

I followed tutorial on CakephpTV to make registration by AuthComponent. Yesterday everything worked good, but today it isn't.
When I'm trying to add new account it says that passwords do not match, and in password field there is hashed password and in password confirmation there is normal (not hashed) password.
My UserController class:
class UsersController extends AppController
{
function beforeFilter() {
parent::beforeFilter();
$this->Auth->allow('new_user');
if($this->action == 'add' || $this->action == 'edit') {
$this->Auth->authenticate = $this->User;
}
}
function new_user()
{
if (!empty($this->data)) {
if ($this->User->save($this->data)) {
$this->Session->setFlash('Rejestracja zakończona pomyślnie');
$this->redirect(array('action' => 'index'));
}
}
}
function login() {
}
function logout() {
$this->redirect($this->Auth->logout());
}
}
My User model:
class User extends AppModel {
var $name = 'User';
var $validate = array (
'email' => array(
'Please supply a valid email address.' => array(
'rule' => 'email',
'message' => 'Please supply a valid email address.'
),
'Already exists' => array(
'rule' => 'isUnique',
'message' => 'Must be unique'
)
),
'password' => array (
'aThis field must have between 6 and 40 alphanumeric characters.' => array(
'rule' => '/^[^\'"]{6,40}$/i',
'message' => 'aThis field must have between 6 and 40 alphanumeric characters.'
),
'Do not match' => array(
'rule' => 'matchPasswords',
'message' => 'Do not match'
)
)
);
function matchPasswords($data) {
if($data['password'] == $this->data['User']['password_confirmation']) {
return TRUE;
}
$this->invalidate('password_confirmation', 'DO not match');
return FALSE;
}
function hashPasswords($data) {
if(isset($this->data['User']['password'])) {
$this->data['User']['password'] = Security::hash($this->data['User']['password'], NULL, TRUE);
return $data;
}
return $data;
}
function beforeSave() {
$this->hashPasswords(NULL, TRUE);
$this->data['User']['registration_date'] = date("Y-m-d H:i:s");
return TRUE;
}
}
My new_user.ctp:
echo $this->Form->create('User', array('action' => 'new_user'));
echo $this->Form->input('email');
echo $this->Form->input('password');
echo $this->Form->input('password_confirmation',array('type' => 'password'));
echo $this->Form->end('Zarejestruj');
My AppController class:
class AppController extends Controller {
var $components = array('Auth','Session');
function beforeFilter() {
$this->Auth->fields = array('username' => 'email', 'password' => 'password');
$this->Auth->allow('index','view','display','new_user');
$this->Auth->authError = 'Zaloguj się aby zobaczyć tą stronę.';
$this->Auth->loginError = 'Wprowadzono niepoprawne dane.';
$this->Auth->loginRedirect = array('controller'=>'pages','action'=>'home');
$this->Auth->loginRedirect = array('controller'=>'pages','action'=>'home');
}
}
CakePHP automatically hashes fields named password in a User model. This is why you get an already hashed password back when the form fails. You might want to check if the hash you get back is the same hash as you'd expect to get back.
Apart from that, in your function matchPasswords your checking on $this->data['password'] whereas I think that should be $this->data['User']['password'].

Resources