Issue with afterFind().
Current code :
<?php
public function afterFind($results, $primary = false)
{
foreach ($results as $key => $val)
{
if (isset($val['User']['country_code']) && isset($val['User']['mobile']))
{
$results[$key]['User']['mobile'] = trim($val['User']['country_code']).trim($val['User']['mobile']);
}
}
return $results;
}
?>
It's working with $this->User->find(), but not working with other models.
I have 3 models. Room, Place and User.
<?php
$this->Place->bindModel(array('belongsTo' => array('User')));
$this->Room->bindModel(array('belongsTo' => array('Place')));
?>
When I try to find Room data :
<?php
$data = $this->Room->find('first');
array(
[Room] => array()
[Place] => array(
[User] => array(
[mobile] => /* here after find not working it should content country code + mobile */
)
)
)
?>
That might be problem with $reset while binding flyby. http://api.cakephp.org/2.1/source-class-Model.html#868-910
Please set $reset to false.
$this->Model->bindModel(array(...),false);
Related
I have registered a custom taxonomy as part of my custom post type, but when passing it through to get_categories() it returns an empty array. Any ideas as to why?
// Register FAQ Categories taxonomy
function bv_faq_register_categories() {
register_taxonomy(
'faq-category',
'faq',
array(
'label' => 'Categories',
'rewrite' => array('slug' => 'faq-category'),
'hierarchical' => true
)
);
}
add_action('init', 'bv_faq_register_categories');
// Category view
$categories = get_categories(array(
'taxonomy' => 'faq-category'
));
$categories is returning an empty array.
Have you tried get_terms instead?
$categories = get_terms( 'faq-category', array(
'orderby' => 'count',
'hide_empty' => 0
) );
Like #AD Styles said I would use get_terms using the custom taxonomy, to expand a bit here's some example code:
<?php
$post_type = 'faq-category';
// Get all the taxonomies for this post type
$taxonomies = get_object_taxonomies( (object) array( 'post_type' => $post_type ) );
foreach( $taxonomies as $taxonomy ) :
// Gets every "category" (term) in this taxonomy to get the respective posts
$terms = get_terms( array(
'taxonomy' => $taxonomy,
'parent' => 0
) );
foreach( $terms as $term ) :
echo "<h1>".$term->name."</h1>";
endforeach;
endforeach;
?>
Your code looks ok. Do you have assigned this category to any post/post type?
If not then you will get an empty result. for testing you can set 'hide_empty' = false like this:
// Category view
$categories = get_categories(array(
'taxonomy' => 'faq-category',
'hide_empty' => false // set it true
));
Also, you can use get_terms() function.
Sample here, please check that happens or not
<?php
echo $this->Paginator->prev
($this->Html->image('prev.png'), array('escape' => false),
array(), null, array('class' => 'prev'));
echo $this->Paginator->counter
('Page {:page} of {:pages}, Total Records {:count}');
echo $this->Paginator->next($this->Html->image
('next.png'), array('escape' => false),
array(), null, array('class' => 'next'));
?>
Check out this, hope it works
public function index() {
try {
$paginatedData = $this->Paginator->paginate();
} catch (NotFoundException $e) {
//get current page
$page = $this->request->params['named']['page'];
if( $page > 1 ){
//redirect to previous page
$this->redirect( array( "page" => $page-1 ) );
}else{
$paginatedData = array(); //no data to paginate so use empty array()
//you will have to check for this in the view and no longer display the pagination links, since they will NOT be defined
}
}
}
I have paginate 2 models (Income,Expanse) in the Student model view page .
I have really page not found problem with cakephp's pagination.
It have no any problem when the paginate result has only 1 page or the same, but It will error if one has more paginate result than other.
for example.
-income has paginate result 1 page and expanse has 1 page. No problem at all.
-income has 10 pages and expanse has 10 pages no problem at all.
-income has 2 pages and expanse has 1 page. income page 2 page not found error.
-income has 5 pages and expanse has 2 pages. income page 3,4,5 page not found error.
-income has 10 pages and expanse has 13 pages. expanse page 11,12,13 page not found error.
for example(not real one) , Student's view have income and expense items ,Both are display as pagination.
//this is how I config paginator in Student controller.
public $paginate = array(
'Income' => array (
'order'=>array('income_id'=>'ASC'),
'limit'=>10,
'recursive'=>0
),
'Expense' => array (
'order'=>array('expense_id'=>'ASC'),
'limit'=>10,
'recursive'=>0,
)
);
<div class="paging">//this is how I config Income paginator in Student view
<?php
echo $this->Paginator->prev('< ' . __('previous'), array('model'=>'Income'), null, array('class' => 'prev disabled'));
echo $this->Paginator->numbers(array('model'=>'Income','separator' => '','modulus'=>100,'first'=>'หน้าแรก','last'=>'หน้าสุดท้าย'));
echo $this->Paginator->next(__('next') . ' >', array('model'=>'Income'), null, array('class' => 'next disabled'));
?>
</div>
//this is how I config Expanse paginator in Student view
<div class="paging">
<?php
echo $this->Paginator->prev('< ' . __('previous'), array('model'=>'Expanse'), null, array('class' => 'prev disabled'));
echo $this->Paginator->numbers(array('model'=>'Expanse','separator' => '','modulus'=>100,'first'=>'หน้าแรก','last'=>'หน้าสุดท้าย'));
echo $this->Paginator->next(__('next') . ' >', array('model'=>'Expanse'), null, array('class' => 'next disabled'));
?>
</div>
Please help me. sorry for my english
If you have any question , please ask me.
Thank you.
Yes It is possible.....
Step1 : Make paging.ctp in View/Elements/paging.ctp
<?php if (!isset($this->Paginator->params['paging'])) {
return;
}
if (!isset($model) || $this->Paginator->params['paging'][$model]['pageCount'] < 2) {
return;
}
if (!isset($options)) {
$options = array();
}
$options['model'] = $model;
$options['url']['model'] = $model;
$this->Paginator->__defaultModel = $model;
?>
<div class="paging">
<ul class="pagination pull-right">
<?php
echo $this->Paginator->prev('<<', array_merge(array('class' => '', 'tag' => 'li'), $options), null, array('class' => 'disabled', 'tag' => 'li'));
echo $this->Paginator->numbers(am($options,array('tag' => 'li', 'separator' => '', 'currentClass' => 'active', 'currentTag' => 'a')));
echo $this->Paginator->next('>>', array_merge(array('class' => '', 'tag' => 'li'), $options), null, array('class' => 'disabled', 'tag' => 'li'));
?>
</ul>
</div>
Step2: Now add this function to Controllers/AppController
public function pageForPagination($model) {
$page = 1;
$sameModel = isset($this->request->params['named']['model']) && $this->request->params['named']['model'] == $model;
$pageInUrl = isset($this->request->params['named']['page']);
if ($sameModel && $pageInUrl) {
$page = $this->request->params['named']['page'];
}
$this->passedArgs['page'] = $page;
return $page;
}
Step3: Now in controller action do some conditions so that proper page should be call
if (empty($this->request->params['named'])) {
$page = $this->pageForPagination('Income');
$page1 = $this->pageForPagination('Expense');
public $paginate = array(
'Income' => array (
'order'=>array('income_id'=>'ASC'),
'limit'=>10,
'page' => $page,
'recursive'=>0
),
'Expense' => array (
'order'=>array('expense_id'=>'ASC'),
'limit'=>10,
'page' => $page1,
'recursive'=>0,
));
} else if ($this->request->params['named']['model'] == 'Income') {
$page = $this->pageForPagination('Income');
public $paginate = array(
'Income' => array (
'order'=>array('income_id'=>'ASC'),
'limit'=>10,
'page' => $page,
'recursive'=>0
));
} else if ($this->request->params['named']['model'] == 'Expense') {
$page1 = $this->pageForPagination('Expense');
public $paginate = array(
'Expense' => array (
'order'=>array('income_id'=>'ASC'),
'limit'=>10,
'page' => $page1,
'recursive'=>0
));
Step 4: Now call the paging element in your student view
<?php echo $this->element('paging', array('model' => 'Income'));?>
<?php echo $this->element('paging', array('model' => 'Expense'));?>
Note: Please take care of brackets and semicolon.......and sorry to be late but will help others...Thanks..
I think if you use two different iframes to load different URLs for pagination, you can handle this.
OR you have to call ajax functions to paginate 2 models in one page without reloading the page....
I am trying to get my edit to work I need the contact detail data to load when the user data loads. I have set the data in a similar manner to how I am retrieving the list of roles. I also don't know how to retrieve according to the model currently I was hard-coding it to retrieve 28. Would greatly appreciate any help provided.
public function edit($id = null) {
//Populate roles dropdownlist
$data = $this->User->Role->find('list', array('fields' => array('id', 'name')));
$this->set('roles', $data);
$data2 = $this->User->ContactDetail->find('first', array(
'conditions' => array('ContactDetail.id' =>'28')));
$this->set('contactdetails', $data2);
if (!$this->User->exists($id)) {
throw new NotFoundException(__('Invalid user'));
}
if ($this->request->is(array('post', 'put'))) {
if ($this->User->save($this->request->data)) {
$this->Session->setFlash(__('The user has been saved.'));
return $this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash(__('The user could not be saved. Please, try again.'));
}
} else {
$options = array('conditions' => array('User.' . $this->User->primaryKey => $id));
$this->request->data = $this->User->find('first', $options);
}
}
my view is set up in the following manner
<?php echo $this->Form->create('User'); ?>
<fieldset>
<legend><?php echo __('Edit User'); ?></legend>
<?php
echo $this->Form->input('id');
echo $this->Form->input('username');
echo $this->Form->input('password');
echo $this->Form->input('role_id');
echo $this->Form->input('ContactDetail.name');
echo $this->Form->input('ContactDetail.surname');
echo $this->Form->input('ContactDetail.address1');
echo $this->Form->input('ContactDetail.address2');
echo $this->Form->input('ContactDetail.country');
echo $this->Form->input('ContactDetail.email');
echo $this->Form->input('ContactDetail.fax');
?>
<label>Are you interested in buying property in Malta?</label>
<?php
$interest_buy = array('0'=>'no','1' => 'yes');
echo $this->Form->input('ContactDetail.interest_buy_property',array('type'=>'radio','options'=>$interest_buy,'value'=>'0','legend'=>FALSE));
?>
<label>Are you interested in renting property in Malta?</label>
<?php
$interest_rent = array('0'=>'no','1' => 'yes');
echo $this->Form->input('ContactDetail.interest_rent_property',array('type'=>'radio','options'=>$interest_rent,'value'=>'0','legend'=>FALSE));
echo $this->Form->input('ContactDetail.mobile');
echo $this->Form->input('ContactDetail.phone');
echo $this->Form->input('ContactDetail.postcode');
echo $this->Form->input('ContactDetail.town');
echo $this->Form->input('ContactDetail.newsletter',array('type'=>'checkbox','label'=>'Would you like to register for the newsletter?' ,'checked'=>'1','legend'=>FALSE,));
?>
?>
</fieldset>
<?php echo $this->Form->end(__('Submit')); ?>
User Model
public $primaryKey = 'id';
public $displayField = 'username';
public function bindNode($user) {
return array('model' => 'Role', 'foreign_key' => $user['User']['role_id']);
}
public function beforeSave($options = array()) {
$this->data['User']['password'] = AuthComponent::password(
$this->data['User']['password']
);
return true;
}
public $belongsTo = array(
'Role' => array('className' => 'Role'));
public $hasOne = array(
'ContactDetail' => array(
'foreignKey' => 'id'));
public $actsAs = array('Acl' => array('type' => 'requester', 'enabled' => false));
public function parentNode() {
if (!$this->id && empty($this->data)) {
return null;
}
if (isset($this->data['User']['role_id'])) {
$roleId = $this->data['User']['role_id'];
} else {
$roleId = $this->field('role_id');
}
if (!$roleId) {
return null;
} else {
return array('Role' => array('id' => $roleId));
}
}
}
ContactDetail Model
public $primaryKey = 'id';
public $displayField = 'name';
If I get you right, you have 1 contact details row for each user. In this case, you need to define in your User model:
public $hasOne = array(
'ContactDetail' => array(
'foreignKey' => 'id',
),
);
Like this, your ids will be synced in both tables. If you don't want to make the id a foreign key, you don't have to, it's just a suggestion.
Next, when you retrieve your data in the controller, you can do:
$this->User->Behaviors->load('Containable');
$user = $this->User->find('first', array(
'conditions' => array('User.id' => $id),
'contain' => array('ContactDetail'),
));
Now I don't know if there is an automated way to do this, but I sort my data manually to fill in the inputs. I am guessing you will get a structure like array('User' => array(), 'ContactDetail' => array()).
$user['User']['ContactDetail'] = $user['ContactDetail'];
unset($user['ContactDetail']);
$this->request->data = $user;
Then in your view just set the fields as the input array:
$this->Form->create('User');
$this->Form->input('User.some_user_field');
$this->Form->input('User.ContactDetail.some_contact_detail_field');
This should fill in your fields. When you go save your data, if your array is structured like this, you can use saveAssociated():
$this->User->saveAssociated($this->request->data, array('deep' => true));
EDIT
In case your relation is defined as User hasMany ContactDetail, then you need to structure your data like this:
$this->request->data = array(
'User' => array(
// user data
'ContactDetail' => array(
[0] => array(
//contact data
),
),
),
);
And in your view:
$this->Form->input('User.ContactData.0.field')
This is for 1 row only, If you need more rows on the child table with 1 input, do your logic accordingly.
Once your User model hasOne ContactDetail, you don't need retrieve the information twice, since you've done in $this->request->data line, all association model will retrieve too.
So, your Controller looks like this:
public function edit($id = null) {
if (!$this->User->exists($id)) {
throw new NotFoundException(__('Invalid user'));
}
// Roles
$roles = $this->User->Role->find('list', array('fields' => array('id', 'name')));
$this->set(compact('roles');
if ($this->request->is(array('post', 'put'))) {
if ($this->User->saveAll($this->request->data)) {
$this->Session->setFlash(__('The user has been saved.'));
return $this->redirect(array('action' => 'index'));
} else {
$this->Session->setFlash(__('The user could not be saved. Please, try again.'));
}
} else {
$this->request->data = $this->User->read(null, $id);
}
}
And your View, for ContactDetail's fields looks like this:
echo $this->Form->input('ContactDetail.name');
And so for all the fields related to the model ContactDetail. You can find more details here: Saving Your Data.
User model:
public $hasOne = array(
'ContactDetail' => array(
'className' => 'ContactDetail',
'foreignKey' => 'user_id',
'dependent' => true
)
);
The best solution I have found is by setting
public $belongsTo = array(
'Role' => array('className' => 'Role')
, 'ContactDetail' => array('className' => 'ContactDetail'));
This way the contact detail data loads. Although the data once saved does not update contactdetails.
For me to save I used
$this->User->saveAll($this->request->data)
this worked fully
I've set a simple search engine on my CakePHP project which looks like that :
<?php
echo $this->Form->create("Post", array(
"action" => "search",
"id" => "searchForm"
));
echo $this->Form->input("keyword", array(
"label" => "",
"type" => "search",
"placeholder" => "Recherche..."
));
echo $this->Form->end();
?>
Here is the controller :
function search() {
$keyword = $this->request->data;
$keyword = $keyword["Post"]["keyword"];
$cond = array("OR" => array(
"Post.title LIKE '%$keyword%'",
"Post.description LIKE '%$keyword%'"
));
$posts = $this->Post->find("all", array("conditions" => $cond));
$this->set(compact("posts", "keyword"));
}
And it works great. The only problem is when I want to paginate the results. I simply add :
$posts = $this->paginate();
And here is the problem. When I add this, CakePHP give me all the posts and not only the ones that match the keyword.
So, if you would have a solution, it would be nice :)
According to the CakePHP book you should be able to do
$this->paginate('Post', array(
'OR' => array(
'Post.title LIKE' => "%$keyword%",
'Post.description LIKE' => "%$keyword%"
)
));
Or you can do it like this ( from the cakephp site ).
public function list_recipes() {
$this->paginate = array(
'conditions' => array('Recipe.title LIKE' => 'a%'),
'limit' => 10
);
$data = $this->paginate('Recipe');
$this->set(compact('data'));
);
Source:
http://book.cakephp.org/2.0/en/core-libraries/components/pagination.html
Paginate does its own lookup on the data I believe. The find you are calling previously has no effect on the paginate.
Try this:
$this->paginate = array( 'conditions' => $cond, ));
you can use Session for storing conditions
the first, when you submit form you store conditions into Session
and then(paginate) you can read conditions from Session
example i want to search the products:
Products/search.ctp
<?php
echo $this->Form->create('Product');
echo $this->Form->input('keyword');
echo $this->Form->end(__('Search'));
?>
ProductsController.php
<?php
class ProductsController extends AppController{
public function search() {
if ($this->request->is('post')) {
$keyword = $this->request->data['Product']['keyword'];
$this->paginate = array(
'fields' => array('Product.name', 'Product.price', 'Product.created'),
'order' => array('Product.created' => 'DESC', 'Product.price' => 'DESC'),
'limit' => 30,
'conditions' => array('Product.name LIKE' => '%' . $keyword . '%')
);
// store array $this->paginate into Session
$this->Session->write('paginate', $this->paginate);
}
$this->paginate = $this->Session->read('paginate');
$this->set('products', $this->paginate('Product'));
}
}