validate data in an array - cakephp

Can the validates method validate user-defined arrays? for example:
Model:
App::uses('AppModel', 'Model');
class Recipe extends AppModel {
public $validate = array(
'price' => 'numeric'
);
}
And in Controller:
App::uses('AppController', 'Controller');
class RecipesController extends AppController {
public function add() {
if($this->request->is('post') && $this->request->data){
$data = array('price' => $this->request->data['myprice']);
$this->Reservation->validates($data); //validate the $data array
}
else{
throw new NotFoundException();
}
}
}

for manually validate you should try this :
$this->Reservation->set( $data);
if($this->Reservation->validates(){
//your code
}else{
$this->validateErrors($this->Reservation);
}

in your controller you can work with a fieldlist like this:
if ($this->Model->validates(array(
'fieldList' => array(
'reason',
'name',
'message',
)
))) {
}
Hope thats what youre looking for.

Related

How to join two tables using models in cakephp

I just created 2 models UsersModel and UserpicsModel and try to get both records but it is returning Error: Call to a member function find() on a non-object.
//UsersModel.php
class Users extends AppModel
{
public $hasMany = array(
'Userpics' => array(
'className' => 'Userpics'
)
);
}
//UserpicsMdoel.php
class Userpics extends AppModel
{
public $belongsTo = array(
'Users' => array(
'className' => 'Users',
'foreignKey' => 'uid'
)
);
}
//RecipesController.php
class RecipesController extends AppController {
public $uses =array('Users','Userpics');
public function view() {
$users = $this->Users->Userpics->find('all');
print('<pre>');
print_r($users);
print('<pre>');
exit;
}
}
first: you are not following cake conventions: models should be singular and not plural.
But the actual problem here is that the model files names are wrong: if you still want to use your conventions then the name for the Users model should be Users.php and not UsersModel.php
the same for Userpics
read this useful answer about how to debug this kind of error.
But if you decide to use the cake naming conventions (and I strongly suggest you to do so) consider doing the following:
//User.php (table users)
class User extends AppModel
{
....
}
//UserPic.php (table user_pics)
class UserPic extends AppModel
{
....
}
//RecipesController.php
class RecipesController extends AppController {
public $uses =array('User','UserPic');
public function view() {
$users = $this->User->UserPic->find('all');
print('<pre>');
print_r($users);
print('<pre>');
exit;
}
}
//UsersModel.php
class Users extends AppModel
{
public $hasMany = array(
'Userpics' => array(
'className' => 'Userpics',
'foreignKey' => 'uid'
)
);
}

How to save HABTM association in CakePhp?

I have a Product model and an Image model. They have an HABTM association.
Some Images exist but they are not linked to the product.
Now when I save a Product I would like to link it to some unlinked images using an array of images IDs (I MUST use this array).
Here's my code:
class Image extends AppModel {
public $useTable = 'images';
var $hasAndBelongToMany = array(
'Product' => array(
'className' => 'Product',
'joinTable' => 'products_images',
'foreignKey' => 'id_image',
'associationForeignKey' => 'id_product'
)
);
}
class Product extends AppModel {
public $useTable = 'products';
var $hasAndBelongToMany = array(
'Image' => array(
'className' => 'Image',
'joinTable' => 'products_images',
'foreignKey' => 'id_product',
'associationForeignKey' => 'id_image'
)
);
}
class productsController extends AppController {
public $name = 'Products';
public $uses = array('Products', 'File');
public function add() {
if (!empty($this->data)) {
$this->Product->create();
if ($this->AnnuncioImmobiliare->save($this->request->data)) {
$idProduct = $this->Product->getLastInsertID();
$this->request->data['imagesIds'] = array("1", "2", "3");
if(isset($this->request->data['imagesIds'])){
foreach($this->request->data['imagesIds'] as $imageId){
$this->Image->id = $imageId;
$this->Image->save(array('Product'=>array('id'=>$idProduct)));
}
}
}
}
}
}
This doesn't work. Where am I wrong?
1) you didn't provide the data, so we can't verify it's in the correct format.
2) you're using "save()" not "saveAll()" or "saveMany()" or "saveAssociated()". Just using "save()" will not save any associated model data.
I found a solution myself!
I observed how CakePHP handles $this->data->response array when data is passed using an input automagically created for HABTM associations and I found the array should be formatted like this:
array(
'Product' => array(
'name' => 'myProduct',
'id' => ''
),
'Image' => array(
'Image'=>array(
0 => '1',
1 => '2',
2 => '3'
)
)
)
So the correct code for the controller is
class productsController extends AppController {
public $name = 'Products';
public $uses = array('Products', 'File');
public function add() {
if (!empty($this->data)) {
$this->Product->create();
if (isset($this->request->data['imagesIds'])) {
$this->request->data['Image'] = array('Image' => $this->request->data['imagesIds']);
}
if ($this->AnnuncioImmobiliare->save($this->request->data)) {
/* success */
}
}
}
}
That's it! I hope you find this useful.

