Pass variable from controller to model (beforeSave) (Upload Field) CakePHP - cakephp

I really need to know this issue to finish my work.
Here I'll give a example envolving model and controller.
I want to pass $final_name from controller to beforeSave() of my model
public function admin_add() {
if($this->request->is('post')) {
if($this->data['Client']['file']['tmp_name'] != '') {
// Upload block
$tmp_file = $this->data['Client']['file']['tmp_name'];
$file = new File($tmp_file);
if($file->mime() == "image/jpeg" or "image/png") {
$ext = explode('.', $this->data['Client']['file']['name']);
$name = md5($this->data['Client']['file']['name']);
$file->copy(IMG_DIR . 'portfolio\\' . $name . '.' . end($ext));
$final_name = $name . "." . end($ext); // File name with extension
}
// If save
if($this->Client->save($this->request->data)) {
$this->Session->setFlash('Client cadastrado com sucesso!', 'admin_flash');
}
}
}
}
In my client model
public function beforeSave($options = array()) {
if($this->data['Client']['file']['name'] != null) {
$this->data['Client']['file'] = $final_name;
}
return parent::beforeSave($options);
}

In Controller
$this->request->data['Client']['final_name'] = $name . "." . end($ext);
In Model
public function beforeSave($options = array()) {
if($this->data['Client']['file']['name'] != null) {
$this->data['Client']['file'] = $this->data['Client']['final_name'];
}
return parent::beforeSave($options);
}
Update for CakePHP3
Pass variable from controller to table beforeSave, afterSave ?
// Examples
// In Controller
$this->Article->save($data, ['passVariable' => 'passedData']);
// in Table
public function beforeSave(Event $event, EntityInterface $entity, ArrayObject $options)
{
if (isset($options['passVariable'])) {
// implement your code
}
}
Read more: https://api.cakephp.org/3.8/class-Cake.ORM.Table.html#_save
But good place to modify data before save like asked in question are:
https://book.cakephp.org/3.0/en/orm/saving-data.html#before-marshal or
https://book.cakephp.org/3.0/en/orm/entities.html#accessors-mutators

Related

I want to display data in the controller using the codeigniter model

I want to display data on the controller
public function __construct() {
parent:: __construct();
if(!isset($_SESSION)){
session_start();
}
if (!$_SESSION['logged_in']) {
redirect('auth/login');
}
$managemenu = new Managemenu();
$get_data = $managemenu->index($_SESSION['admin_level'],$GLOBALS['PAGE_DISTRIK']);
if(empty($get_data['validPage'])){
redirect('auth/login');
}
$this->getdata = $get_data;
$this->load->model('Model_distrik');
}
public function index()
{
$data['page'] = 'v_distrik';
$data['title'] = 'List Distrik';
$data['menu'] = $this->getdata['menu'];
$data['distrik'] = $this->Model_distrik->getDataDistrik();
echo "<pre>";
print_r ($data['distrik']);
echo "</pre>";
die();
$this->load->view('main',$data);
}
I've tried a number of times but the results are like
this error message: undefined property: district :: $ model_district
class Model_distrik extends CI_Model {
public function getDataDistrik(){
$this->db->select('*');
$this->db->from('distrik');
$this->db->where("Deleted", 0);
$query = $this->db->get()->result_array();
return $query;
}
}

Codeigniter autocheck db depending on session value

