I have the following link structure for my portfolio:
<?php echo $this->Html->link($post['Portfolio']['title'], array('controller' => 'portfolio', 'action' => 'view', Inflector::slug($post['Portfolio']['title'])), array('title' => $post['Portfolio']['title'])); ?>
Which gives urls like: http://driz.co.uk/portfolio/view/Paperview_Magazine
However how do I get my controller to show the item based on the title?
So far I have this but have not been able to get it to work and just get a blank page (so I ALSO need to check the format is correct and that their is a relevant item)
function view ( $title )
{
$posts = $this->Portfolio->find('first', array('conditions' => array('Portfolio.title' => $title)
));
if (empty($title))
{
$this->cakeError('error404');
}
$this->set(compact('posts'));
}
#Ross suggested that you search using Portfolio.slug so here's how you could do this:
Add a field to your database table called slug. You'll most likely want a VARCHAR with sufficient length to accommodate the slug.
When you create or update a "Portfolio" record, use the Inflector::slug method to generate a slug and save it to your database. You could always do this in the model's beforeSave event or if you prefer, in the controller before saving the data.
Update the find call to look for Portfolio.slug instead of Portfolio.title.
Unfortunately, there's no way to reverse the Inflector::Slug function as it removes certain characters like apostrophes, quotes, parentheses, etc. which is why you need to save the slug to your database if you want to search for it.
Here's how you could use the beforeSave event in your model:
public function beforeSave(array $options = array())
{
// If the title is not empty, create/update the slug.
if ( ! empty($this->data[$this->alias]['title'] )
$this->data[$this->alias]['slug'] = Inflector::slug($this->data[$this->alias]['title']);
// Returning true is important otherwise the save or saveAll call will fail.
return true;
}
Related
So, I'm using this extension: x-editable for yii.
And I'm currently trying to update two models in update() function.
I have two models:
Realisasi.php
RealisasiDeadline.php.
So when a cell is updated on table Realisasi.php (one value in column t1701 in this case), I want the function to update the corresponding value in column t1701 of table RealisasiDeadline, using column no as the foreign key.
Since I haven't found any example on Google, I made it up myself:
public function actionSimpanEdit($kode) {
Yii::import('editable.EditableSaver');
$es = new EditableSaver($_GET['model']); // 'modelName' is classname of model to be updated
$es->update();
$es2 = RealisasiDeadline::model()->findByPk($kode);//this is where I'm stuck
$es2['t1701'] = '1991-11-19';//this too
$es->update();//and this
}
This is the view.php:
array(
'name' => 't1701',
'value' => 'CHtml::value($data,"hubtarget.t1701")=== "0"?"Target Nol":$data->t1701',
'header' => 'Bkl Selatan',
'class' => 'editable.EditableColumn',
'editable' => array(
'url' => $this->createUrl('simpanEdit', array('model' => 'Realisasi', 'kode'=>'$data->no')),
)
),
What have I missed? Is it possible at all to do? If not, is there another solution?
UPDATE
It's not showing any error. But the value in table RealisasiDeadline doesn't change, only the one in Realisasi does.
Added some comments to original function so you can improve upon it. Biggest issue with this code is that looking at it I have no idea what it does.
public function actionSimpanEdit($kode) {
Yii::import('editable.EditableSaver'); // Should be at the top of the file
// For the love of god use descriptive variable names
$es = new EditableSaver($_GET['model']); // Would prefer to have model as actions argument
$es->update();
$es2 = RealisasiDeadline::model()->findByPk($kode); // no idea what this model is responsible for
$es2['t1701'] = '1991-11-19'; // no idea what attribute t1701 is, use descriptive names
$es->update();
}
I have refactored it a bit. Still have no idea what it does ;/
public function actionSimpanEdit($id, $model) {
$editableSaver = new EditableSaver($model);
$editableSaver->update();
$deadline = RealisasiDeadline::model()->findByPk($id);
if($deadline instanceof RealisasiDeadline) {
$deadline->t1701 = '1991-11-19';
if(!$deadline->update()) {
// something went wrong
}
} else {
// not found
}
}
Going back to your problem. It is probably caused by RealisasiDeadline model being not found or some behavior or event preventing it from update.
I've got problem with field validation.
I would like to validate form through model. I want to check if field with some value exists.
I would like to block using some titles more than once.
For example
if field "Site" with title "Main" exists in database, you can't validate form.
If it doesn't exist, you can pass it.
I would like to allow user to add just one "Site" with title "Main", but he can add "Site" with any other title in any case.
Have you got some idea how to solve it?
I think you have two options.
(1) Setup an Ajax request to the server.
To do so:
Create a function, that responds to an Ajax request, in your SiteController named checkName()
public function checkName($name) {
// allow ajax requests
$this->request->allowMethod(['ajax']);
// perform your check within the db
$isExistent = [...];
// prepare the response
$response = ['name' => $name, 'isExistent' => $isExistent];
if ($this->request->isAjax()){
$this->autoRender = false;
$this->response->disableCache();
$this->response->type(['json' => 'application/json']);
$this->response->body(json_encode($response));
}
}
Add the route to your routes file with the option '_ext' => 'json'
Prepare your Javascript Ajax function that call the route you have defined and attach it on the onchange attribute of your input field. (see this link for a simple example: http://www.w3schools.com/jquery/ajax_ajax.asp)
(2) Make the 'name' field of the Site table unique.
To do so you could add the following function to your SiteTable class
public function buildRules(
RulesChecker $rules
) {
$rules->add($rules->isUnique(['name']));
return $rules;
}
In my form, I created the value by populating the dropbox from values from a table.
<?php echo $form->dropDownList($model,'status', CHtml::listData(Statusprospect::model()->findAll(), 'id', 'status'),array('prompt' => 'Select')); ?>
When I view the record it has a 1, as it should for status. How do I make it display the value when the record is viewed, instead of the 1.
The view file code that currently displays the field is this:
<?php echo CHtml::encode($data->status); ?>
The Model does have the relationship defined:
public function relations()
{
// NOTE: you may need to adjust the relation name and the related
// class name for the relations automatically generated below.
return array(
'status0' => array(self::BELONGS_TO, 'Statusprospect', 'status'),
);
}
How would I accomplish showing the value instead of the number?
Right now this should work $data->status0->status.
Take care that $data->status0->status might not be set if $data->status can be null so make a check beforehand if that is the case. You can use
CHtml::encode(isset($data->status0->status) ? $data->status0->status : '-');
Assume I'm in my items controller.
Ok say I am in my view action (the url would be something like /items/view/10012?date=2013-09-30) which lists a list of items that belongs to a client on a given date.
I want to link to add a new item. I would use the htmlhelper like so:
echo $this->Html('action'=>'add');
In my add action I have a form which has fields like client_id and item_date.
When I'm in my view action I know these values as I am viewing the items for a specific client on a specific date. I want to pass these variables to my add action so it will prefill those fields on the form.
If I add a query string in my link ('?' => array('client_id'=>$client_id)) it breaks the add action as it will give an error if the request is not POST. If I use a form->postLink I get another error as the add action's POST data must only be used for adding the record, not passing data to prefill the form.
I basically want to make my link on the view page pass those 2 variables to the add action in the controller so I can define some variables to prefill the form. Is there a way to do this?
Here is my add controller code. It may differ in content a bit from my question above as I have tried to simplify the question a bit but the concept should still apply.
public function add(){
if ($this->request->is('post')) {
$this->Holding->create();
if ($this->Holding->save($this->request->data)) {
$this->Session->setFlash(__('Holding has been saved.'), 'default', array('class' => 'alert alert-success'));
return $this->redirect(array('action' => 'index'));
}
$this->Session->setFlash(__('Unable to add your holding.'), 'default', array('class' => 'alert alert-danger'));
}
$this->set('accounts', $this->Holding->Account->find('list'));
$sedol_list = $this->Holding->Sedol->find('all', array(
'fields' => array(
'id', 'sedol_description'
),
'recursive' => 0,
'order' => 'description'
)
);
$this->set('sedols', Hash::combine($sedol_list, '{n}.Sedol.id', '{n}.Sedol.sedol_description') );
}
Why not use proper Cake URL parameters?
echo $this->Html->link('Add Item', array(
'action' => 'add',
$client_id,
$item_date
));
This will give you a much nicer URL like:
http://www.example.com/items/add/10012/2013-09-30
And then in your controller, you modify the function to receive those parameters:
public function add($client_id, $item_date) {
// Prefill the form on this page by manually setting the values
// in the request data array. This is what Cake uses to populate
// the form inputs on your page.
if (empty($this->request->data)) {
$this->request->data['Item']['client_id'] = $client_id;
$this->request->data['Item']['item_date'] = $item_date;
} else {
// In here process the form data normally from when the
// user has submitted it themselves...
}
}
I am modifying an already contributed drupal module (Inline Ajax Search) to handle searching of a specific content type with some search filters (i.e. when searching for help documentation, you filter out your search results by selecting for which product and version of the product you want help with).
I have modified the module some what to handle all the search filters.
I also added in similar functionality from the standard core search module to handle the presenting of the search form and search results on the actual search page ( not the block form ).
The problem is that when i submit the form, i discovered that I'd lose all my post data on that submit because somewhere, and i don't know where, drupal is either redirecting me or something else is happening that is causing me to lose everything in the $_POST array.
here's the hook_menu() implementation:
<?php
function inline_ajax_search_menu() {
$items = array();
$items['search/inline_ajax_search'] = array(
'title' => t('Learning Center Search'),
'description' => t(''),
'page callback' => 'inline_ajax_search_view',
'access arguments' => array('search with inline_ajax_search'),
'type' => MENU_LOCAL_TASK,
'file' => 'inline_ajax_search.pages.inc',
);
}
?>
the page callback is defined as such (very similar to the core search module's search_view function):
<?php
function inline_ajax_search_view() {
drupal_add_css(drupal_get_path('module', 'inline_ajax_search') . '/css/inline_ajax_search.css', 'module', 'all', FALSE );
if (isset($_POST['form_id'])) {
$keys = $_POST['keys'];
// Only perform search if there is non-whitespace search term:
$results = '';
if(trim($keys)) {
require_once( drupal_get_path( 'module', 'inline_ajax_search' ) . '/includes/inline_ajax_search.inc' );
// Collect the search results:
$results = _inline_ajax_search($keys, inline_ajax_search_get_filters(), "page" );
if ($results) {
$results = theme('box', t('Search results'), $results);
}
else {
$results = theme('box', t('Your search yielded no results'), inline_ajax_search_help('inline_ajax_search#noresults', drupal_help_arg()));
}
}
// Construct the search form.
$output = drupal_get_form('inline_ajax_search_search_form', inline_ajax_search_build_filters( variable_get( 'inline_ajax_search_filters', array() ) ) );
$output .= $results;
return $output;
}
return drupal_get_form('inline_ajax_search_search_form', inline_ajax_search_build_filters( variable_get( 'inline_ajax_search_filters', array() ) ) );
}
?>
from my understanding, things should work like this: A user goes to www.mysite.com/search/inline_ajax_search and drupal will process the path given in my url and provide me with a page that holds the themed form for my search module. When i submit the form, whose action is the same url (www.mysite.com/search/inline_ajax_search), then we go thru the same function calls, but we now have data in the $_POST array and one of them is indeed $_POST['form_id'] which is the name of the form "inline_ajax_search_search_form". so we should be able to enter into that if block and put out the search results.
but that's not what happens...somewhere from when i submit the form and get my results and theme it all up, i get redirected some how and lose all my post data.
if anybody can help me, it'd make me so happy lol.
drupal_get_form actually wipes out the $_POST array and so that's why I lose all my post data.
according to this: http://drupal.org/node/748830 $_POST should really be ignored when doing things in drupal. It's better to find a way around using it. One way is the way described in the link, making ur form data persist using the $_SESSION array. I'm sure there are various other and better ways to do this, but yeah, drupal_get_form was the culprit here...