Unit testing the Auth Component

I am using the following code to test the login action in UsersController
public function testLogin() {
$data = array('User' => array(
'username' => 'hello',
'password' => '411'
)
);
$this->Users = $this->generate('Users',array('components'=> array('Auth','Session')));
$this->Users->Auth->staticExpects($this->once())
->method('user')
->with('id');
$this->testAction('/users/login', array('data' => $data, 'method' => 'post'));
}
and the fixture is-
class UserFixture extends CakeTestFixture {
public $import = array('model' => 'User', 'records' => true, 'connection' => 'fixture');
}
adn action is-
public function login() {
if($this->request->is('post')) {
if($this->Auth->login()) {
$this->redirect($this->Auth->redirect());
} else {
return false;
$this->Session->setFlash(__('Wrong Username Or Password,Please Try Again'));
}
}
}
It always showing
Expectation failed for method name is equal to when invoked 1 time(s).
Method was expected to be called 1 times, actually called 0 times.
What is the problem?Cant find any solution,and the reason also.Please help.
I think your problem mocking the auth component is that in addition to including auth in your components array, you need to specify which methods of Auth to mock, and how to mock them.
The way I deal with AuthComponent in my tests is I create a superclass with a method: _generateMockWithAuthUserId which mocks the Auth component, among other things, the way I need.
I've pasted the code from my superclass below.
class AppControllerTest extends ControllerTestCase {
public function setUp() {
parent::setUp();
$this->User = ClassRegistry::init('User');
}
public function tearDown() {
unset($this->User);
parent::tearDown();
}
public function testPlaceholder(){
// This just here so we don't get "Failed - no tests found in class AppControllerTest"
$this->assertTrue(true);
}
protected function _generateMockWithAuthUserId($contollerName, $UserId){
$this->authUserId = $UserId;
$this->authUser = $this->User->findById($this->authUserId);
$this->controller = $this->generate($contollerName, array(
'methods' => array(
'_tryRememberMeLogin',
'_checkSignUpProgress'
),
'components' => array(
'Auth' => array(
'user',
'loggedIn',
),
'Security' => array(
'_validateCsrf',
),
'Session',
)
));
$this->controller->Auth
->expects($this->any())
->method('loggedIn')
->will($this->returnValue(true));
$this->controller->Auth
->staticExpects($this->any())
->method('user')
->will($this->returnCallback(array($this, 'authUserCallback')));
}
public function authUserCallback($param){
if(empty($param)){
return $this->authUser['User'];
} else {
return $this->authUser['User'][$param];
}
}
}
And then here's a example of a class that inherits from that superclass. Take note of where/how it calls _generateMockWithAuthUserId. Basically, doing that sets up a suitable controller with Auth mocked for the appropriate user id.
<?php
require_once dirname(__FILE__) . DS . 'AppControllerTest.php';
class EmployeeNotesControllerTestCase extends AppControllerTest {
public $fixtures = array(
// your fixtures go here
);
public function setUp() {
parent::setUp();
$this->EmployeeNote = ClassRegistry::init('EmployeeNote');
}
public function tearDown() {
unset($this->EmployeeNote);
parent::tearDown();
}
public function testSupervisorIndexCanNotSeeNotesOnSelf() {
$authUserId = 1;
$this->_generateMockWithAuthUserId('EmployeeNotes', $authUserId);
$this->controller->Session
->expects($this->once())
->method('setFlash');
$result = $this->testAction('supervisor/employee_notes/index/'.$authUserId, array('return' => 'vars', 'method' => 'get'));
$this->assertTrue(empty($result['employeeNotes']));
}
}
Hope that helps.
I have found a solution.it worked.
public function testLogin() {
$data = array('User' => array(
'username' => 'sasa',
'password' => '111'
)
);
$this->Users = $this->generate('Users', array());
$result = $this->testAction('/users/login', array('data' => $data, 'method' => 'post'));
$this->assertEquals($data['User']['username'],$this->Users->Session->read('Auth.User.username'));
$result = $this->testAction('/users/logout');
}

