First time user of stack overflow so if I am posting incorrectly please let me know. So my website is developed in cakePHP 3.0. I currently have articles on the site and would like a way for users to move from article to article. I should mention I had this working with the get() method but because of the way the my controller is written I need to use a select query with a condition. I am able to create an article and not post it until a future date. So this code is supposed to ignore anything that hasn't been published yet to users don't see those articles.
Super newbie with PHP in general let alone the cakePHP MVC framework so bear with me :)
In my controller within the public view function I have this:
//get story id for next and previous buttons
$todays_date = date('Y-m-d H:i:s');
$this->loadModel('Story');
$storyID = $story->id;
$storyNextID = $storyID + 1;
$storyPreviousID = $storyID - 1;
$storyNext = $this->Story->find()->select('Story.id')->where(['Story.pub_date <' => $todays_date])->first();
$this->set('storyNext', $storyNext);
$storyPrevious = $this->Story->find()->select('Story.id')->where(['Story.pub_date <' => $todays_date])->first();
$this->set('storyPrevious', $storyPrevious);
And in my view.ctp I have this:
<div class="next row" align="center">
<?php
if(!empty($storyPrevious)) {
echo '<a class="btn btn-secondary" style="width:50%" href="' .BASE_URL. '/' .$storyPrevious->slug. '" role="button">Previous Story</a>';
}
if(!empty($storyNext)) {
echo '<a class="btn btn-secondary" style="width:50%" href="' .BASE_URL. '/' .$storyNext->slug. '" role="button">Next Story</a>';
}
?>
</div>
I feel like I'm super close since I am no longer getting any errors on my development site. But the link just sends me to the homepage of my website.
Thanks for the help!
there are probably many things that you can improve in your code**. But the main reason you are redirected to your main page is that you are just selecting the id of your Story but then in your view you need to echo the slug.
So when you are echoing $storyPrevious->slug PHP returns an empty string
So in the controller select the slug too
$this->Story->find()
->select(['id', 'slug')
->where(['Story.pub_date <' => $todays_date])
->first();
** such as using helpers in your view and using Cakephp naming conventions
Thanks for the input everyone. It was really helpful. I have no one to really get feedback from, until now. I took the above input and re coded my logic a bit. I am not sure why I was trying to use so many variables. I also found through some digging, someone who wrote something similar, they called it a neighbors table. I combined yours, mine and theirs to create this. Looks like its working on my dev site as of now and Ill update my answer if that changes when I bring it live.
In my StoryController:
$todays_date = date('Y-m-d H:i:s');
$this->loadModel('Story');
$id = $story->id;
$storyNext = $this->Story->find()
->select(['id', 'slug'])
->order(['id' => 'ASC'])
->where(['id >' => $id, 'Story.pub_date <' => $todays_date])
->first();
$this->set('storyNext', $storyNext);
$storyPrevious = $this->Story->find()
->select(['id', 'slug'])
->order(['id' => 'DESC'])
->where(['id <' => $id, 'Story.pub_date <' => $todays_date])
->first();
$this->set('storyPrevious', $storyPrevious);
And in my view.ctp:
<?php
if(!empty($storyPrevious)) {
echo 'Previous Story';
}
if(!empty($storyNext)) {
echo 'Next Story';
}
?>
Related
tl;dr; Trying to link the 'save and return' button when editing/deleting a course to my local plugins index.php instead of moodles default redirect for these features, moodle allready has a returnTo query parameter so i was thinking if that could be used somehow.
Hey
I am creating a local plugin that has a administration panel, where you can access CRUD on all courses in the system as seen in the picture below:
The problem now is that whenever I click edit, I get into the course edit page of course, but when I return from there I click "save and return" I would like to get back to my own admin page instead of the course page or category manage page.
The code I have right now looks like this:
//edit
$edit_course_moodle_url = new moodle_url('/course/edit.php', array('id' => $course->id, 'returnto' => 'local/adminpanel/index.php'));
$edit_course_url = $edit_course_moodle_url->get_path() . '?id=' . $edit_course_moodle_url->get_param('id') . '&returnto=' . $edit_course_moodle_url->get_param('returnto');
//delete
$delete_course_moodle_url = new moodle_url('/course/delete.php', array('id' => $course->id, 'returnto' => 'local/adminpanel/index.php'));
$delete_course_url = $delete_course_moodle_url->get_path() . '?id=' . $delete_course_moodle_url->get_param('id') . '&returnto=' . $delete_course_moodle_url->get_param('returnto');
As you can see I use the "returnto" query parameter, normally moodle has a "catmanage" as "returnto" that returns you to the category management page, where moodle has its own CRUD for categories and courses. So my question is, can I create my own alias for a link and use it like moodle uses the catmanage link, but for my admin page instead.
Thanks a lot ! :)
EDIT:
Change code to the following:
if (empty($CFG->loginhttps)) {
$securewwwroot = $CFG->wwwroot;
} else {
$securewwwroot = str_replace('http:','https:',$CFG->wwwroot);
}
$returnurl = new moodle_url($securewwwroot . '/local/adminpanel/index.php');
$edit_course_moodle_url = new moodle_url($securewwwroot . '/course/edit.php', array(
'id' => $course->id,
'sesskey' => sesskey(),
'returnto' => 'url',
'returnurl' => $returnurl->out(false))
);
$edit_course_url = $edit_course_moodle_url->out();
But it looks like moodle took away the button from edit course called "save and return" now it only has "save and display" or "Cancel" , both of which brings me back to the course, sad times :(
According to the code I can see in course/edit.php, you should use the following URL arguments:
returnto: 'url'
returnurl: The url
sesskey: sesskey()
In code that gives us:
$returnurl = new moodle_url('/local/plugin/page.php');
$editurl = new moodle_url('/course/edit.php', array(
'id' => 2,
'sesskey' => sesskey(),
'returnto' => 'url',
'returnurl' => $url->out(false)
));
echo $editurl->out();
The page course/delete.php does not seem to support those arguments. But it's probably easier for your plugin to delete the course by itself, it's as simple as calling delete_course($courseid);.
I'm stuck trying to get joomla full article to render in a tab. The tab is working. I just can´t render the article content. This is where I am now.
This is helper.php
public static function getArticle($articleId)
{
JModelLegacy::addIncludePath(JPATH_SITE.'/components/com_content/models', 'ContentModel');
$model = JModelLegacy::getInstance('Article', 'ContentModel', array('ignore_request' => true));
$article = $model->getItem((int) $articleId);
$fullarticle = $item->fulltext;
$itemsHtml = '<div>'. $fullarticle .'</div>';
return $itemsHtml;
}
And this is in default.php
...code...
else if ($list_of_tabs['use'][$i][0] == 'article'){
echo '<div class="tab-pane '.$active.'" id="'.$i.$rid.'">'.
modJpTabsHelper::getArticle($list_of_tabs['article'][$i], $params) .
'</div>';
}
...code...
If you need more info. Don't hesitate to ask.
What are you trying to achieve: to write your own Joomla! extension which displays articles in a tab or you just need to display your J! articles in a tab?
If it's a latter, then there are already some nice and free (as in a "free bear") add-ons written just for that.
You are trying to use the model part of an MVC as a thing to render.
You should use the MVC system - using a controller to gathering the model and the view, and then you can render the model with the attached view, via the controller.
So you use something like (I've not tested this - you will need to correct it).
$filter=array('id' => $i->query['id']);
$options=array('filter_fields' => $filter,'ignore_request' => true);
$ctl = new ContentModelController();
$view = $ctl->getView( 'Article');
$model = $ctl->getModel( 'Article','',$options);
you may need to set params from application, eg..
$model->setState('params', JApplication::getInstance('site')->getParams());
then continue
$view->setModel( $model, true );
$result = $view->display();
Make sure that you have JLoader::import'ed any classes/classpaths - j. tends to fail silently if they aren't found, which can be difficult to trace.
Sorry, it's only a partial solution - but hopefully it may put you on the right track.
Here was the problem:
$fullarticle = $item->fulltext;
Article object from model was in variable $article not $item:
$article = $model->getItem((int) $articleId);
So getting property fulltext from article object should be:
$fullarticle = $article->fulltext;
Ok i have been looking for a while now... and i wasnt able to find nothing related to jquery and cakephp when loading content to a div using the helper $this->Js->link... so i decided to post my question here in this awesome site... my first question and its so silly (i guess).
So... mechanics works fine, i mean.. it loads the content into a div called "algo" but now i try to add some effects (fadein) and im not being able to find the correct syntaxys for this! im brand new with cake... just 1 month old using it.
How do i add "fadeIn" effect when showing this damn div? i have tried lots of things but so far nothing makes the div load content with fadein effect whatsoever...
echo $this->Js->link('Categoria 1', array('controller' => 'Categories', 'action' => 'categorias1'), array('update' => '#algo'));
this perfectly loads a bunch of pictures that i have on category 1 inside the div that im asking... what should i do to add fadeIn effect? i have added some crazy things to see if they work but... nope... no luck
i have even tried this crazy one:
echo $this->Js->link('Categoria 1', array('controller' => 'Categories', 'action' => 'categorias1'), array('update' => '#algo', array('effect' =>array('fadeIn', array('speed' => 'slow'), true))));
any help will be apreciated! nobody shows examples of divs with cakephp.. or at least i wasnt able to find one that suits my needs!
great site by the way! it helped me a lot all this years!
i finally manage myself to accomplish what i was trying to do and i want to share with you guys what i did:
echo $this->Js->link('categoria 1', array('controller' => 'Categories', 'action' => 'categorias1'),array('update' => '#categorias', 'evalscripts' => true, 'before' => $this->Js->get('#algo,#categorias2')->effect('fadeOut', array('buffer' => false)), 'complete' => $this->Js->get('#categorias')->effect('fadeIn', array('buffer' => false))));
This huge piece of code is doing what i was expecting to, i also have added some editing to my jquery helper in order to pass them more than one div so i can have them all refreshed at the same time.
if you guys want to hack your helper here is the code:
cake/libs/view/helpers/jquery_engine.php
find this line:
$success .= $this-jQueryObject . '("' . $options['update'] . '").html(data);';
and have it replaced with:
if(is_array($options['update'])){
$success .= 'var temp = ' . $this->jQueryObject . '(" <div/>").html(data);';
foreach($options['update'] as $divId){
$success .= $this->jQueryObject . '("' . $divId . '").html(' . $this->jQueryObject . '("' . $divId . '", temp).html());';
}
} else {
$success .= $this->jQueryObject . '("' . $options['update'] . '").html(data);'; //linea que ya estaba
}
//termina agregado
As suggested by Dunhamzzz, I write all my jQuery by hand and never use the helpers. There doesn't seem to be any point tbh.
One useful tip, pass the base URL and any other useful cake variables into your page as a javascript variable. Add this to your layout:
<?php
$baseUrl = Router::url('/');
echo $this->Html->scriptBlock(<<<EOJS
var baseUrl = '{$baseUrl}';
EOJS
); ?>
Scenario:
3 tables:
restaurants
cuisines
features
2 join tables:
cuisines_restaurants
features_restaurants
Question:
What is the best way to get data for a single restaurant from my controller to the view which includes not only the restaurant data, but also the cuisines and features that it has.
I have it working with this:
$restaurant = $this->Restaurant->find('all', array('conditions' => array('Restaurant.id' => $id)));
$this->set('restaurant', $restaurant);
And I'm calling it in the view like this:
echo "<span class='label'>Name:</span> " . $restaurant[0]['Restaurant']['name'] . "<br />";
echo "<span class='label'>Cuisine:</span> ";
$cuisineList = "";
foreach($restaurant[0]['Cuisine'] as $cuisine) {
$cuisineList .= $cuisine['name'] . ", ";
}
echo substr($cuisineList,0,-2) . "<br />";
(and repeat for Features)
But this seems overkill, since in all the Cake tutorials I see, the view method in the controller just has:
$this->set('restaurant', $this->Restaurant->read(null, $id));
Then they call it like this:
echo $restaurant['Restaurant']['name'];
...etc
Again - it IS working - I just want to know if there's a better way - the way I'm currently doing it seems sloppy compared to all the other slick things Cake does for me! :)
Your working code uses Model::find('all'), but when you want to retrieve just one Restaurant's data, you want to use Model::find('first'). I think you'll find if you change the first parameter of your call from 'all' to 'first', you'll get the data you want in the format you want.
Somewhat tangentially, there is quite literally no difference between the data returned by the two following calls:
$data = $this->Restaurant->find('first', array(
'conditions'=>array('Restaurant.id'=>$id)
));
or
$data = $this->Restaurant->read(null,$id);
Model::read is essentially a wrapper for Model::find('first'), though it also sets the model's internal state a bit (setting the Model::id and Model::data properties before returning data retrieved with Model::find('first')).
I’m trying to implement a simple search into an application, but not sure of the best way to handle this. My database contains a Listings object which includes City field. I want to create a search form where the user inputs a city into a text field and gets all of the Listings for that city on the next page. I don’t want to perform a full-text search, just the query on that City field.
Also, on the results page, I’d like to store the query in POST and can’t figure out the best way to do this.
What is the best way to approach this in the controller?
Well your view would look something like this
$this->Form->Create('Listing', array('action'=>'search'));
$this->Form->input('city', array('default'=>$city));
$this->Form->end();
if (isset($listings)) {
//code to display listings
}
This view would create the correct form. And your controller needs to get that value
function search() {
$city = '';
if (!empty($this->data)) {
$city = $this->data['Listing']['city'];
$opts = array(
'conditions' => array('Listing.city' => $city)
);
$listings = $this->Listing->find('all', $opts);
$this->set('listings', $listings);
}
$this->set('city', $city); // so the keyword is saved. Can also get it via $this->data
}
This code should give you an idea on how to do this.
This is a great tutorial with a CakePHP search plugin tutorial. You can download the full working code as well from github (w/ MySQL dump).
View:
<?php echo $this->Form->create()
echo $this->Form->input('search');
?>
<input name="data[Product][word]" />
controller:
<?php
$result = $this->Product->find('all',array(
'conditions'=>array(
'OR'=>array(
array('name LIKE'=>'%'.$word.'%'),
array('description LIKE'=>'%'.$word.'%')))));
$this->set(compact('result'));
?>