Testing controller on CakePHP2.0 which calls model functions - cakephp

This is my test:
public function testIncludeNumComment() {
$post = array(...stuff.....);
$result = $this->Comments->includeNumComments($post);
echo "end"; //this is not printed
$expected =1;
$this->assertEquals($result, $expected);
}
Then, my controller function is this one:
public function includeNumComments($post){
echo "printed";
$comments = $this->Comment->getNumComments($post['Post']['id']);
echo "not printed";
return $comments;
}
As you can see, this call on the controller to the model function doesn't work
$this->Comment->getNumComments($idPost);
And what is more, when i introduce an echo "hi"; at the very start of the getNumComments function inside the Comment model, it is not printed either.
It's like it didn't find the function or something like that. (but it doesn't show any error by screen during the test)
It stops there and it doesn't execute more code.
I am completely sure that function works well, it just returns the number of comments from a post. The question is: why it isn't working on the test case?
Thanks.
UPDATE:
The test setUp looks like this:
public function setUp() {
parent::setUp();
$this->Comments = new TestCommentsController();
$this->Comments->constructClasses();
}

$result = $this->Comments->includeNumComments($post);
this doesnt make much sense if your model is "Comment"
so change it to:
$result = $this->Comment->includeNumComments($post);

Check that you include the TestCommentsController like following:
App::uses('TestCommentsController', 'Controller');
Then write beforeFilter function in AppController like following:
class AppController extends Controller {
......
...
public function beforeFilter() {
// you stuff
}
}
Then add this to you controller which contains test function:
public function beforeFilter(){
parent::beforeFilter();
$this->Comments = new TestCommentsController();
$this->Comments->constructClasses();
}
.....
NOW keep going with...
public function testIncludeNumComment() {
$post = array(...stuff.....);
$result = $this->Comments->includeNumComments($post);
echo "end"; //this is not printed
$expected =1;
$this->assertEquals($result, $expected);
}

Related

Displaying array values in laravel 5.2

I have the following hasMany() relationship in App\User.php ,
public function partner_preference_occupation()
{
return $this-hasMany('App\Models\User\PartnerPreferenceOccupation', 'user_id');
}
The following is my PartnerPreferenceOccupation Model,
<?php
namespace App\Models\User;
use App\Models\BaseModel,
App\Models\ValidationTrait;
class PartnerPreferenceOccupation extends BaseModel {
use ValidationTrait;
public function __construct() {
parent::__construct();
$this->__validationConstruct();
}
/**
* The database table used by the model.
*
* #var string
*/
protected $table = 'partner_preferences_occupation';
protected $fillable = array('user_id', 'occupation_id');
protected $dates = array();
public $uploadPath = array();
protected function setRules() {
$this->val_rules = array();
}
protected function setAttributes() {
$this->val_attributes = array();
}
public function occupation_name() {
return $this->belongsTo('App\Models\Master\OccupationModel', 'occupation_id');
}
}
I want to display the array of occupation name in my view. I tried the following code, but it fails.
{{$obj->partner_preference_occupation ? $obj-partner_preference_occupation->occupation_name->name : null}}
The error is as follows,
Undefined property:Illuminate\Database\Eloquent\Collection::$occupation_name
How can I display them.Thanks in advance.
There is a typo in $obj-partner_preference_occupation->occupation_name->name
Should be $obj->partner_preference_occupation->occupation_name->name
Make sure that occupation_name exists in the collection. You can check by doing the following in your View:
dump( $obj->partner_preference_occupation );
It might help you identify where the issue lies.
Also, to display a collection as an array, you can use the toArray() method, e.g.:
$obj->partner_preference_occupation->toArray()
Ok I got it,
As it is an array of values to be fetched, I used foreach to display them in my view as,
#if($occ=$obj->partner_preference_occupation->lists('occupation_name'))
#foreach($occ as $oc)
{{$oc->name}}
#endforeach
#endif
occupatoin_name is the name of my relationship that I used in my model. And that worked for me :)

CakePHP 3 : display data from other model and pass parameter in url from action