I'm trying to force my app to check every time it loads a model or controller depending on which is my session value.
This is actually running, but just when I get throw this model.
class News_model extends CI_Model {
public function __construct()
{
parent::__construct();
if($this->session->dbname=='db1'){
$this->db=$this->load->database('db1', TRUE);
}
else{
$this->db=$this->load->database('db2', TRUE);
}
}
public function get_news($slug = FALSE)
{
if ($slug === FALSE)
{
$query = $this->db->get('news');
return $query->result_array();
}
$query = $this->db->get_where('news', array('slug' => $slug));
return $query->row_array();
}
}
But I do not war to include that __construct code to all my models or controllers.
I've tried to add on my autoload.php
$autoload['model'] = array('General');
Where my General code is something like this.
class General extends CI_Model {
function __construct()
{
parent::__construct();
if($this->session->dbname=='db1'){
$this->db=$this->load->database('db1', TRUE);
}
else{
$this->db=$this->load->database('db2', TRUE);
}
}
}
How can I do it?
You can do it by creating a base model which will be extended by your models that require the database check.
I have simplified the checking and loading code. A simple ternary determines the string to use and stores it in the variable $dbname. That variable is used to load the database, i.e. $this->load->database($dbname);.
I don't believe you need the second argument to load::database() which means you don't need to set $this->db explicitly. If I'm wrong, use
$this->db = $this->load->database($dbname, TRUE);
Below is the "base" model. The prefix of the file name is determined in config.php with the setting $config['subclass_prefix'] = 'MY_'; Adjust your base model's file and class name to match the 'subclass_prefix' you use.
/application/core/MY_Model.php
<?php
class MY_Model extends CI_Model
{
public function __construct()
{
parent::__construct();
$dbname = $this->session->dbname == 'db1' ? 'db1' : 'db2';
$this->load->database($dbname);
}
}
Use the above to create other models like so...
class News_model extends MY_Model
{
public function get_news($slug = FALSE)
{
if ($slug === FALSE)
{
$query = $this->db->get('news');
return $query->result_array();
}
$query = $this->db->get_where('news', array('slug' => $slug));
return $query->row_array();
}
}

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.

Using session component in custom component

