In cakephp I have a search function which uses parameters and call backs. My issue is that I want to call this function with a parameter but the function cant accept parameters when called.
//I cant call this function with a paramater
$this->redirect(array('action' => 'email_list',$id,));
....
public function email_list($search = 0) {
$this->set( 'search',$search);
;
if (($this->request->is('post') || $this->request->is('put'))) {
if (isset($this->request->data['searchFilter'])) {
$filter_url['controller'] = $this->request->params['controller'];
$filter_url['action'] = $this->request->params['action'];
$filter_url['page'] = 1;
// for each filter we will add a GET parameter for the generated url
foreach($this->data['User'] as $name => $value){
if($value){
$filter_url[$name] = urlencode($value);
}
}
//Post params are now GET paramaters
return $this->redirect($filter_url);
}//isset
worked out a solution using a session variable that gets destroyed on entry. It is quick and easy. Having to redo a search function in cakephp ver 2 is not something i want to do. I am updating to cakephp ver 3
public function email_list($search = 0) {
if ($this->Session->check('sessrowid'))
{
$searchRowId=$this->Session->read('sessrowid');
$this->Session->delete('sessrowid');
}
Related
I am developing a simple profile page but I am having a little dificulty passing the result array to the controller..am not sure if this how to do it.
Model:
class Login_model extends CI_Model{
function get_profile()
{
$this->db->where('email', $this->input->post('email'));
$query = $this->db->get('user');
if($query->num_rows == 1)
{
return $query->result_array();
}
}
}
Controller:
class Login extends CI_Controller {
function show_profile{
$this->load->model('login_model');
$q['user'] = $this->login_model->get_profile();
echo $q['user'];
}
}
I tried to echo out $q['user'] as a tests to see if it will work, but it did not work.
in this context a result array would be if you were getting back more then one result. since you are only getting back one result you can do row_array() so like
if($query->num_rows == 1)
{
return $query->row_array();
}
else
{
return false;
}
NEVER do this
// example of what NOT to do
$this->db->where('email', $this->input->post('email'));// NO NO NO
validate the email first using codeigniter form validation and then send it like
// if no user comes back then deal with it right away
if( ! $user = $this->login_model->get_profile($email) )
{
$this->showNoUserFor($email) ;
}
else
{ // carry on....
otherwise - do the tutorial first in the codeigniter manual, it will save you a lot of time.
you cannot echo $q['user'] because it is an array. Use
`print_r($q['user']); exit;
and you can pass this to your view page by
`$this->load->view('yourViewPage',$q);
Using cakephp 2.3.5.
I use beforeFilter in several controllers to allow certain actions without the need to log in. I've used it successfully for quite some time. However, I've noticed that I can't get beforeFilter to fire if the controller also has the implementedEvents() method.
public function beforeFilter() {
parent::beforeFilter();
$this->Auth->allow('matchWwiProducts');
}
public function implementedEvents() {
return array(
'Controller.Product.delete' => 'deleteSku',
'Controller.Product.price' => 'notifySubscribers',
'Controller.Product.stock' => 'notifySubscribers'
);
}
For the code as displayed above I will be forced to do a login if I call the method www.example.com/products/matchWwiProducts.
When I comment out the implementedEvents() everything works as intended. I've searched around and can't find any references to implementedEvents() creating issues with beforeFilter.
The action matchWwiProducts() is as follows. It works perfectly when I log in. However, I don't want to force a log in for this action to take place.
public function matchWwiProducts() {
// this is an audit function that matches Products sourced by wwi
//
$this->autoRender = false; // no view to be rendered
// retrieve products sourced from wwi from Table::Product
$this->Product->contain();
$wwiProducts = $this->Product->getWwiSkus();
$wwiProductCount = count($wwiProducts);
// retrieve products sourced from wwi from Table:Wwiproduct
$this->loadModel('WwiProduct');
$this->Wwiproduct->contain();
$wwiSource = $this->Wwiproduct->getSkuList();
$wwiSourceCount = count($wwiSource);
// identify SKUs in $wwiProducts that are not in $wwiSource
$invalidSkus = array_diff($wwiProducts, $wwiSource);
// identify SKUs in $wwiSource that are not in $wwiProducts
$missingSkus = array_diff($wwiSource, $wwiProducts);
$missingSkuDetails = array();
foreach ($missingSkus as $missingSku) {
$skuStockStatus = $this->Wwiproduct->getStockStatus($missingSku);
$missingSkuDetails[$missingSku] = $skuStockStatus;
}
$email = new CakeEmail();
$email->config('sourcewwi');
$email->template('sourcewwiaudit', 'sourcewwi');
if (count($invalidSkus) > 0 || count($missingSkus) > 0) {
$email->subject('WWI Source Audit: Invalid or Missing SKUs');
$email->viewVars(array('invalidSkus' => $invalidSkus,
'missingSkuDetails' => $missingSkuDetails,
'wwiProductCount' => $wwiProductCount,
'wwiSourceCount' => $wwiSourceCount));
} else {
$email->subject('WWI Source Audit: No Exceptions');
$email->viewVars(array('wwiProductCount' => $wwiProductCount,
'wwiSourceCount' => $wwiSourceCount));
}
$email->send();
}
It doesn't fire because you're overloading the implementendEvents() method without making sure you keep the existing events there.
public function implementedEvents() {
return array_merge(parent::implementedEvents(), array(
'Controller.Product.delete' => 'deleteSku',
'Controller.Product.price' => 'notifySubscribers',
'Controller.Product.stock' => 'notifySubscribers'
));
}
Overloading in php.
Check most of the base classes, Controller, Table, Behavior, Component, they all fire or listen to events. So be careful when extending certain methods there. Most simple way might to do a search for "EventListenerInterface" in all classes. A class that implements this interface is likely to implement event callbacks.
Trying to start off with CakePHP's EventListener. I have set an event up, but it is not firing. I can't figure out why? This is the code I have so far...
public function view($slug = null) {
$profile = $this->Profiles->find()->where(['slug' => $slug])->first();
$this->set('profile', $profile);
$this->set('_serialize', ['profile']);
}
// I have confirmed this works.. but it is not calling the updateCountEvent method
public function implementedEvents(){
$_events = parent::implementedEvents();
$events['Controller.afterView'] = 'updateCountEvent';
return array_merge($_events, $events);
}
/**
* Triggered when a profile is viewed...
*/
public function updateCountEvent(){
Log::write('error', "Update count events"); // I dont get this line in the log. Not sure why this does not fire...
}
I revisited this question and was able to come up with a solution that works for me. Thanks Jose Lorenzo for the 'heads up'. This is my solution:
use Cake\Event\Event;
public function view($slug = null) {
$profile = $this->Profiles->find()->where(['slug' => $slug])->first();
$this->profileId = $profile->id;
$event = new Event('Controller.Profiles.afterView', $this);
$this->eventManager()->dispatch($event);
$this->set('title', $profile->name);
$this->set('profile', $profile);
$this->set('_serialize', ['profile']);
}
public function implementedEvents(){
$_events = parent::implementedEvents();
$events['Controller.Profiles.afterView'] = 'updateCountEvent';
return array_merge($_events, $events);
}
public function updateCountEvent(){
$profile = $this->Profiles->get($this->profileId);
$profile->set('views_count', $profile->views_count + 1);
$this->Profiles->save($profile);
}
I see the power of Events especially if I get to send out emails, update more tables and perhaps run a cron..., however instead of writing these 2 lines of code and create 2 more methods for this specific case, I could have made this simple call within the view action as such
$profile->set('views_count', $profile->views_count + 1);
$this->Profiles->save($profile);
The question would be.... Should I have opted for this simpler process, or stick with the events route?
How can I get the parameter in the URL and save it to a varialble so I can save it to my database?
example: www.mydomain.com/item/products/3 <-
This is for my upload image, so I can specify what product ID will I use for that image.
function add() {
if ($this->request->is('post')) {
$this->Upload->create();
if(empty($this->data['Upload']['image']['name'])) {
unset($this->request->data['Upload']['image']);
}
if(!empty($this->data['Upload']['image']['name'])) {
$filename = $this->request->data['Upload']['image']['name'];
$new_filename = STring::uuid().'-'.$filename;
$file_tmp_name = $this->request->data['Upload']['image']['tmp_name'];
$dir = WWW_ROOT.'img'.DS.'uploads';
move_uploaded_file($file_tmp_name,$dir.DS.$new_filename);
$this->request->data['Upload']['image'] = $new_filename;
if($this->Upload->save($this->request->data)) {
$this->Session->setFlash(__('Uploaded.'));
$this->redirect(array('action' => 'index'));
}
}
}
}
How will I add it here. Thank you in advance :)
Im using cakePHP
Just add the product id as a hidden input in the Form.
Then it will be included in the $this->data variable when you get the POST request.
For example in a controller method like the following
public function product($id) {
.....
}
You access it by the url (for example): www.mydomain.com/item/products/3 where Item is the controller, product is the method you are calling in that controller and 3 represent a parameter that is required to the function to work in this case $id. (assuming you don't have any routing configuration)
Is treated as a normal php variable, just do whatever you wanna do with it. Just make sure you pass the correct value
I am attempting to create a change password form in cakephp 2.0. I found a behavior that EuroMark created for 1.3 and now am having a tough time converting this code to work with 2.0. I know that it has something to do with the Auth Component as there were major changes to this component in 2.0.
public function validateCurrentPwd(Model $Model, $data) {
if (is_array($data)) {
$pwd = array_shift($data);
} else {
$pwd = $data;
}
$uid = null;
if ($Model->id) {
$uid = $Model->id;
} elseif (!empty($Model->data[$Model->alias]['id'])) {
$uid = $Model->data[$Model->alias]['id'];
} else {
return false;
}
if (class_exists('AuthExtComponent')) {
$this->Auth = new AuthExtComponent();
} elseif (class_exists($this->settings[$Model->alias]['auth'].'Component')) {
$auth = $this->settings[$Model->alias]['auth'].'Component';
$this->Auth = new $auth();
} else {
return true;
}
return $this->Auth->verifyUser($uid, $pwd);
}
I am getting an error on the line that reads $this->Auth = new $auth();
The error is as follows:
Argument 1 passed to Component::__construct() must be an instance of ComponentCollection, none given, called in C:\UniServer\www\new_company_test\app\Model\Behavior\change_password.php on line 117 and defined [CORE\Cake\Controller\Component.php, line 77]
and
Undefined variable: collection [CORE\Cake\Controller\Component.php, line 78]
it's also throwing this
Call to undefined method AuthComponent::verifyUser() in C:\UniServer\www\new_company_test\app\Model\Behavior\change_password.php on line 121
I am not sure if there is anything else that needs to be addressed in the script, I'm guessing not as there is no other place where Auth is used.
Any suggestions on what I need to do to get this to work? Any help is appreciated.
Thanks
you did discover that there is also a 2.0 branch, didnt you? :)
it should contain the same behavior:
https://github.com/dereuromark/tools/tree/2.0
either way, you need to pass a component collection into it:
$this->Auth = new AuthExtComponent(new ComponentCollection());
You should create a method verifyUser in your custom AuthExt Component which extends Auth Component for "current password" to work like so:
/**
* Quickfix
* TODO: improve - maybe use Authenticate
* #return bool $success
*/
public function verifyUser($id, $pwd) {
$options = array(
'conditions' => array('id'=>$id, 'password'=>$this->password($pwd)),
);
return $this->getModel()->find('first', $options);
$this->constructAuthenticate();
$this->request->data['User']['password'] = $pwd;
return $this->identify($this->request, $this->response);
}
/**
* returns the current User model
* #return object $User
*/
public function getModel() {
return ClassRegistry::init(CLASS_USER);
}
Maybe it is also possible to use the existing identify method in combination with a fake request object in the behavior directly?
I am thinking about using
$this->authenticate = array('Form'=>array('fields'=>array('username' => 'id')));
feel free to fork the behavior and submit a pull request.
"current password" is the only thing that is not yet cleanly solved right now.