I'm working on a project using CakePHP 3.x.
I have UserAddress, ServiceRequests, Service models.
There is a button on service/view/$id which when clicked will ask user to select address from service-requests/serviceArea which has a list of addresses added by user. service-requests/serviceArea view will contain a select button which when clicked will call add action in ServiceRequests controller with passing two parameters serviceId and userAddressId
This is the serviceArea function created by me.
public function serviceArea($id = null)
{
public $uses = array('UserAddress');
$service = $id;
$query = $userAddresses->find('all')
->where(['UserAddresses.user_id =' => $this->Auth->user('id')]);
$this->set(compact('userAddresses'));
$this->set('_serialize', ['userAddresses']);
}
How to display the address and also pass the $service parameter to the serviceArea view.
I am new to CakePHP, so if you think question is incomplete any edit to it will be appreciated instead of down-voting.
Thank You.
Edit 2
Thank for your answer #jazzcat
After changing my code according to yours and visiting http://domain.com/service-requests/service-area/$id. It is showing error as
Record not found in table "service_requests"
and pointing to the ServiceRequestsController on line no 33
The ServiceRequestController as containing line no 33 is
<?php
namespace App\Controller;
use App\Controller\AppController;
/**
* ServiceRequests Controller
*
* #property \App\Model\Table\ServiceRequestsTable $ServiceRequests
*/
class ServiceRequestsController extends AppController
{
/**
* isAuthorized method
*
*/
public function isAuthorized($user)
{
$action = $this->request->params['action'];
// The add and index actions are always allowed.
if(in_array($action, ['index', 'add', 'serviceRequests'])) {
return true;
}
// All other actions require an id.
if (empty($this->request->params['pass'][0])) {
return false;
}
// Check that the service request belongs to the current user.
$id = $this->request->params['pass'][0];
$serviceRequest = $this->ServiceRequests->get($id); // line : 33
if($serviceRequest->user_id == $user['id']) {
return true;
}
return parent::isAuthorized($user);
}
/* Other actions */
}
?>
This worked for me.
Just added the serviceArea action name in the isAuthorized method
if(in_array($action, ['index', 'add', 'serviceArea'])) {
return true;
}
and it's working fine as expected.
There is alot wrong with your code. Please read the docs
Is the table named user_addresses or user_address ?
You seem to mix the both.
The following would be the correct way to do it assuming your table is named user_addresses
public function serviceArea($id = null)
{
$this->loadModel('UserAddresses');
$userAddresses = $this->UserAddresses->find('all')
->where(['UserAddresses.user_id =' => $this->Auth->user('id')]);
// If you want to filter on the serviceArea ID aswell
if($id)
$userAddresses->andWhere(['id' => $id]);
// Setting SerivceArea ID to compact makes it available in view.
$serviceAreaId = $id;
$this->set(compact('userAddresses', 'serviceAreaId'));
$this->set('_serialize', ['userAddresses']);
}
This snippet:
$id = $this->request->params['pass'][0];
$serviceRequest = $this->ServiceRequests->get($id); // line : 33
Just checks if the first parameter passed to the method exists in ServiceRequests.
(That parameter could be anything, you have to keep that in mind when creating all your methods in that controller, that is to say the least.. bad)
I'm assuming that the service_requests table is associated with the users table and an user_id column exists in the service_requests table.
If that is the case this should work:
public function isAuthorized($user)
{
$action = $this->request->params['action'];
// The add and index actions are always allowed.
if(in_array($action, ['index', 'add'])) {
return true;
}
// Is not authorized if an argument is not passed to the method.
// Don't know why you'd want this , but sure.
if (empty($this->request->params['pass'][0])) {
return false;
}
// Check that the service request belongs to the current user.
$user_id = $this->Auth->user('id');
$serviceRequest = $this->ServiceRequests->find()->where(['ServiceRequests.user_id' => $user_id])->first();
if(!empty($serviceRequest)) {
return true;
}
return parent::isAuthorized($user);
}

Declaration of Upload::beforeSave() should be compatible with Model::beforeSave($options = Array) [APP/Model/Upload.php, line 5]

