Saving data array in AppModel with CakePHP - cakephp

I have this function in CakePHP's AppModel (This is used to install initial data in CakePHP) However, I can't seem to get it to save my data, and I get no errors.
Here is my function inside App/Model/AppModel.php:
public function importData() {
$initialOptionData = array(
array( 'Option' => array( 'name' => 'version', 'value' => '1.0.0', )),
array( 'Option' => array( 'name' => 'site-name', 'value' => 'Site Title', )),
);
$this->create();
$this->saveMany($initialOptionData);
}

From you posted code it seems you're trying to save you data to options table, and to do that you need to use Option model.
But you're code is within AppModel, so first import Option model and then execute your save statements.
Your code should look like:
public function importData() {
$initialOptionData = array(
array( 'Option' => array( 'name' => 'version', 'value' => '1.0.0', )),
array( 'Option' => array( 'name' => 'site-name', 'value' => 'Site Title', )),
);
App::import('model','Option'); // Import the Option Model
$Option = new Option(); // create instance of Option class
// save statements
$Option->create();
$Option->saveMany($initialOptionData);
}
Note
Code you're trying will work if you write that within app/model/Option.php file.

I suppose it would be enough to store the values as model property. No need to call $this->save...
public $initialOptionData = array(
array( 'Option' => array( 'name' => 'version', 'value' => '1.0.0', )),
array( 'Option' => array( 'name' => 'site-name', 'value' => 'Site Title', )),
);
all models will inherit initialOptionData...

Related

CakePHP 2.7 GoogleChart Plugin

First of all, sorry if I'm asking for help regarding this question but I have been working on this for almost a day now. I searched this site and was able to find a post similar to my question but I cannot get it to work.
Anyway, I am using CakePHP 2.x, and I need to show reports via charts. I saw this plugin for CakePHP CakePHP GoogleCharts Plugin by Scott Harwell. I did everything step-by-step and somehow my views keep on appearing empty. I made sure it wasn't because of conflicting files so I decided to make a new CakePHP project, unfortunately, it didn't work.
Here are my codes:
Controller:
<?php
App::uses('AppController', 'Controller');
App::uses('GoogleCharts', 'GoogleCharts.Lib');
class ChartsController extends AppController {
public $uses = array('Student');
public $helpers = array('GoogleCharts.GoogleCharts');
public function test_chart(){
$student= $this->Student->getStudentAges();
$studentAgesChart= new GoogleCharts();
$studentAgesChart->type('LineChart');
$studentAgesChart->options(array('title' => "Student Ages"));
$studentAgesChart->columns(array(
//Each column key should correspond to a field in your data array
'name' => array(
'type' => 'string',
'label' => 'Student Name'
),
'age' => array(
'type' => 'number',
'label' => 'Student Age'
)
));
foreach($student as $row){
$studentAgesChart->addRow(array('age' => $row['Student']['age'], 'name' => $row['Student']['name']));
}
$this->set(compact('studentAgesChart'));
debug($studentAgesChart);
}
}
?>
View:
<div id="chart_div" >
<?php
$this->GoogleCharts->createJsChart($studentAgesChart);
?>
</div>
Debug($studentAgesChart):
object(GoogleCharts) {
[private] type => 'LineChart'
[private] columns => array(
'name' => array(
'type' => 'string',
'label' => 'Student Name'
),
'age' => array(
'type' => 'number',
'label' => 'Student Age'
)
)
[private] rows => array(
(int) 0 => array(
(int) 0 => 'Student 1',
(int) 1 => '17'
),
(int) 1 => array(
(int) 0 => 'Student 2',
(int) 1 => '16'
)
)
[private] options => array(
'width' => (int) 400,
'height' => (int) 300,
'title' => 'Student Ages',
'titleTextStyle' => array(
'color' => 'red'
)
)
[private] callbacks => array()
[private] div => 'chart_div'
}
Model:
public function getStudentAges(){
$student_ages = $this->find('all',
array(
'order' => array('Student.name' => 'ASC'),
'limit' => 3,
'fields' => array(
'Student.name',
'Student.age'
)
)
);
return $student_ages;
}
The way I see it, it doesn't contain any errors but my view is empty.
#Scrappy, do you see any output (JavaScript or HTML) included in the DOM when you view source on your page? Or, is the plugin not generating any content at all? If you do see JavaScript code added, is your page reporting JS errors in the console that might prevent the chart from loading properly? If you do not see the JS code, then you likely have not loaded the plugin in your bootstrap file.
Is the page available on the public Internet for review?
The plugin has not seen updates from me in a few years, but there are a few developers that have forked it and updated it for CakePHP 3.0 too. But, this version should still be working unless something changed on the Google end, which I am sure I would have heard about if that was the case.

