Custom Session Handler on CakePHP 2.0.2 - php

i tried follow from http://book.cakephp.org/2.0/en/development/sessions.html#creating-a-custom-session-handler then i cant solve this and im really confuse about this :(
become like this:
<?php
App::uses('DatabaseSession', 'Model/Datasource/Session');
class CartSession implements CakeSessionHandlerInterface {
public $cacheKey;
public function __construct() {
$this->cacheKey = Configure::read('Session.handler.cache');
parent::__construct();
}
// read data from the session.
public function read($id) {
$result = Cache::read($id, $this->cacheKey);
if ($result) {
return $result;
}
return parent::read($id);
}
// write data into the session.
public function write($id, $data) {
$result = Cache::write($id, $data, $this->cacheKey);
if ($result) {
return parent::write($id, $data);
}
return false;
}
// destroy a session.
public function destroy($id) {
$result = Cache::delete($id, $this->cacheKey);
if ($result) {
return parent::destroy($id);
}
return false;
}
// removes expired sessions.
public function gc($expires = null) {
return Cache::gc($this->cacheKey) && parent::gc($expires);
}
}
?>
Output Error:
Fatal error: Class CartSession contains 2 abstract methods and must therefore be declared abstract or implement the remaining methods (CakeSessionHandlerInterface::open, CakeSessionHandlerInterface::close) in /Users/user/Sites/app/shop/Model/Datasource/Session/CartSession.php on line 43
I did added in core.php:
Configure::write('Session', array(
'defaults' => 'database',
'handler' => array(
'engine' => 'CartSession',
'model' => 'Session',
'cache' => 'apc'
)
));
Cache::config('apc', array('Engine' => 'Apc'));

You need to extend DatabaseSession. So your class declaration will look like:
class CartSession extends DatabaseSession implements CakeSessionHandlerInterface

Related

Default scope in Yii 1.1

AR model Player:
public function scopes()
{
return array(
'proleague' => array(
'condition' => 'mode = "proleague"',
),
'main' => array(
'condition' => 'mode = "main"',
),
);
}
Using model Player:
Player::model()->
proleague()->
with('startposition')->
findAllByAttributes(... here some condition ...);
^^^ That's all ok. Scope-condition will be executed. But...
In my project I have many places where any scope for Player model doesn't specified and in this cases I need use this scope-condition as default:
'main' => array(
'condition' => 'mode = "main"',
)
If I add defaultScope() method to Player model like this
public function defaultScope()
{
return array(
'condition' => 'mode = "main"',
);
}
the next code
Player::model()->
proleague()->
with('startposition')->
findAllByAttributes(... here some condition ...);
won't run correct. I won't get mode = "proleague" condition, becouse I'll use defaultScope() with mode = "main".
Any suggestions? How can I resolve the problem?
You should just use the resetScope(true) method. It "removes" the defaultScope filter.
$model = Player::model()->resetScope(true)->proleague();
create a new Class for this.
<?php
## e.g. protected/models/
class MyCoreAR extends CActiveRecord
{
/**
* Switch off the default scope
*/
private $_defaultScopeDisabled = false; // Flag - whether defaultScope is disabled or not
public function setDefaultScopeDisabled($bool)
{
$this->_defaultScopeDisabled = $bool;
}
public function getDefaultScopeDisabled()
{
return $this->_defaultScopeDisabled;
}
public function noScope()
{
$obj = clone $this;
$obj->setDefaultScopeDisabled(true);
return $obj;
}
// see http://www.yiiframework.com/wiki/462/yii-for-beginners-2/#hh16
public function resetScope($bool = true)
{
$this->setDefaultScopeDisabled(true);
return parent::resetScope($bool);
}
public function defaultScope()
{
if(!$this->getDefaultScopeDisabled()) {
return array(
'condition' => 'mode = "main"',
);
} else {
return array();
}
}
}
In your code:
// no default scope
$model = Player::model()->noScope()->proleague();
// with default scope
$model = Player::model()->proleague();

Mocking validator in Laravel with Mockery returning call to member function on a non-object

