Access values modified with beforeSave() in cakePHP - php

I am using beforeSave() to assign the user a temporary customer number. I need to return this value to the device accessing the API. Is it possible to access that from my controller?
// app/Model/User.php
<?php
class User extends AppModel {
function beforeSave($options) {
$this->data['User']['customerNumber'] = uniqid(); // This is the value I want
$this->data['User']['password'] = md5($this->data['User']['password']);
}
function isUnique() {
$users = $this->find('all', array('conditions' => array('email' => $this->data['User']['email'])));
if (empty($users)) {
return true;
} else {
return false;
}
}
}
?>
// app/Controller/UserController.php
<?php
class UserController extends AppController {
public $components = array('RequestHandler');
public function register() {
if ($this->request->is('post')) {
$this->User->set($this->data);
if ($this->User->isUnique()) {
if ($this->User->save($this->data)) {
// This is where I need to return the customer number
echo json_encode(array('status' => 'User registered', 'customerNumber' => $this->data['customerNumber']));
} else {
echo json_encode(array('status' => 'User could not be registered'));
}
} else {
echo json_encode(array('status' => 'user is duplicate'));
}
} else {
echo json_encode(array('error' => 'Requests must be made using HTTP POST'));
}
}
}
?>
As a secondary question, is uniqid() an okay way to assign temporary customer numbers?

You can't get to that value directly, but you can immediately fetch it after a succesful save, like:
if ($this->User->save($this->data)) {
// Fetch inserted row
$user = $this->User->findById($this->User->getInsertId());
echo json_encode(array(
'status' => 'User registered',
'customerNumber' => $user['User']['customerNumber']
));
}

Related

What is the best way to return validation messages with Phalcon PHP as json

