Save associations not working in cakephp 4 - cakephp

I have these nested associations :
CustomRubriques hasOne ExtendedRubriques hasMany Photos
Photos has fields id and legend
I'm trying to save legend from CustomRubriques like this :
// CustomRubriques/edit.php
echo $this->Form->control('extended_rubrique.photos.0.id');
echo $this->Form->control('extended_rubrique.photos.0.legend');
echo $this->Form->control('extended_rubrique.photos.1.id');
echo $this->Form->control('extended_rubrique.photos.1.legend');
// etc..
// CustomRubriquesController.php
public function edit($id)
{
$rubrique = $this->CustomRubriques->findById($id)->firstOrFail();
if ($this->request->is(['post', 'put'])) {
$rubrique = $this->CustomRubriques->patchEntity($rubrique, $this->request->getData());
debug($rubrique); // $rubrique->extended_rubrique->photos[0]['id'] and $rubrique->extended_rubrique->photos[0]['legend'] are well defined
if ($this->CustomRubriques->save($rubrique, ['associated' => ['ExtendedRubriques', 'ExtendedRubriques.Photos']])) {
return $this->redirect(['action' => 'view', $rubrique->id]);
}
}
$this->set(compact('rubrique'));
}
The legend of the photos are not saved (without any error returned) and I really don't know why !
(Note that legend is true in Photo Entity's $_accessible )
Could anybody tell me what I'm doing wrong ?

Related

Basic CakePHP: Unable to get the id (Edit Method)

This my database:
http://gyazo.com/c6a86127d6f91aae947cf45ee535cecd
Example:
http://gyazo.com/c23fec3fabb7e4504c42453980fbc372
When I press the edit button , they able to retrieve the data however the page show me empty field instead of the field that have old data.
Secondly, unable to undate because they keep send empty id_field back to controller.
p.s. add,edit,delete method work totally fine.
Below are my code:
Model
<?php
App::uses('AppModel', 'Model');
class EventDate extends AppModel {
public $useTable = 'eventdate';
public $primaryKey = 'eventDate_id';
public $validate = array(
'event_date' => array(
'rule' => array('date','ymd'),
'message' => 'Enter a valid date in YY-MM-DD format.',
'required' => true,
'allowEmpty' => false
)
);
}
Controller
public function edit($id = null) {
//Retrieve from database
$post = $this->EventDate->findByEventdateId($id);
$this->set('edate', $post) ;
// debug($post);
//Without Id
if (!$id) {
throw new NotFoundException(__('Invalid Event Date'));
}
//If Not Exist the id
if (!$post) {
throw new NotFoundException(__('Invalid Event Date'));
}
//After press the submit
if ($this->request->is(array('post','put'))) {
$this->EventDate->eventDate_id = $id;
debug($_POST);
if ($this->EventDate->save($this->request->data)) {
$this->Session->setFlash(__('The Event has been saved.'));
return $this->redirect(array('action' => 'index'));}
else
{$this->Session->setFlash(__('The Event could not be saved. Please, try again.'));}
}
//Set the data same as retrieved
if (!$this->request->data) { $this->request->data = $post;}
}
edit.ctp
<h2>Edit Event</h2>
<?php
echo $this->Form->create('eventdate');
//echo $this->Form->input('eventDate_id', array('type' => 'hidden'));
echo $this->Form->hidden('eventDate_id');
echo $this->Form->input('event_date',array(
'label' => 'Event Date',
'type' => 'text',
'id' => 'datepicker'));
echo $this->Form->end('Save Post');
?>
Below link is the debug($_Post) been shown:
http://gyazo.com/5e569e6cc6b3026fc8896c315197a938
Should be:
echo $this->Form->create('EventDate'); // notice the capital CamelCase
Side note: The info that displays in the fields will be out-of-date, since you 1) get the data from the DB and set to var, THEN do the save based on posted data.
Another side note: There are quite a few things that you're doing that are non-standard and not consistent w/ the recommended conventions. Cleaning that up will make it easier to work with AND easier to receive help.