Adding associated data in model::beforeSave

I'm trying to add associated data to during cakePHPs beforeSave() but it looks like cakePHP is ignoring it.
<?php
App::uses("AppModel", "Model");
class Recipe extends AppModel {
public $hasMany = array('Ingredient');
public function beforeSave($options=array()) {
if(!isset($this->data["Ingredient"])) {
Debugger::log("data[Ingredient] didn't exist! adding some ingredients...");
$this->data["Ingredient"] = array(
array(
'Ingredient' => array(
'name' => 'Gluten Free Flour',
'amount' => '12 cups'
)
),
array(
'Ingredient' => array(
'name' => 'Sugar',
'amount' => '50 cups'
)
),
array(
'Ingredient' => array(
'name' => 'A shoe',
'amount' => 'Just one'
)
),
);
}
Debugger::log("Saving Data: ");
Debugger::log($this->data, 7, 10);
return true;
}
}
In my RecipesController I have this:
public function test_save() {
//Test saving With the ingredients in the recipe
Debugger::log("Saving w/ ingredients");
Debugger::log($this->Recipe->saveAssociated(array(
'Recipe' => array(
'name' => 'Test Recipe 1'
),
'Ingredient' => array(
array(
'name' => 'Test Ingredient 1 for Test Recipe 1',
'amount' => 'a few'
),
array(
'name' => 'Test Ingredient 2 for Test Recipe 1',
'amount' => 'a lot'
)
)
)));
Debugger::log("Saving w/o ingredients");
Debugger::log($this->Recipe->saveAssociated(array(
'Recipe' => array(
'name' => 'Test Recipe 2'
)
)));
}
The save with ingredients works, but the save without ingredients doesn't, the data in Recipe->data before beforeSave returns is this:
array(
'Recipe' => array(
'name' => 'Test Recipe 1'
),
'Ingredient' => array(
(int) 0 => array(
'Ingredient' => array(
'name' => 'Test Ingredient 1 for Test Recipe 1',
'amount' => 'a few'
)
),
(int) 1 => array(
'Ingredient' => array(
'name' => 'Test Ingredient 2 for Test Recipe 1',
'amount' => 'a lot'
)
)
)
)
And when Ingredient is added in the before save:
array(
'Recipe' => array(
'name' => 'Test Recipe 1'
),
'Ingredient' => array(
(int) 0 => array(
'Ingredient' => array(
'name' => 'Gluten Free Flour',
'amount' => '12 cups'
)
),
(int) 1 => array(
'Ingredient' => array(
'name' => 'Sugar',
'amount' => '50 cups'
)
),
(int) 2 => array(
'Ingredient' => array(
'name' => 'A shoe',
'amount' => 'Just one'
)
)
)
)
When the data is in the array before I call a save method, it'll work just fine, only when I try and add the associated data in the beforeSave.
From the documentation:
Be sure that beforeSave() returns true, or your save is going to fail.
http://book.cakephp.org/2.0/en/models/callback-methods.html#beforesave
Edited: I tested your code and you are right, related data added in beforeSave() is being ignored. This is happening because you cannot add or modify related data in a model's beforeSave(). It means that, in your Recipe's beforeSave(), you cannot neither add Ingredients nor modify the Ingredients you previously attached to Recipe in your controller.
In your Recipe's beforeSave() you can only modify Recipe data.
Is this a bug? It is not, according to Mark Story (creator of CakePHP):
Its a feature, as currently saveAll only lets you use beforeSave to
modify the record that's about to be saved, not the full data set. I
personally don't feel that should change, but its something that could
be discussed.
This statement is about saveAll() but the important part is what he said about beforeSave(). Check the full thread: https://github.com/cakephp/cakephp/issues/1765

cakedc search plugin use pb