I am being shown the following error on top of my page when using beforeSave method in my Upload model.
Strict (2048): Declaration of Upload::beforeSave() should be
compatible with Model::beforeSave($options = Array)
[APP/Model/Upload.php, line 5]
Could someone point out what I'm doing wrong?
Here is my model:
<?php
App::uses('AppModel', 'Model');
class Upload extends AppModel {
protected function _processFile() {
$file = $this->data['Upload']['file'];
if ($file['error'] === UPLOAD_ERR_OK) {
$name = md5($file['name']);
$path = WWW_ROOT . 'files' . DS . $name;
if (is_uploaded_file($file['tmp_name'])
&& move_uploaded_file($file['tmp_name'], $path) ) {
$this->data['Upload']['name'] = $file['name'];
$this->data['Upload']['size'] = $file['size'];
$this->data['Upload']['mime'] = $file['type'];
$this->data['Upload']['path'] = '/files/' . $name;
unset($this->data['Upload']['file']);
return true;
}
}
return false;
}
public function beforeSave() {
if (!parent::beforeSave($options)) {
return false;
}
return $this->_processFile();
}
}
?>
Just change this line
public function beforeSave() {
to this, so you have correct method declaration
public function beforeSave($options = array()) {
The beforeSave() function executes immediately after model data has been successfully validated, but just before the data is saved. This function should also return true if you want the save operation to continue.
This callback is especially handy for any data-massaging logic that needs to happen before your data is stored. If your storage engine needs dates in a specific format, access it at $this->data and modify it.
Below is an example of how beforeSave can be used for date conversion. The code in the example is used for an application with a begindate formatted like YYYY-MM-DD in the database and is displayed like DD-MM-YYYY in the application. Of course this can be changed very easily. Use the code below in the appropriate model.
public function beforeSave($options = array()) {
if (!empty($this->data['Event']['begindate']) &&
!empty($this->data['Event']['enddate'])
) {
$this->data['Event']['begindate'] = $this->dateFormatBeforeSave(
$this->data['Event']['begindate']
);
$this->data['Event']['enddate'] = $this->dateFormatBeforeSave(
$this->data['Event']['enddate']
);
}
return true;
}
public function dateFormatBeforeSave($dateString) {
return date('Y-m-d', strtotime($dateString));
}
Make sure that beforeSave() returns true, or your save is going to fail.

CakePHP Custom Helper not working

MY first time creating a custom helper. I'm getting an error in my Controller Code that I"m calling a a method on a non existed object (helper). Yet i believe my helper "BM" is being loaded successfully because i'm not getting any errors on loading helpers.
Error: Call to a member function mcpGetActiveMerchantID() on a non-object
File: C:\wamp\www\bm\app\Controller\MCPController.php
Line: 412
I have placed BMHelper.php into my View\Helper\ directory.
<?php
class BMHelper extends AppHelper{
public function mcpGetActiveMerchant(){
return $this->Session->read('Auth.ActiveMerchant');
}
public function mcpGetActiveMerchantID() {
$activemerchant = $this->Session->read('Auth.ActiveMerchant');
foreach($activemerchant as $key => $value) {
$merchant_id = $key;
}
return $merchant_id;
}
}
?>
Then in my Controller I have this:
<?php
class MCPController extends AppController {
public $helpers = array('Html', 'Form', 'Session','BM','Js' => array('Jquery'));
public function walkinadd() {
$test = $this->BM->mcpGetActiveMerchantID(); //Line 412
}
}
?>
HEre is the error again (same as the error I pasted at the top)
Error: Call to a member function mcpGetActiveMerchantID() on a non-object
File: C:\wamp\www\bm\app\Controller\MCPController.php
Line: 412
Anyone know what is wrong?
Helpers are to be used in Views not Controllers, though you could do:
public function walkinadd() {
$view = new View($this);
$bm = $view->loadHelper('BM');
$test = $bm->mcpGetActiveMerchantID();
}

How to use global variable in cakephp

this code
class CircumstancesController extends AppController {
public $circumstances = array();
public function init() {
$this->circumstances = $this->getAllCircumstance();
}
//get all circumstances
public function getAllCircumstance() {
$arr_allcircumstance = $this->Circumstance->find('all', array(
'recursive' => -1
));
return $arr_allcircumstance;
}
public function getCircumstances($circumstance) {
$arr_cir = $this->circumstances;
return $arr_cir;
}
public function data_matrix() {
pr($this->getCircumstances(3));
}
}
i had a variable "$circumstances"(type array) when i call function data_matrix() then function result is NULL.
$arr_cir = $this->circumstances;
why $arr_cir is null ???
thank all.
public $circumstances = array();
Because this is a empry array that why it's return empty
public $circumstances = array(3,5);
Please use this and check
push some values into array.. and after debug() or print it to exactly view the array values. try it .
You need to rename your init() function to beforeFilter().
BeforeFilter documentation

Resources