My codeigniter site stopped outputting data from my database

Good day internet. I am working on a basic cms using codeigniter. I have it set up so it is showing data from my database.
Here is the code in my controller for the first 2 pages
class Site extends CI_Controller {
public function index(){
$this->home();
}
public function home(){
$this->load->model("model_get");
$data["results"] = $this->model_get->getData("home");
$this->load->view("site_header");
$this->load->view("site_nav");
$this->load->view("content_home", $data);
$this->load->view("site_footer");
}
public function about(){
$this->load->model("model_get");
$data["results"] = $this->model_get->getData("about");
$this->load->view("site_header");
$this->load->view("site_nav");
$this->load->view("content_about", $data);
$this->load->view("site_footer");
}
Here is the model to get the data from the database
class Model_get extends CI_Model{
function getData($page){
$query = $this->db->get_where("pageData", array("page" => $page));
return $query->result();
}
}
Here is the view to output the data in the database
<div id="content">
<?php
foreach($results as $row){
$title = $row->title;
$text1 = $row->text1;
$text2 = $row->text2;
}
echo heading($title, 1);
?>
<p><?php echo $text1; ?></p>
<p><?php echo $text2; ?></p>
It has been working just fine but I wanted to use a form to change the data in the database. Here is the code for the view of my form
<div id="content">
<?php
$this->load->helper("form");
echo validation_errors();
echo form_open("site/updatevalues");
echo form_label("Heading", "title");
$data = array(
"name" => "title",
"id" => "title",
"value" => set_value("title"),
"style" => "width:100%",
"rows" => "rows:3"
);
echo form_textarea($data);
echo form_label("Text 1", "text1");
$data = array(
"name" => "text1",
"id" => "text1",
"value" => set_value("text1"),
"style" => "width:100%",
"rows" => "rows:3"
);
echo form_textarea($data);
echo form_label("Text 2: ", "text2");
$data = array(
"name" => "text2",
"id" => "text2",
"value" => set_value("text2"),
"style" => "width:100%",
"rows" => "rows:3"
);
echo form_textarea($data);
echo form_submit("dataSubmit", "Submit");
echo form_close();
?>
Here is the code snippet in my controller that is using the form inputs from the above view
public function updatevalues(){
$this->load->library("form_validation");
$this->form_validation->set_rules("title", "Heading", "required|xss_clean");
$this->form_validation->set_rules("text1", "Text 1", "required|xss_clean");
$this->form_validation->set_rules("text2", "Text 2", "required|xss_clean");
if($this->form_validation->run() == FALSE){
$data ["success"] = "";
$this->load->view("site_header");
$this->load->view("site_nav");
$this->load->view("data_input", $data);
$this->load->view("site_footer");
} else {
echo $data["success"] = "The page has been updated";
$this->load->view("site_header");
$this->load->view("site_nav");
$this->load->view("data_input", $data);
$this->load->view("site_footer");
$this->load->model("model_update");
$newRow = array(
"id" => "3",
"title" => set_value("title"),
"page" => "Contact Page", **<---This was the problem**
"text1" => set_value("text1"),
"text2" => set_value("text2")
);
$this->model_update->update1($newRow);
}
}
Here is the model that is handling updating the data in the database, I am just using the first function here
class Model_update extends CI_Model{
function update1($data){
$this->db->update("pagedata", $data, "id = 3");
}
function update2($data){
$this->db->update_batch("pagedata", $data, "id");
}
}
So after days of trying to figure this out I finally got it to update certain fields in the database which would theoretically update the output in the view but now it is giving me this error message:
A PHP Error was encountered
Severity: Notice
Message: Undefined variable: title
Filename: views/content_about.php
Line Number: 10
It is giving the error for all the variables I am trying to echo. I don't get it, I haven't touched the code to display from the database and now that I am finally able to change the data through a form the variable is all of a sudden undefined. If anyone can help me with this I would appreciate it. Been working on this single task for 2 weeks now!
Edit: As I was writing this up I figured out the problem and have put an arrow to identify it. The page data must be "about" because that is how the foreach loop is grabbing the data. I could just not post this but maybe this code will help someone else. Take what you can and enjoy internet you have just witnessed someone correcting themselves, lol.
Change this line in your site controller function home:
From this:
$data["results"] = $this->model_get->getData("home");
Into this:
$data["results"] = $this->model_get->getData("home page");
I know this because you took this from the youtube tutorial of Steven.

Cakephp: combine input values to create hidden name input

I've searched high and low for a solution but can't seem to get this figured out. What I'm trying to do is upon adding a product, I want the name field to be populated from the inputs in the form. So the name would include the values the user selects for type_id,category_id and subcategory_id. Does anyone know of a way to accomplish this?
Add product View page
<fieldset>
<legend><?php echo __('Add Product'); ?></legend>
<?php
echo $this->Form->input('type_id');
echo $this->Form->input('category_id', array('label' => 'Vendor'));
echo $this->Form->input('subcategory_id', array('label' => 'Model'));
echo $this->Form->input('location', array('label' => 'Location'));
echo $this->Form->input('sku', array('label' => 'Asset Tag'));
echo $this->Form->input('mac');
echo $this->Form->input('description', array('label' => 'Notes'));
echo $this->Form->input('name', array( 'value' => ['type_id']['category_id'] , 'type' => 'hidden'));
//echo $this->Form->input('cost');
// echo $this->Form->input('Tag');
?>
</fieldset>
Product controller add function
public function add() {
if ($this->request->is('post')) {
$this->Product->create();
if ($this->Product->save($this->request->data)) {
$this->Session->setFlash(__('The product has been saved'));
$this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash(__('The product could not be saved. Please, try again.'));
}
}
$subcategories = $this->Product->Subcategory->find('list',array('order'=>'Subcategory.name asc'));
$categories = $this->Product->Category->find('list',array('order'=>'Category.name asc'));
$types = $this->Product->Type->find('list',array('order'=>'Type.name asc'));
$this->set(compact('subcategories', 'categories', 'types'));
}
In order to do it the way you are trying to do it, you would have to use client-side javascript to update the input value "on-the-fly", but that's not very safe and can easily be messed with. It would make much more sense to drop the name input altogether and just handle this in the beforeSave method of your Product model (or alternatively by defining the name value in your Controller just before saving).
public function beforeSave($options = array()) {
// Generate the name based on type and category
$this->data['Product']['name'] = $this->data['Product']['type_id'] .
$this->data['Product']['category_id'];
return true;
}
Update based on your comment.
In order to get the names, just find those names (assuming your models are associated) and define those:
public function beforeSave($options = array()) {
// Get the type name
$type = $this->Type->field('name', array(
// Set the condition for the field
'Type.id' => $this->data['Product']['type_id']
));
// Get the category name
$category = $this->Category->field('name', array(
// Set the condition for the field
'Category.id' => $this->data['Product']['category_id']
));
// Generate the name based on type and category
$this->data['Product']['name'] = $type . $category;
return true;
}

how to combine two HABTM saves in one form in CakePHP?

I have two models Business and User. They are related by a HABTM relationship.
Everything is working with the baked controllers, models and views.
Now I'm trying to combine the two models in one form so the user can enter a business name with is user info.
Here's the form :
Form->create('User'); ?>
Form->input('Business.name', array('label' => __('Business name')));
echo $this->Form->input('User.email');
echo $this->Form->input('User.firstname');
echo $this->Form->input('User.lastname');
echo $this->Form->input('User.password');
echo $this->Form->input('User.phone_cell', array('type' => 'text'));
echo $this->Form->input('User.phone_home', array('type' => 'text'));
echo $this->Form->input('User.phone_work', array('type' => 'text'));
?>
Form->end(__('Submit')); ?>
The only way I was able to make it work was to save the User first and then get the user id and save the business after by adding the user array with the new id.
if ($this->User->save($this->request->data)) {
$this->request->data['User'] = array('User' => array(0 => $this->User->id));
if ($this->User->Business->save($this->request->data)) {
// User saved
} else {
// User not saved
}
} else {
$this->Session->setFlash(__('The user could not be saved. Please, try again.'));
}
I tried the saveAll method without success. Is is possible to optimize this the CakePHP way for a single save ?
Thanks
I was able to get it to work myself with a couple models named User and Group. Here's some snips from my code to show how I did it:
UsersController.php
public function edit($id = null)
{
$this->User->id = $id;
if ($this->request->is('get')) {
//On page load load the user data
$this->request->data = $this->User->read();
} else {
//Saving
if ($this->User->save($this->data)) {
//....snipped...
} else {
$this->Session->setFlash('Unable to update the user.');
}
}
//Build $groups array for form
// Only admins can assign admin rights
if ($this->isMember('Admin')) {
$this->set('groups',$this->User->Group->find('list'));
} else {
$this->set('groups',$this->User->Group->find('list',array(
'conditions' => array(
'Group.name !=' => 'Admin'
)
)));
}
//...more snipping...
}
edit.ctp (View)
echo $this->Form->create('User', array('action' => 'edit'));
echo $this->Form->input('User.username');
echo $this->Form->input('Group',array(
'type' => 'select',
'multiple' => true,
'label' => "Group (Select multiple entries with CTRL)",
'size' => count($groups)
)
);
//More snipping
With that example to work from, how are you validating that the Business.name entered is valid and can be matched to the HABTM relation? Mine forces a selection list in this case. My Model is extremely simple so I didn't include that.
What are your outputs to debug($this->data); vs. debug($this->request->data)?

Updating a row in cakephp

I need to update a particular row. This doesn't seem to work. Any help is appreciated.
View updated:
<?php
echo $this->Form->create("Setting", array('action' => 'index'));
echo $this->Form->input('id', array('type' => 'hidden'));
echo $this->Form->checkbox('blog_state');
echo $this->Form->end('Save Post');
?>
Controller updated:
public function index($id = 0){
$this->Setting->id = $id;
if (empty($this->request->data)) {
$this->request->data = $this->Setting->read();
} else {
if ($this->request->is('post')) {
$this->request->data['Setting']['id'] = $id;
$this->Setting->save($this->request->data);
$this->Session->setFlash('This should have saved...');
}
}
}
Edit:
blog_state is a boolean, and works fine. It loads the value from the DB normally and saves it to the new row normally. (I need it to update the existing row it is being pulled from, which is where my problem is)
Update your view:
<?php
echo $this->Form->create("Setting", array('action' => 'index'));
echo $this->Form->input('id', array('type' => 'hidden'));
echo $this->Form->checkbox('blog_state');
echo $this->Form->end('Save Page');
?>
You will also need to make sure you set the id in the function so it will populate the value correctly. The record cannot be updated unless it knows the PK ID it is updating.
The way you can accomplish this is by setting it in the request data:
$this->request->data['Setting']['id'] = $id;
Then it will automatically be set in the view.
UPDATE
It looks like your logic may be flawed. The form will not necessarily pass the ID back on the URL. So update you form like so and check again if it works. It looks like the way you currently have it it will set ID to null which will create a new record.
public function index($id = 0){
if (empty($this->request->data)) {
$this->Setting->id = $id;
$this->request->data = $this->Setting->read();
} else {
if ($this->request->is('post')) {
$this->Setting->save($this->request->data);
$this->Session->setFlash('This should have saved...');
}
}
}
Well you need to know what row it is effecting (this will usually be argument to your function).
public function index() {
// Things here
}
This will create the index page for that controller.
Create an edit function like
public function edit($id = null) {
$this->Setting->id = $id;
if (!$this->Setting->exists()) {
// Exception.
}
if ($this->Setting->save($this->request->data)) {
$this->Session->setFlash(__('Saved'));
}
}
Then you can access it like http://example.com/setting/edit/45
Make sure you have primary key id column in your DB if not override the your chosen primary key in model like below.
<?php
class Test extends AppModel{
public $primaryKey = 'primarykey column name';
}
?>

Resources