So, what I have is a page which displays a post. Posts are gathered into projects. And, on this page, in addition to the post, I'ld to display the previous and next post of the same project. So, I have this in my controller :
$this->set("post", $this->Post->find("first", array("conditions" => array("Post.id" => $id), "contain" => array("User", "Project", "Project.Post" => array("id", "image", "title"), "Comment", "Comment.User" => array("id", "username", "mail"), "Comment.User.Post" => array("id", "image", "title")))));
$this->set("neighbors", $this->Post->find("neighbors", array("field" => "id", "value" => $id)));
The problem is that it get the previous and next post from all the post, not only the ones of the same project.
So, if you could helping me a bit :)
I'm assuming Post belongsTo Project and Project hasMany Post.
You would just need to add an extra condition:
$post = $this->Post->find("first", ...); // this is your first find call, assign it to a var instead
$neighbors = $this->Post->find('neighbors', array(
'field' => 'id',
'value' => $id,
'conditions' => array(
'Post.project_id' => $post['Post']['project_id'],
),
));
$this->set(compact('post', 'neighbors'));
I haven't tried it, but looking at the source, findNeighbors does honor the conditions key.
Related
I'm working with some module and I must add new column to my database.
1) I modified edit form:
$fieldset->addField("temporary", "select", array(
"label" => Mage::helper("my_helper")->__("Temporarily unavailable"),
"name" => "temporary",
'values' =>
Mage::getSingleton('adminhtml/system_config_source_yesno')->toOptionArray(),
));
2) I add new column to grid:
$this->addColumn("temporary", array(
"header" => Mage::helper("my_helper")->__("Temporarily unavailable"),
"index" => "temporary",
"type" => "options",
"options" => Mage::getSingleton('adminhtml/system_config_source_yesno')->toArray(),
));
At the end I run my script na update extension version in config.xml
Mage::log(__FILE__ . '::start');
$installer = $this;
$installer->startSetup();
$tableName = $installer->getTable('my_extension/designer');
$installer->getConnection()
->addColumn($tableName, 'temporary', array(
'type' => Varien_Db_Ddl_Table::TYPE_BOOLEAN,
'default' => 0,
'length' => null,
'nullable' => false,
'comment' => 'temporary'
));
$installer->endSetup();
Mage::log(__FILE__ . '::end');
After that everything works perfectly until, I want to change temporary value "temporary". If I check it once as "Yes" i can't change it back to "No".
Any Ideas
It might be a cache problem.
You need to clear cache through admin System -> Cache Management (Flush Magento Cache and Flush Cache Storage buttons). Magento likes to cache previous queries so adding new fields without clearing the cache can cause problems with new columns not being saved.
All,
I currently have slug setup in my app where I generate the following as links:
http://www.domain.com/article/my-first-news-article.
And this is the current route that I use to accomplish that in addition to the view acepting a slug instead of id:
Router::connect('/article/*',array('controller' => 'articles', 'action' => 'view'));
However, I wanted to improve that a little bit more by adding published date to the URL like the following:
http://www.domain.com/article/2012/06/27/my-first-news-article
I have the following code from the CakePHP manual, but it doesnt seem to work:
Router::connect(
'/article/:year/:month/:day/:slug',
array(
'controller' => 'articles',
'action' => 'view'
),
array(
'year' => '[12][0-9]{3}',
'month' => '0[1-9]|1[012]',
'day' => '0[1-9]|[12][0-9]|3[01]'
)
);
For the sake of this, I really dont care what date is passed to the view. I just care about the slug that is passed. Then I will use function view($slug) to find the article and display it. However the URL needs to be http://www.domain.com/2012/06/27/slug-slug-slug
Thank you....
How do the $this->Html->link() calls look like in the places where you want to use the date in the link?
Are you adding the required params there?
$this->Html->link('Article', array('year' => 2012, 'month' => 01, 'day' => 01, 'action' => 'view', 'slug' => $article['Article']['slug']));
For the sake of completeness, and because somebody else might be interested in this as well, I'll show you my solution to a similar problem:
I want to have URLS in the format
http://mydomain.com/blog/2012/06/slug-slug-slug
i.e. /blog/yyyy/mm/slug
For this, I use
// view a post by year and month and title
Router::connect('/blog/:year/:month/:title/*', array(
'controller' => 'posts',
'action' => 'view'
), array(
'year' => '[12][0-9]{3}',
'month' => '0[1-9]|1[012]',
'title' => '[a-z0-9-]+'
));
With the rules below, you can make sure the correct formats are entered. It also prevents users from entering values such as &"% as slugs.
The /* after title even allows for additional parameters, e.g. for pagination, when your blog entry has several pages (http://mydomain.com/blog/2012/06/slug/page:2).
I also realized that setting the "pass" array is not really necessary (at least in CakePHP 2.0). You can access the parameters directly via $this -> request -> params['year'], etc.
After more research and trials I was able to figure it out.
The following route will work to accept a URL like this:
http://www.mydomain.com/article/2009/06/10/my-first-article-in-mydomain-dot-com.
As a matter of fact, it doesnt actually matter how the date is setup and it will still work. It could also be,
http://www.mydomain.com/article/06/10/2012/my-first-article-in-mydomain-dot-com
Router::connect(
'/article/:year/:month/:day/:slug',
array(
'controller' => 'articles',
'action' => 'view'
),
array(
'pass' => array('slug')
)
);
Just for organization sake, I wanted to use a different table for the authentication component to check, but it doesn't quite work. While I can initially state:
$this->Auth->userModel = "CoreUsers" plus set the loginAction to my proper MVC
works to look at that table just to confirm it's there, but the login doesn't work, it only keeps returning an incorrect password. Something happens in the authentication component; I can't tell what makes it fail. When I rename my table to "Users", it works.
The other part is I'd prefer to actually use the column name of 'email' rather than 'username' since that's really what I'm using anyway.
I am just not having luck finding a complete tutorial and reference sets to do both these successfully with CakePHP 2.x. What is the way forward?
References:
Stack Overflow question How do I use a table other than "Users" for CakePHP's AuthComponent?
Stack Overflow question CakePHP - 'AuthComponent' with a different model name (not 'User')
(I had a look for answers, but I never quite got the whole answer.)
Make sure your database table "core_users" and model "CoreUser" exists.
When you setup component you can put login/logout redirect here.
var $components = array(
"Auth" => array(
'loginRedirect' => array('controller' => 'dashboard', 'action' => 'index'),
'logoutRedirect' => array('controller' => 'core_users', 'action' => 'login')
),
"Session");
Now in beforeFilter medhod you can put the following
function beforeFilter(){
$this->Auth->authenticate = array(
AuthComponent::ALL => array('userModel' => 'CoreUser', 'scope' => array("CoreUser.status" => 1), "fields" => array("username" => "email", "password" => "your_password_field"), 'Form', 'Basic'
);
}
Above example you can ignore status, if you need to pass any other info on the login verification u can use that. Now about you can remove 'Basic' if you only need form validation.
I hope this would work .
First, model names are generally singular. Are you sure you didn't mean CoreUser which would look in the core_users table?
Secondly, you can use the email field instead of username by setting the fields key on your auth setup.
public $components = array(
'Auth' => array(
'authenticate' => array(
'Form' => array(
'userModel' => 'CoreUser',
'fields' => array('username' => 'email')
)
)
)
);
See the book for more information.
I have been able to use CakePHP's saveAll method to simultaneously create 'Members' and enroll them in an 'Event' (creating the HABTM link record), which is awesome. For example, this code creates two new 'Members' and adds a record for each of them to the 'EventsMember' table, enrolling them 'Event' 10:
$data = array(
'0' => array(
'Member' => array('email' => 'nobody#nowhere.com'),
'Event' => array('id' => 10)
),
'1' => array(
'Member' => array('email' => 'somebody#nowhere.com'),
'Event' => array('id' => 10)
)
);
$this->Member->saveAll($data);
However, the record in the 'EventsMember' table also has a field called 'role' that holds something like "Presenter" or "Host" or "Attendee" and I would like to save that data when I create the relationship. I tried this and it does not work (the 'EventsMember' 'role' field is always blank):
$data = array(
'0' => array(
'Member' => array('email' => 'nobody#nowhere.com'),
'Event' => array('id' => 10),
'EventsMember' => array('role' => 'Host')
),
'1' => array(
'Member' => array('email' => 'somebody#nowhere.com'),
'Event' => array('id' => 10),
'EventsMember' => array('role' => 'Attendee')
)
);
$this->Member->saveAll($data);
I'm wondering if this is even possible, and if maybe I have to use some kind of callback like beforeSave or afterSave to get this done? I've read that there are some problems with these callbacks when using saveAll, so I'm looking for any tips on what would be the best practice here.
Thanks!
EDIT: I took Adam's advice and made the following changes to my models:
// Event.php
var $hasMany = array('EventsMember');
// Member.php
var $hasMany = array('EventsMember');
// EventsMember.php
var $belongsTo = array('Event', 'Member');
Then in my controller, my code looked almost identical to my second example, except I called the saveAll() method from the EventsMember model, as described in the documentation:
$data = array(
'0' => array(
'Member' => array('email' => 'nobody#nowhere.com'),
'Event' => array('id' => 10),
'EventsMember' => array('role' => 'Host')
),
'1' => array(
'Member' => array('email' => 'somebody#nowhere.com'),
'Event' => array('id' => 10),
'EventsMember' => array('role' => 'Attendee')
)
);
$this->EventsMember->saveAll($data);
The result was no Member or EventsMember records were saved at all. I tried triggering the save from the Member model ($this->Member->saveAll($data);) and this saved the Member records, but not the joining EventsMember records.
I tried removing the pre-existing HABTM associations, and it made no difference. The beforeSave method of the EventsMember model is getting triggered when I call $this->EventsMember->saveAll($data); but it looks like it won't actually save anything.
I'm stymied.
UPDATE: It turns out that no records were created because the joining records were all being created with Event ids and Member ids of 0, which goes against a unique key I have on those two fields combined (that is, no Member can enroll in an Event twice).
Does this suggest that the join model saveAll functionality is not working as documented, since the Member record isn't getting created (meaning there is no Member id to use in the joining record), and the existing Event id is not being passed to the joining EventsMember record either?
VERDICT: I changed the controller to loop on each record and attempt to $this->EventsMember->saveAll($data) for each index of the array, instead of passing the entire array at once. It worked, but was significantly slower than my first example (at the very top). Mind you, I am using transactions, so perhaps using the atomic => false; option would speed things up, while still allowing me to recover from any invalid records.
Bottom line, if you need to save extra data in join table records, you have to process them one at a time. If not, use the method at the top for the best performance.
You can use The Join Model in this case.
I got a controller named Posts, a model called Content which is properly linked with other models such as Category and Location.
In my view for add 'Content' i successfully populate the multi select lists with categories and locations to pick to relate to the post. Saving it all works perfectly.
Now in edit/update mode, I can once again fill the multi selects with categories and locations, but it will not select the ones related to the current post. When looking in the database, there are categories and locations successfully realted to the current post.
This is what I got in my controller:
$this->data = $this->Content->read();
$this->set('locations',$this->Content->Location->find('list',array('fields' => array('id','location'))));
$this->set('categories',$this->Content->Category->find('list',array('fields' => array('id','category'))));
And this is what I got in my view:
echo $this->Form->input('Location', array('type' => 'select','multiple' => 'true','options' => $locations));
echo $this->Form->input('Category', array('type' => 'select','multiple' => 'true','options' => $categories));
What am i missing here? How do i get the already related locations and categories, select in the multi select lists?
(filling of non relationship data, will repopulate textfields etc just perfectly)
Grateful for any help!
Jason
instead of
$this->data = $this->Content->read()
try
$params['conditions'] = array(
'Content.id' => $id
);
$params['contain'] = array(
'Category',
'Location'
);
$this->data = $this->Content->find('first', $params);
You will need the Containable Behaviour for that
Use this:
echo $this->Form->input('Location', array(
'label' => 'Location',
'type' => 'select',
'options' => $LocationArray,
'selected'=> 12(Selected Value)
);