I'm trying to implement some unit tests for my REST controller. Everything works fine until I use the Validator facade. The index and show tests are working fine.
The error I'm getting is:
Fatal Error: Call to a member function setAttributeName() on a non-object in D:\....\controllers\AllergyController.
My code is:
//Unit test
class AllergyControllerTest extends TestCase
{
public function setUp()
{
parent::setUp();
$this->allergy = $this->mock('App\Modules\Patient\Repositories\IAllergyRepository');
}
public function mock($class)
{
$mock = Mockery::mock($class);
$this->app->instance($class, $mock);
return $mock;
}
public function tearDown()
{
parent::tearDown();
Mockery::close();
}
public function testIndex()
{
$this->allergy->shouldReceive('all')->once();
$this->call('GET', 'api/allergy');
$this->assertResponseOk();
}
public function testShow()
{
$this->allergy->shouldReceive('find')->once()->andReturn(array());
$this->call('GET', 'api/allergy/1');
$this->assertResponseOk();
}
public function testStore()
{
$validator = Mockery::mock('stdClass');
Validator::swap($validator);
$input = array('name' => 'foo');
$this->allergy->shouldReceive('create')->once();
$validator->shouldReceive('make')->once();
$validator->shouldReceive('setAttributeNames')->once();
$this->call('POST', 'api/allergy', $input);
$this->assertResponseOk();
}
}
My controller:
class AllergyController extends \App\Controllers\BaseController
{
public function __construct(IAllergyRepository $allergy){
$this->allergy = $allergy;
}
public function index()
{
...
}
public function show($id)
{
...
}
public function store()
{
//define validation rules
$rules = array(
'name' => Config::get('Patient::validation.allergy.add.name')
);
//execute validation rules
$validator = Validator::make(Input::all(), $rules);
$validator->setAttributeNames(Config::get('Patient::validation.allergy.messages'));
if ($validator->fails()) {
return Response::json(array('status' => false, 'data' => $validator->messages()));
} else {
$allergy = $this->allergy->create(Input::all());
if ($allergy) {
return Response::json(array('status' => true, 'data' => $allergy));
} else {
$messages = new \Illuminate\Support\MessageBag;
$messages->add('error', 'Create failed! Please contact the site administrator or try again!');
return Response::json(array('status' => false, 'data' => $messages));
}
}
}
}
I can't seem to fgure out why it's throwing this error. When I call the controller with a normal api call it works fine.
Any help is much appreciated!
You are probably wanting to return the validator double from the stubbed make call.
$validator->shouldReceive('make')->once()->andReturn($validator);

Testing laravel repository which has model as a dependency

Problem is that i can't test one function, because it is touching other functions of the same repository.
Do I need to test one function in isolation from other functions in same repository, or it is normal that one function can access other functions in same repository ?
If function needs to be tested in isolation from other, how it can be done, because I don't understand how I can mock repository in which I'm working. I understand how to mock dependencies, but how to mock other functions in same repository ?
Am I mocking model correctly in setUp method in the test?
Code:
Real world binding of and repository:
// Bind User repository interface
$app->bind('MyApp\Repositories\User\UserInterface', function () {
return new EloquentUser(new User);
});
EloquentUser.php:
public function __construct(Model $user)
{
$this->user = $user;
}
public function findById($id)
{
return $this->user->find($id);
}
public function replace($data)
{
$user = $this->findById($data['user']['id']);
// If user not exists, create new one with defined values.
if ( ! $user) {
return $this->create($data);
} else {
return $this->update($data);
}
}
public function create($data)
{
$user = $this->user->create($data['user']);
if ($user) {
return $this->createProfile($user, $data['profile']);
} else {
return false;
}
}
private function createProfile($user, $profile)
{
return $user->profile()->create($profile);
}
public function update($user, $data)
{
foreach ($data['user'] as $key => $value) {
$user->{$key} = $value;
}
if (isset($data['profile']) && count($data['profile']) > 0) {
foreach ($data['profile'] as $key => $value) {
$user->profile->$key = $value;
}
}
return ($user->push()) ? $user : false;
}
EloquentUserTest.php
public function setUp()
{
parent::setUp();
$this->user = Mockery::mock('Illuminate\Database\Eloquent\Model', 'MyApp\Models\User\User');
App::instance('MyApp\Models\User\User', $this->user);
$this->repository = new EloquentUser($this->user);
}
public function testReplaceCallsCreateMethod()
{
$data = [
'user' => [
'id' => 1,
'email' => 'test#test.com',
],
'profile' => [
'name' => 'John Doe',
'image' => 'abcdef.png',
],
];
// Mock the "find" call that is made in findById()
$this->user->shouldReceive('find')->once()->andReturn(false);
// Mock the "create" call that is made in create() method
$this->user->shouldReceive('create')->once()->andReturn(true);
// Run replace method that i want to test
$result = $this->repository->replace($data);
$this->assertInstanceOf('Illuminate\Database\Eloquent\Model', $result, 'Should be an instance of Illuminate\Database\Eloquent\Model');
}
When running this test I got:
Fatal error: Call to a member function profile() on a non-object in C:\Htdocs\at.univemba.com\uv2\app\logic\Univemba\Repositories\User\EloquentUser.php on line 107
So it means that Test is trying to touch function in EloquentUser.php:
private function createProfile($user, $profile)
{
return $user->profile()->create($profile);
}
Do I need to mock createProfile ? because profile() cant be found. And if I need to do this, how can i do it because this function is in same repository that i'm testing?
Question is solved.
Just needed to create one more Model instance and pass it in mocked method.
My Working setUp method:
public function setUp()
{
parent::setUp();
$this->user = Mockery::mock('MyApp\Models\User\User');
App::instance('MyApp\Models\User\User', $this->user);
$this->repository = new EloquentUser($this->user);
}
Working test method:
public function testReplaceCallsCreateMethod()
{
$data = [
'user' => [
'id' => 1,
'email' => 'test#test.com',
'password' => 'plain',
],
'profile' => [
'name' => 'John Doe',
'image' => 'abcdef.png',
],
];
// Mock Model's find method
$this->user->shouldReceive('find')->once()->andReturn(false);
// Create new Model instance
$mockedUser = Mockery::mock('MyApp\Models\User\User');
// Mock Models profile->create and pass Model as a result of a function
$mockedUser->shouldReceive('profile->create')->with($data['profile'])->andReturn($mockedUser);
// Pass second instance Model as a result
$this->user->shouldReceive('create')->once()->andReturn($mockedUser);
// Now all $user->profile is properly mocked and will return correct data
$result = $this->repository->replace($data);
$this->assertInstanceOf('Illuminate\Database\Eloquent\Model', $result, 'Should be an instance of Illuminate\Database\Eloquent\Model');
}