I'm creating REST API, and I want to return messages from validation.
Here is example with user register:
class Users extends Phalcon\Mvc\Model {
public function validation() {
$validator = new Validation();
$validator->add('email', new PresenceOf([
'message' => 'The email is required'
]));
$validator->add('email', new Email([
'message' => 'Invalid email given'
]));
$validator->add('email', new Uniqueness([
'message' => 'Sorry, The email was registered by another user'
]));
return $this->validate($validator);
}
Here is my current code:
class UserController extends Phalcon\Mvc\Controller {
public function register() {
$data = $this->request->getJsonRawBody();
$user = new Users();
$user->setEmail($data->email)->setUsername($data->username)->setPassword($data->password);
if ($user->save() === false) {
$data = [];
$messages = $user->getMessages();
foreach ($messages as $message) {
$data[] = array(
'field' => $message->getField(),
'type' => $message->getType(),
'message' => $message->getMessage()
);
}
return $this->response->setStatusCode(409, 'Conflict')->setJsonContent(array('error' => $data));
}
return $this->response->setStatusCode(201, 'Created')->setJsonContent(array('message' => "User id:" . $user->getId() . " created"));
}
When I change this for loop with something like that I get empty response:
return $this->response->setStatusCode(409, 'Conflict')->setJsonContent(array('error' => $user->getMessages()));
The question is it possible make this code shorter without loop trough messages, but just simple return json object.
You can do it with very little modifications by extending default methods. Here is a working sample of your code:
// BaseModel class which overwrites default Phalcon methods if needed.
class BaseModel extends \Phalcon\Mvc\Model
{
public function getMessagesNormalized()
{
$messages = parent::getMessages();
$data = [];
foreach ($messages as $message) {
$data[] = array(
'field' => $message->getField(),
'type' => $message->getType(),
'message' => $message->getMessage()
);
}
return $data;
}
}
// Note that your models from now on extend BaseModel which extends \Phalcon\Mvc\Model
class Users extends BaseModel {
// ...
}
// Your controller
class UserController extends Phalcon\Mvc\Controller {
public function register() {
$data = $this->request->getJsonRawBody();
$user = new Users();
$user->setEmail($data->email)->setUsername($data->username)->setPassword($data->password);
if ($user->save() === false) {
$data = [];
// Get the messages in RESTsuitable format
$messages = $user->getMessagesNormalized();
return $this->response->setStatusCode(409, 'Conflict')->setJsonContent(array('error' => $data));
}
return $this->response->setStatusCode(201, 'Created')->setJsonContent(array('message' => "User id:" . $user->getId() . " created"));
}

Unable to view Form page in CodeIgniter facing Error

This is my home.php file in this controller I am facing Fatal error: Uncaught ArgumentCountError:
I have also attached a screenshot, In this screenshot error mentioned, You can easily understand the error through this screenshot, I am newbie in CodeIgniter.
[
I upload only my controller related file.
<?php
class home extends CI_Controller {
function __construct() {
parent::__construct();
$this->load->model('select');
$this->load->helper(array('form', 'url', 'html'));
$this->load->library(array('form_validation', 'session'));
}
function records() {
$ytl['dta'] = $this->users->datas();
//$this->load->view('info',$ytl);
//echo "<pre>controller";print_r($ytl);
}
function primezone() {
$ytl['dta'] = $this->users->datas();
echo "<pre>controller";
print_r($ytl);
}
function form($id) {
//die($id);
if ($this->input->post()) {
//echo"<pre>";print_r( $this->input->post());die;
$this->form_validation->set_rules('fname', 'First Name', 'required|min_length[5]');
$this->form_validation->set_rules('lname', 'Last Name', 'required|callback_check_picture[lname]');
//$this->form_validation->set_rules('email','Email','required');
$this->form_validation->set_rules('mobile', 'Mobile Number', 'required|callback_valid_phone_number[mobile]');
$this->form_validation->set_error_delimiters('<h1 class="error">', '</h1>');
if ($this->form_validation->run() == TRUE) {
$data = [
'fname' => $this->input->post('fname'),
'lname' => $this->input->post('lname'),
'email' => $this->input->post('email'),
'mobile' => $this->input->post('mobile'),
'message' => $this->input->post('message'),
];
if (empty($id)) {
$ytl = $this->select->insertdata($data);
} else {
$ytl = $this->select->updatedata($data, $id);
}
if ($ytl) {
$this->session->set_flashdata('message', 'Successfully Added.');
redirect('home');
}
} else {
//$this->load->view('form');
}
}
$ytl['dta'] = $this->select->getDataById($id);
//echo "<pre>";print_r($ytl);die;
$this->load->view('form', $ytl);
}
public function check_picture($a) {
if ( ! is_numeric($a)) {
return TRUE;
} else {
$this->form_validation->set_message('check_picture', 'Please enter only char value');
return FALSE;
}
}
function valid_phone_number($value) {
$value = strlen($value);
//echo $value;die;
if ($value == 10) {
return TRUE;
} else {
$this->form_validation->set_message('valid_phone_number', 'Mobile number not in range'); //{10}
return FALSE;
}
}
public function index() {
//load the database
//$this->load->database();
//load the model
$this->load->model('select');
//load the method of model
$data['h'] = $this->select->select();
//return the data in view
$this->load->view('fetch_view', $data);
}
public function delete() {
$this->load->model('select');
$id = $this->input->get('id');
if ($this->select->deleteuser($id)) {
$data['data'] = $this->select->getuser();
$this->load->view('fetch_view', $data);
}
}
}
The error you have mention is normally came when there is mismatch in param mention in function and the passing ones.
According to your code
public function form($id)
$id is required and you are not passing that.
So change your code to
public function form($id=null)
Set default id value in your controller function like
function form($id = null){
....
}

CakePHP error for the connexion with ACL

I'm trying to understand how Cakephp works. I built a connection system with a simple form (username and password). When I click on the submit button (with the correct username and password), I always receive the same flash message, "Your username or password was incorrect". I tried many things, but I don't know how to fix it .
If I'm logged, I want to be redirect on Google (it's the test i try) .
Look at my code :
login.ctp (View)
<?php
echo $this->Form->create('User',array('action'=>'login'));
echo $this->Form->inputs(array('legend'=>'Se connecter','username','password'));
echo $this->Form->end('Se connecter');
?>
UsersController
class UsersController extends AppController {
public function beforeFilter() {
parent::beforeFilter();
$this->Auth->allow();
}
public function login() {
if ($this->request->is('post')) {
if ($this->Auth->login()) {
$this->User->id = $this->Auth->user("id");
$this->redirect('http://www.google.fr');
} else {
$this->Session->setFlash('Your username or password was incorrect.');
}
}
}
}
User (Model)
<?php
App::uses('AppModel', 'Model', 'AuthComponent', 'Controller/Component');
class User extends AppModel {
public $actsAs = array('Acl' => array('type' => 'requester'));
public function parentNode() {
if (!$this->id && empty($this->data)) {
return null;
}
if (isset($this->data['User']['group_id'])) {
$groupId = $this->data['User']['group_id'];
} else {
$groupId = $this->field('group_id');
}
if (!$groupId) {
return null;
} else {
return array('Group' => array('id' => $groupId));
}
}
public function beforeSave($options = array()) {
$this->data['User']['password'] = AuthComponent::password($this->data['User']['password']);
return true;
}
public $belongsTo = array(
'Group' => array(
'className' => 'Group',
'foreignKey' => 'group_id',
'conditions' => '',
'fields' => '',
'order' => ''
)
);
}
?>
The password in my table user (sql) :
password char(40) latin1_swedish_ci

CakePHP DB field update fail

I am using cakePHP why won't the name insert into the table, a null value seams to be passed as the table is updated but with out the name?
Table in Database
CREATE TABLE tests (
id serial not null unique primary key,
name varchar,
created timestamp default CURRENT_TIMESTAMP
)
add.ctp
<?php
echo $this->Form->create('Post');
echo $this->Form->input('name');
echo $this->Form->end('RSVP');
?>
Test Model
<?php
class Test extends AppModel {
var $name = 'Test';
}
TestContoller
<?php
class TestController extends AppController {
public $helpers = array('Html', 'Form');
var $name = "Test";
public function index() {
$this->set('tests', $this->Test->find('all'));
}
public function view($id = null) {
$this->Test->id = $id;
$this->set('Test', $this->Test->read());
}
public function add() {
if ($this->request->is('post')) {
if ($this->Test->save($this->request->data)) {
$this->Session->setFlash('Your post has been saved.');
$this->redirect(array('action' => 'index'));
}
else {
$this->Session->setFlash('Unable to add your post.');
}
}
}
public function edit($id = null) {
$this->Test->id = $id;
if ($this->request->is('get')) {
$this->request->data = $this->Post->read();
}
else {
if ($this->Test->save($this->request->data)) {
$this->Session->setFlash('Your post has been updated.');
$this->redirect(array('action' => 'index'));
}
else {
$this->Session->setFlash('Unable to update your post.');
}
}
}
public function delete($id) {
if ($this->request->is('get')) {
throw new MethodNotAllowedException();
}
if ($this->Test->delete($id)) {
$this->Session->setFlash('The post with id: ' . $id . ' has been deleted.');
$this->redirect(array('action' => 'index'));
}
}
}
In your method you missed to include $this->Test->create();, which will add new row to table and inset new data to it.
public function add() {
if ($this->request->is('post')) {
$this->Test->create(); // missed this line
if ($this->Test->save($this->request->data)) {
$this->Session->setFlash('Your post has been saved.');
$this->redirect(array('action' => 'index'));
}
else {
$this->Session->setFlash('Unable to add your post.');
}
}
}

Real-world testing of CakePHP controllers?

I'm writing a new application with CakePHP (just-released 1.2.4), using SimpleTest 1.0.1. I have read the relevant sections of the Cookbook, searched on the Bakery, and read Mark Story's postings on controller testing (the hard way and with mocks).
Unfortunately, none of this talks about real-world testing of non-trivial controllers. Lots of apps put areas of the site behind a login, yet I cannot figure out how to test the simple scenario of:
guest access to protected page redirects?
valid credentials sets expected session variables?
invalid credentials re-displays login page with error message?
The controller and test below do not work as I thought they would. Both assertions fail and I also get a PHP error:
FAILED
[NULL] should not be null at [.../app/tests/cases/controllers/users_controller.test.php line 79]
.../app/tests/cases/controllers/users_controller.test.php -> UsersControllerTest -> testLogin
FAILED
Equal expectation fails as [NULL] does not match [Integer: 1] at [.../app/tests/cases/controllers/users_controller.test.php line 80]
.../app/tests/cases/controllers/users_controller.test.php -> UsersControllerTest -> testLogin
ERROR
Unexpected PHP error [Undefined index: action] severity [E_NOTICE] in [.../cake/libs/controller/components/auth.php line 266]
.../app/tests/cases/controllers/users_controller.test.php -> UsersControllerTest -> testLogin
Here is the controller (baked plus Mark Story's "hard way" testing method):
class UsersController extends AppController
{
var $name = 'Users';
var $helpers = array('Html', 'Form');
var $components = array('Auth');
function login()
{
}
function logout()
{
$this->redirect($this->Auth->logout());
}
function index()
{
$this->set('users', $this->paginate());
}
function view($id = null)
{
if (!$id)
{
$this->Session->setFlash(__('Invalid User.', true));
$this->redirect(array('action'=>'index'));
}
$this->set('user', $this->User->read(null, $id));
}
function add()
{
if (!empty($this->data))
{
$this->User->create();
if ($this->User->save($this->data))
{
$this->Session->setFlash(__('The User has been saved', true));
$this->redirect(array('action'=>'index'));
}
else
{
$this->Session->setFlash(__('The User could not be saved. Please, try again.', true));
}
}
}
function edit($id = null)
{
if (!$id && empty($this->data))
{
$this->Session->setFlash(__('Invalid User', true));
$this->redirect(array('action'=>'index'));
}
if (!empty($this->data))
{
if ($this->User->save($this->data))
{
$this->Session->setFlash(__('The User has been saved', true));
$this->redirect(array('action'=>'index'));
}
else
{
$this->Session->setFlash(__('The User could not be saved. Please, try again.', true));
}
}
if (empty($this->data))
{
$this->data = $this->User->read(null, $id);
}
}
function delete($id = null)
{
if (!$id)
{
$this->Session->setFlash(__('Invalid id for User', true));
$this->redirect(array('action'=>'index'));
}
if ($this->User->del($id))
{
$this->Session->setFlash(__('User deleted', true));
$this->redirect(array('action'=>'index'));
}
}
}
Here is the test:
/* SVN FILE: $Id$ */
/* UsersController Test cases generated on: 2009-08-05 17:08:03 : 1249507923*/
App::import('Controller', 'Users');
class TestUsers extends UsersController
{
var $autoRender = false;
var $redirectUrl;
var $redirectStatus;
var $renderedAction;
var $renderedLayout;
var $renderedFile;
var $stopped;
function redirect($url, $status = null, $exit = true)
{
$this->redirectUrl = $url;
$this->redirectStatus = $status;
}
function render($action = null, $layout = null, $file = null)
{
$this->renderedAction = $action;
$this->renderedLayout = (is_null($layout) ? $this->layout : $layout);
$this->renderedFile = $file;
}
function _stop($status = 0)
{
$this->stopped = $status;
}
}
class UsersControllerTest extends CakeTestCase
{
var $fixtures = array('user');
var $Users = null;
function startTest()
{
$this->Users = new TestUsers();
$this->Users->constructClasses();
$this->Users->Component->initialize($this->Users);
}
function prepareForAction()
{
$this->Users->beforeFilter();
$this->Users->Component->startup($this->Users);
}
function endTest()
{
$this->Users->Session->destroy();
unset($this->Users);
ClassRegistry::flush();
}
//-----------------------------------------------------------------------
function testUsersControllerInstance()
{
$this->assertTrue(is_a($this->Users, 'UsersController'));
}
function testLogin()
{
$this->Users->data = array(
'User' => array(
'username' => 'admin',
'password' => 'admin'
)
);
$this->prepareForAction();
$this->Users->login();
$this->assertNotNull($this->Users->redirectUrl);
$this->assertEqual($this->Users->Session->read('Auth.User.id'), 1);
}
}
The test you have isn't really testing your UsersContoller, you're really testing the AuthComponent. If you want to do this you need to make sure you setup your TestUsersController the same as it would be in your app. In the case of your testLogin you need to set the controller's action and url:
function testLogin()
{
$this->Users->data = array(
'User' => array(
'username' => 'admin',
'password' => 'admin'
)
);
$this->Users->params['url']['url'] = '/users/login';
$this->Users->params['action'] = 'login';
$this->prepareForAction();
$this->Users->login();
$this->assertNotNull($this->Users->redirectUrl);
$this->assertEqual($this->Users->Session->read('Auth.User.id'), 1);
}
Alternately, I would suggest taking another look at Mark's mock objects post and using those methods to write tests for the controller code and mocking the auth component.

Categories