I'm trying to use Session component in custom component (CakePHP 2.3) but when I call Session component functions I get: Fatal error: Call to a member function read() on a non-object in ...\app\Controller\Component\CartComponent.php on line 7
My CartComponent looks like that:
<?php
App::uses('Component', 'Controller');
class CartComponent extends Component {
public $components = array('Session');
function hasItems() {
$cart = $this->Session->read('Cart');
return $cart != null && count($cart) > 0;
}
}
?>
And I use it in controller:
<?php
class OrdersController extends AppController {
public $name = 'Orders';
public $components = array('Cart', 'Email');
function beforeFilter() {
parent::beforeFilter();
if ($this->Cart->hasItems()) {
$this->Auth->allow('add_item', 'remove_item', 'cart');
} else {
$this->Auth->allow('add_item', 'remove_item', 'cart', 'make');
}
}
}
?>
For using session inside the custom component I tried with
public $components = array('Session');
and then called it by using
$this->Session->read('Cart');
but I cant able to use it and I start to use
CakeSession::read('Cart')
Now it works Hope it will used for you note I used in cake php version > 2
If you want to use Session in your Component Use-
$test = CakeSession::read('user');
print_r($test);
You should use as bellow
class YourComponent extends Component {
public function initialize(Controller $controller){
$this->controller = $controller;
if (!isset($this->controller->presetVars)) {
$this->controller->presetVars = true;
}
$model = $this->controller->modelClass;
if (!empty($settings['model'])) {
$model = $settings['model'];
}
if ($this->controller->presetVars === true) {
// auto-set the presetVars based on search definitions in model
$this->controller->presetVars = array();
$filterArgs = array();
if (!empty($this->controller->$model->filterArgs)) {
$filterArgs = $this->controller->$model->filterArgs;
}
foreach ($filterArgs as $key => $arg) {
if ($args = $this->_parseFromModel($arg, $key)) {
$this->controller->presetVars[] = $args;
}
}
}
foreach ($this->controller->presetVars as $key => $field) {
if ($field === true) {
if (isset($this->controller->$model->filterArgs[$key])) {
$field = $this->_parseFromModel($this->controller->$model->filterArgs[$key], $key);
} else {
$field = array('type' => 'value');
}
}
if (!isset($field['field'])) {
$field['field'] = $key;
}
$this->controller->presetVars[$key] = $field;
}
/* now you can use Component existing in your Component :) */
public function sayHello(){
$this->controller->Session->setFlash(__('Hello you'));
}
}

Opposite of requireSecure in CakePHP

CakePHP has a requireSecure function in the SecurityComponent. I'm using this to force SSL when passing sensitive information such as a credit card number.
Questions:
Is there a requireNonSecure function?
If there's no requireNonSecure function is it possible to extend/add a function to CakePHP's core file without modifying the original file?
I want a requireNonSecure function because some of my pages have embedded videos that can only be played on our domain name. When using SSL the video hosting service does not recognize our domain name and cannot play the videos.
This is some of the code in the beforeFilter of a controller:
function beforeFilter() {
parent::beforeFilter();
$this->Security->validatePost = false; // disable CSRF protection
$this->Security->blackHoleCallback = 'forceSSL';
$this->Security->requireSecure('pay', 'index');
$this->Auth->allow('index');
}
This is the callback in app_controller.php
function forceSSL() {
$redirect = '';
if (!empty($this->params['url']['redirect'])) {
$redirect = '?redirect=' . $this->params['url']['redirect'];
}
$this->redirect('https://' . rtrim(env('SERVER_NAME'), '/') . $this->here . $redirect);
}
A solution would be to append a function to beforeFilter like this:
In a controller:
function beforeFilter() {
parent::beforeFilter();
// Require non secure (http) for video action
$this->requireNonSecure('video');
// ... other code here
}
In app_controller.php:
function requireNonSecure() {
$requireNonSecure = array_map('strtolower', func_get_args());
if (in_array(strtolower($this->action), $requireNonSecure) || $requireNonSecure == array('*')) {
if ($this->RequestHandler->isSSL()) {
$this->redirect('http://' . rtrim(env('SERVER_NAME'), '/') . $this->here);
return;
}
}
}
This solution adds to SecurityComponent. It should work but there is a risk of redirect loops if both requireSecure and requireNonSecure are set.
SecurityPlusComponent:
class SecurityPlusComponent extends SecurityComponent {
/**
* List of actions that do not require an SSL-secured connection
*
* #var array
* #access public
* #see SecurityPlusComponent::requireNonSecure()
*/
var $requireSecure = array();
/**
* Component startup. All security checking happens here.
*
* #param object $controller Instantiating controller
* #access public
*/
function startup(&$controller) {
$this->_action = strtolower($controller->action);
$this->_methodsRequired($controller);
$this->_secureRequired($controller);
$this->_nonSecureRequired($controller);
$this->_authRequired($controller);
$this->_loginRequired($controller);
$isPost = ($this->RequestHandler->isPost() || $this->RequestHandler->isPut());
$isRequestAction = (
!isset($controller->params['requested']) ||
$controller->params['requested'] != 1
);
if ($isPost && $isRequestAction && $this->validatePost) {
if ($this->_validatePost($controller) === false) {
if (!$this->blackHole($controller, 'auth')) {
return null;
}
}
}
$this->_generateToken($controller);
}
function requireNonSecure() {
$this->_requireMethod('NonSecure', func_get_args());
}
/**
* Check if access requires non secure connection (http)
*
* #param object $controller Instantiating controller
* #return bool true if secure connection required
* #access protected
*/
function _nonSecureRequired(&$controller) {
if (is_array($this->requireNonSecure) && !empty($this->requireNonSecure)) {
$requireNonSecure = array_map('strtolower', $this->requireNonSecure);
if (in_array($this->_action, $requireNonSecure) || $this->requireNonSecure == array('*')) {
if ($this->RequestHandler->isSSL()) {
if (!$this->blackHole($controller, 'nonSecure')) {
return null;
}
}
}
}
return true;
}
}
Modified app_controller forceSSL function:
function securityBlackhole($type) {
$redirect = '';
if (!empty($this->params['url']['redirect'])) {
$redirect = '?redirect=' . $this->params['url']['redirect'];
}
// Force http (non-SSL)
if($type == 'nonSecure') {
$this->redirect('http://' . rtrim(env('SERVER_NAME'), '/') . $this->here . $redirect);
// Force https (SSL)
} else {
$this->redirect('https://' . rtrim(env('SERVER_NAME'), '/') . $this->here . $redirect);
}
}
Would be called like this in a controller:
function beforeFilter() {
parent::beforeFilter();
$this->SecurityPlus->validatePost = false; // disable CSRF protection
$this->SecurityPlus->blackHoleCallback = 'securityBlackhole';
$this->SecurityPlus->requireSecure('pay', 'index');
$this->SecurityPlus->requireNonSecure('video');
$this->Auth->allow('index');
}

Resources