I use the plugin cakedc search, but there is one thing I can not seem to find, I have a form with two fields, and I would add for example "online = 1" to my search
in my controller, I trying:
public function find() {
$this->Prg->commonProcess();
$array = array('type'=>'post', 'online'=>'1', 'created'=> '<= NOW()');
$this->passedArgs = Set::merge($this->passedArgs, $array);
$this->paginate = array(
'conditions' => array($this->Post->parseCriteria($this->passedArgs)),
);
$this->set('posts', $this->paginate());
model:
public $displayField = array('name', 'category_id');
public $filterArgs = array(
array('name' => 'name', 'type' => 'query', 'method' => 'filterName'),
array('name' => 'category_id', 'type' => 'value')
);
.....
debug($this->passedArgs):
array(
'name' => 'mon',
'category_id' => '2',
'type' => 'post',
'online' => '1',
'created' => '<= NOW()'
)
but $array argument are not taken in my search
Can anyone help?
I am a beginner with cakephp,
Thanks a lot !
Instead of
'conditions' => array($this->Post->parseCriteria($this->passedArgs)),
try
'conditions' => $this->Post->parseCriteria($this->passedArgs),
I also recommend you to use DebugKit and to add the generated query to your question in the case it is still not working.

Lack of 'required' fields in form suggests I am not correctly associating models

I'm having trouble validating an input form and saving the data from that form. I suspect that perhaps these are both caused by an association problem, though I am not sure.
I'm using CakePHP 2.2.0 RC2.
I have three models: User, Member and Address. Each user can have several members in their account and each user can have many addresses (it remembers past addresses, too).
My model associations are:
User model:
class User extends AppModel {
public $name = 'User';
public $hasMany = array(
'Member' => array(
'className' => 'Member',
'foreignKey' => 'user_id',
'order' => 'Member.member ASC',
'dependent' => true
),
'Address' => array(
'className' => 'Address',
'foreignKey' => 'user_id',
'order' => 'Address.address ASC',
'dependent' => true
)
);
...
Member model:
class Member extends AppModel {
public $name = 'Member';
public $displayField = 'member';
public $belongsTo = array(
'User' => array(
'className' => 'User',
'foreignKey' => 'user_id'
)
);
...
Address model:
class Address extends AppModel {
public $name = 'Address';
public $displayField = 'address';
public $belongsTo = array(
'User' => array(
'className' => 'User',
'foreignKey' => 'user_id'
)
);
...
For my Form create statement, I have:
$this->Form->create( 'Member', array( 'url' => array( 'action' => 'add' ) ) );
I am using the Member model and controller to handle the form as it submits either only Member fields, or Member and Address fields, depending on whether the user already has an address entry or not (if the user doesn't, it adds address input fields to the form, otherwise it doesn't).
I am not submitting any User fields in the form.
Now, I would expect, if my associations were set up correctly, that any 'required' fields in any of the models would have an asterisk next to them. There are some fields set as required in both the Member and Address models, and while the Member fields show up on the form as being required (with an asterisk), the Address fields do not.
An example of required Address field code from the Address model:
public $validate = array(
'street1' => array(
'required' => array(
'rule' => array( 'notEmpty' ),
'required' => true, 'allowEmpty' => false,
'message' => 'Please enter a street address'
),
....
And here's some of my view/form code:
echo $this->Form->input( 'Member.firstname', array( 'label' => 'First name', 'type' => 'text' ) );
echo $this->Form->input( 'Member.middlename', array( 'label' => 'Middle name', 'type' => 'text' ) );
echo $this->Form->input( 'Member.lastname', array( 'label' => 'Last name', 'type' => 'text' ) );
echo '<p class="bold">Please enter current address details:</p>';
echo $this->Form->input( 'Address.street1', array( 'label' => 'Street address (line 1)', 'type' => 'text' ) );
echo $this->Form->input( 'Address.street2', array( 'label' => 'Street address (line 2)', 'type' => 'text' ) );
echo $this->Form->input( 'Address.suburb', array( 'label' => 'Suburb', 'type' => 'text' ) );
...
When I output $validationErrors on the form page (before form submission), I get this:
Array
(
[Member] => Array
(
)
[User] => Array
(
)
)
I'm assuming there should also be an [Address] section there.
I can't spot anything obvious but I'm new to CakePHP (though I do have PHP experience), so any ideas would be appreciated.
Thanks!
Peter.
Firstly you said you were using a release candidate (RC2) of Cake 2.2. There is now a stable release and I strongly encourage you to upgrade to that.
You create the form with the Member model but it doesn't have a direct relation(association) to Address. Address is associated to User. If you create the form via the User model it should work all right.
If this scenario - creating the form with the User model - doesn't work for you and your application
logic than your Database model and your Model associations are wrong and they do not comply with your business needs. If this is the case you should consider changing the Architecture of the application.
And a note on $uses: you shouldn't have to include the Address model in your controller's $uses in order to be able to validate inputs. Controller::$uses is for use of models (other than the controller's own model) directly in the Controller itself. For example:
public $uses = array('Article', 'News');
in any controller would make all Article and News Models' methods available in that controller with:
$this->Article->methodName();
or
$this->News->methodName();

CakePhp: On the fly associations using a re-named Model field?

I'm trying to use on the fly associations to trim down the data I retrieve, but the model I'm using is associated to other models with a re-named field because I have 2 of the same models associated with it.
So, here's the model, say 'test', that has two 'user' fields, both related to the User model.
In the model:
var $belongsTo = array(
'User' => array(
'className' => 'User',
'foreignKey' => 'user_id'
),
'User_Watched' => array(
'className' => 'User',
'foreignKey' => 'user_id_watched'
)
);
When I retrieve data related to 'test', I want to only retrieve particular data linked to the 'User' and 'User_Watched' fields without any other nested information.
But when I do:
$this->User->unbindModel(array('hasMany' => array('something1', 'something2')), false);
then something1 and something2 data does not show up for the 'User' field of model 'test', but is still retrieved for the 'User_watched' field.
Can I not retrieve unwanted data for the 'User_watched' field?
Hope this makes sense... :)
KcYxA,
Containable behavior might help a lot in this case, as benjamin mentioned, your "find" queries would look like:
$this->User->find('first', array(
'conditions' => array('User.id' => $id),
'contain' => array('UserWatched')
));
In this case, you won't have to use unbindModel method. In this example, you'll get User and UserWatched data.
If you need only User data from "find", then tell Cake to "$this->User->contain();" so it won't go further then User model.
to use on the fly associations to trim
down the data I retrieve
Good idea.
'foreignKey' => 'user_id_watched'
should possibly be:
'foreignKey' => 'user_watched_id'.
Edit 1: At least this would make sense according to my current understanding. If user_id is a correct foreign key(FK), which cakephp uses to unbind the relations, but user_id_watched isn't, than your described behavior is explained.
Edit 2: The Containable behavior gives you another tool for controlling associated models.
Change $primaryKey in fly, run controller
Sample:
// Models
//....
class PreProductoDescripcion extends AppModel {
/**
* Primary key field
*
* #var string
*/
public $primaryKey = 'id_producto_descripcion';
//....
//....
}
class SenasaPedidosDetalles extends AppModel {
/**
* Display field
*
* #var string
*/
public $displayField = 'cod_tango';
public $belongsTo = array(
'SenasaPedidos' => array(
'className' => 'SenasaPedidos',
'foreignKey' => 'senasa_pedidos_id',
'conditions' => '',
'fields' => '',
'order' => ''
),
'PreProductoDescripcion' => array(
'className' => 'PreProductoDescripcion',
'foreignKey' => 'cod_tango',
//'conditions' => array('SenasaPedidosDetalles.cod_tango' => 'PreProductoDescripcion.codigo'),
'fields' => '',
'order' => ''
)
);
//....
#
// Controller Fly
//...
$this->SenasaPedidos->Behaviors->load('Containable');
$this->SenasaPedidos->SenasaPedidosDetalles->PreProductoDescripcion->primaryKey = 'codigo';
$datos = $this->SenasaPedidos->find(
'first', array(
'fields' => array( 'SenasaPedidos.*' ),
'conditions' => array( 'SenasaPedidos.id' => $id ),
'contain' => array(
'Usuarios' => array(
'fields' => array( 'Usuarios.apellido_nombre' )
),
'Clientes' => array(
'fields' => array( 'Clientes.razon_social' )
),
'Provincias' => array(
'fields' => array( 'Provincias.nombre' )
),
'Transportes' => array(
'fields' => array( 'Transportes.razon_social' )
),
'SenasaPedidosDetalles' => array(
'fields' => array( 'SenasaPedidosDetalles.*' ),
'PreProductoDescripcion' => array(
'fields' => array(
'PreProductoDescripcion.id_producto_descripcion',
'PreProductoDescripcion.descripcion'
)
)
),
)
));
//...

Resources