cakephp plugin search cakeDC usage

I'm using the 2.0 version of cakephp search plugins by cakeDC (with cakephp 2.x)(https://github.com/CakeDC/search) . I'm need search in many models but thats models aren't related. So i create a new model (search) and a controller (searches) . I got this error
"Notice (8): Indirect modification of overloaded property SearchesController::$paginate has no effect [APP/Controller/SearchesController.php, line 17]"
Model:
App::uses('AppModel', 'Model');
class Search extends AppModel {
public $actsAs = array('Search.Searchable');
public $useTable = false;
public $filterArgs = array(
'terminada' => array(
'type' => 'like',
'field' => array(
'Sludge.terminada',
'SurfacesWater.terminada',
'ResidualWater.termianda',
'UndergroundWater.terminada',
'PotableWater.terminada',
'SpecifiedsResidualsWater.terminada'
)
),
'revisada' => array(
'type' => 'like',
'field' => array(
'Sludge.revisada',
'SurfacesWater.revisada',
'ResidualWater.revisada',
'UndergroundWater.revisada',
'PotableWater.revisada',
'SpecifiedsResidualsWater.revisada'
)
),
'eliminada' => array(
'type' => 'like',
'field' => array(
'Sludge.eliminada',
'SurfacesWater.eliminada',
'ResidualWater.eliminada',
'UndergroundWater.eliminada',
'PotableWater.eliminada',
'SpecifiedsResidualsWater.eliminada'
)
),
);
public function orConditionsDates($data = array()) {
$start = date('Y-m-d');
$end = date('Y-m-d', strtotime('-1 month'));
$cond = array(
'OR' => array(
$this->alias . '.monitoreofecha LIKE <=' => $end,
$this->alias . '.monitoreofecha LIKE >=' => $start,
));
return $cond;
}
}
Controller:
App::uses('AppController', 'Controller');
class SearchesController extends AppController {
public $components = array('Search.Prg');
public $presetVars = true; // using the model configuration
public function index() {
$this->Prg->commonProcess();
$this->paginate['conditions'] = $this->Search->parseCriteria($this->passedArgs);
$this->set('searches', $this->paginate());
}
}
The view is the same of any index make with bake
Any idea how what is my mistake?
Thanks for all!!
S.
if you do it this way you need to declare paginate first in your controller:
public $paginate = array();
or initialize it in your method directly
$this->paginate = array();
Try do it this way:
App::uses('AppController', 'Controller');
class SearchesController extends AppController {
public $components = array('Search.Prg');
public $presetVars = true; // using the model configuration
public $paginate = array();
public function index() {
$this->Prg->commonProcess();
$cond = $this->Search->parseCriteria($this->passedArgs);
$this->set('searches', $this->paginate('Search', $cond));
}
}

Testing a CakePHP 2.0.5 Helper which extends FormHelper

I am creating a CakePHP helper which extends from FormHelper:
App::uses('FormHelper', 'View/Helper');
class MyFormHelper extends FormHelper{
public function wysiwyg($fieldName, $options = array()){
return parent::textarea('Model.field');
}
}
Here is my TestCase:
App::uses('Controller', 'Controller');
App::uses('View', 'View');
App::uses('MyFormHelper', 'View/Helper');
class MyFormHelperTest extends CakeTestCase {
public $helper = null;
public function setUp() {
parent::setUp();
$Controller = new Controller();
$View = new View($Controller);
$this->helper = new MyFormHelper($View);
}
public function testWysiwyg() {
$result = $this->helper->wysiwyg('Model.field');
$expected = array(
'textarea' => array('name' => 'data[Model][field]', 'id' => 'ModelField'),
'/textarea',
);
$this->assertTags($result, $expected);
}
}
When I run the test, I have a PHPUNIT_FRAMEWORK_ERROR_NOTICE
Trying to get property of non-object
I know that the problem comes from my helper:
return parent::textarea('Model.field');
I have no idea how to fix this.
Thanks in advance :)
To overwrite a HtmlHelper method in Cake 2.0 you can simply:
Create your OwnHelper class containing for example a link method, which extends HtmlHelper, in AppController specify:
$helpers = array('Html' => array('className' => 'OwnHelper'));
via ADmad

Resources