laravel 4 - subdomains - session lost after Redirect::action()

I have to redirect in CompanyController->create():
class CompanyController extends \BaseController {
...
public function index(){
echo var_dump(Session::get('err'));
}
...
public function create()
{
if($validator->passes()){
$this->setError("no errors");
}else{
$this->setError("Some errors occurred: ");
foreach($validator->messages()->all() as $msg)
$this->setError($msg);
}
return Redirect::action('CompanyController#index');
}
}
My BaseController class looks like this:
class BaseController extends Controller {
private $errors = array();
protected $view_params = array();
function __construct() {
if(Session::has('err')){
$this->errors = Session::get('err');
$this->view_params['err'] = $this->errors;
}
}
...
protected function setError($str){
if(!isset($this->view_params['err']) || $this->view_params['err']==null)
$this->view_params['err']=array();
if(!isset($this->errors) || $this->errors==null)
$this->errors=array();
array_push($this->view_params['err'],$str);
array_push($this->errors,$str);
Session::put('err',$this->errors);
}
protected function getErrors(){
return $this->errors;
}
}
The CompanyController->index() function displays always NULL. why?
EDIT
my session settings are:
'driver' => 'native',
'lifetime' => 0,
'domain' => '.domain.com',
restoring the default setting values of the config/session.php, solved the problem!
so, now, configs are:
'driver' => 'native',
'lifetime' => 0,
'domain' => null,

Codeigniter issues when loading Model

I am new to codeigniter and I am having some issues loading a model in my constructor method. Could someone help me out? Below is the code from the controller I am trying to load the model from...
<?php
class Login extends CI_Controller {
function Login(){
$this->load->model('membership_model');
}
public function index(){
$this->load->view('login_view.php');
}
public function authenticate(){
$user = $this->input->post('username');
$pass = sha1($this->input->post('password'));
if($user != null && $pass != null){
$access = $this->membership_model->request_access($user, $pass);
if($access == true){
$cookie = array(
'name' => 'username',
'value' => $user,
'expire' => '86500',
'domain' => 'unleashourmedia.com',
'path' => '/',
'prefix' => '',
'secure' => TRUE
);
$this->input->set_cookie($cookie);
echo "cookie";
} else {
redirect('login');
}
}
}
}
?>
The problem is you are not calling the constructor of the parent class.
Add this as the first line in your constructor:
parent::__construct();
function Login(){
$this->load->model("membership_model","",TRUE);
}
//make sure you call parent constructor before anything in that constructor like this
function Login(){
parent::__construct();
$this->load->model('membership_model');
}
//and you may also try to name the constructor __construct
function __construct(){
parent::__construct();
$this->load->model('membership_model');
}

Categories