Can anyone suggest the best solution for creating a recently viewed items/pages logic using codeigniter? I'd prefer to use the codeigniter sessions rather than the standard $_SESSION if possible.
Also - to add to session but once I hit 10 items in the array to remove the oldest item in the array.
$recentlyViewed = $this->session->userdata('recentlyViewed');
if(!is_array($recentlyViewed)){
$recentlyViewed = array();
}
//change this to 10
if(sizeof($recentlyViewed)>3){
array_shift($recentlyViewed);
}
//here set your id or page or whatever
if(!in_array($data['id'],$recentlyViewed)){
array_push($recentlyViewed,$data['id']);
}
$this->session->set_userdata('recentlyViewed', $recentlyViewed);
$recentlyViewed = array_reverse($recentlyViewed);
//var_dump($recentlyViewed);
Now use a foreach on recentlyViewed with an or_where query
I have no idea if this approach will work for you, but you could dump that kind of data into a SQL database with a timestamp and then use the "Ascending"/"Descending" property of a SQL query in conjunction with a "limit(10)" property... it might be too much effort for what you are trying to accomplish, but you could also sync the query data with your CI session object? Dunno, just a thought :D
Related
First post on stackoverflow. I have been following this site for a long time, and usually find what im looking for. But this has me perplexed.
Let me set the stage. I am developing a web driven program. I have Wordpress, with the Divi theme from Elegant Themes. and I am using shortcodes to insert into the modules. I am a newbie (this says it all.)
Here is my problem. I have run a wpdb query that returns a single row of results.
$editresult = $wpdb->get_results ("SELECT `serialnumber`, `batttype`, `cells`, `fullvolts` FROM listbattery WHERE serialnumber = '$serialnumber'", ARRAY_A);
When I vardump this, i get the following.
array(1) {[0]=>array(4) {["serialnumber"]=>string(10)"battery #2" ["batttype"]=>string(5) "NiCad" ["cells"]=>string(1) "8"["fullvolts"]=>string(6)"12.125"}}
So with that being said, I know that the query is working fine. I know that I am receiving the information. What I can't for the life of me figure out, is how to turn the results from each column into individual variables, so that I can insert each variable randomly throughout my page.
I have tried about 8 different methods so far. I hope you guys can help! thanks!!!
You can loop through the result:
foreach($editresult as $result) {
$serialnumber = $result['serialnumber'];
$batttype = $result['batttype'];
$cells = $result['cells'];
$fullvolts = $result['fullvolts'];
}
If only one row is expected to be returned, you can do the following
$editresult = $wpdb->get_row("SELECT `serialnumber`, `batttype`, `cells`, `fullvolts` FROM listbattery WHERE serialnumber = '$serialnumber'", ARRAY_A);
Then you can access returned values like
$editresult['serialnumber']
$editresult['batttype']
$editresult['cells']
$editresult['fullvolts']
or if you change ARRAY_A to OBJECT, you will be able to access these values like so
$editresult->serialnumber
$editresult->batttype
$editresult->cells
$editresult->fullvolts
There is no need in get_results and foreach like shown in #nanodanger's answer if you always expect to get only 1 row
Is it possible to ask for all data in my database and make objects from it and save it into an array or something, so I just need to call the database once and afterwards I just use my local array? If yes, how is it done?
public function getAllProjects(){
$query="SELECT * FROM projects";
$result=mysql_query($query);
$num=mysql_numrows($result);
while ($row = mysql_fetch_object($result)) {
// save object into array
}
}
public function fetchRow($row){
include("Project.php");
$project = new Project();
$id=$row->id;
$project->setId($id);
$title=$row->title;
$project->setTitle($title);
$infos=$row->info;
$project->setInfo($infos);
$text=$row->text;
$project->setText($text);
$cate=$row->category;
$project->setCategory($cate);
return $project;
}
If I have for example this code. How do i store the objects correctly into an array, where I grab the data from? And why can't I make more than one object of type "Project"?
Let's ignore the fact that you will run out of memory.
If you have everything in an array you will no longer have the functionalities of a relational database.
Try a search over a multi megabytes, multi dimensional array in php and be prepared for a extended coffee break.
If you are thinking in doing something like that is because you feel that the database is slow... You should learn about data normalization and correct use of indexes then.
And no NoSQL is not the answer.
Sorry to pop your balloon.
Edited to add: What you CAN to is use memcache to store the final product of some expensive processes. Don't bother storing the result of trivial queries, the internal cache of mysql is very optimized for those.
You should use the $_SESSION vars in php, To use them, add a session_start() at the beginning of your code. Then you can set vars with $_SESSION['selectaname'] = yourvar
Nothing prevent you to make a sql query like "SELECT username FROM users WHERE id = 1" and then set a $_SESSION['user'] = $queryresult
Then you'll have this :
echo $_SESSION['user'];
"mylogin"
I have small problem.
I've coded a full website in php using CodeIgniter framework. One of my modules is search module, it contains text input with keyword and three select lists with filtering criterias.
That's ok, when I'm searching something - result's listing pagination is done via URL like that:
mysite.com/$keyword/$criteria1/$criteria2/$criteria3/$offset
works like a charm.
But when I'm entering into one of my images (it's image gallery) I want to have an option to go into NEXT and PREVIOUS image from my search results - the ones which I entered this image from.
I'm solving this case now in this way - I have session table called 'search_conditions' and I'm storing values of keyword and my three criterias there, but that's quite not comfortable, because why if someone opens second window and search something else there?
Then all of his searches in another windows or tabs are getting the same criteria - because with every new search, user overwrite the session value.
My next and previous functions:
public function next($count)
{
$search = $this->session->userdata('search_conditions'); //getting session table and overwriting it
$catid = isset($search['catid'])?$search['catid']:'0';
$brandid = isset($search['brandid'])?$search['brandid']:'0';
$prodid = isset($search['prodid'])?$search['prodid']:'0';
$keyword = isset($search['keyword'])?$search['keyword']:'';
$res = $this->search_model->main_search($keyword, $catid, $brandid, $prodid, $count, 1);
}
public function previous($count)
{
$search = $this->session->userdata('search_conditions');
$catid = isset($search['catid'])?$search['catid']:'0';
$brandid = isset($search['brandid'])?$search['brandid']:'0';
$prodid = isset($search['prodid'])?$search['prodid']:'0';
$keyword = isset($search['keyword'])?$search['keyword']:'';
$res = $this->search_model->main_search($keyword, $catid, $brandid, $prodid, $count-2, 1);
}
Can you recommend me some other, more comfortable solution, because this seems not to be good...
: )
Thank you!
Add an index to the $search_conditions variable:
$search_conditions[1]['catid']
$search_conditions[1]['brandid']
...
then refer to it with a controller's or config variable. This way you can allow one session to store multiple search conditions.
But I would recommend you drop storing the search condition in session. Instead, just pass it with the URI. Session data, in the case you describe, work as an intermediary; you don't need it. Use the Pagination Class and pass the search page number, not the direction (next or previous) to the URI.
Do not worry that the URI may look ugly - it only depends on what user searches for, and it's still friendly to share. Your only concern is if the GET string does not extend the limited length.
Pull the segments from the URI in your next() and previous() functions. Use the codeigniter URL helper. That should allow you to pass the different search criterion as variables to the next page, this would also remove your need to use the session.
OK, here's my dilemma:
I've read all over about how many guys want to be able to display a set of images from Flickr using PHPFlickr, but lament on how the API for PhotoSets does not put individual photo descriptions. Some have tried to set up their PHP so it will pull the description on each photo as the script assembles the gallery on the page. However, the method has shown how slow and inefficient it can be.
I caught an idea elsewhere of creating a string of comma separated values with the photo ID and the description. I'd store it on the MySQL database and then call upon it when I have my script assemble the gallery on the page. I'd use explode to create an array of the photo ID and its description, then call on that to fill in the gaps...thus less API calls and a faster page.
So in the back-end admin, I have a form where I set up the information for the gallery, and I hand a Set ID. The script would then go through and make this string of separated values ("|~|" as a separation). Here's what I came up with:
include("phpFlickr.php");
$f = new phpFlickr("< api >");
$descArray = "";
// This will create an Array of Photo ID from the Set ID.
// $setFeed is the set ID brought in from the form.
$photos = $f->photosets_getPhotos($setFeed);
foreach ($photos['photoset']['photo'] as $photo) {
$returnDesc = array();
$photoID = $photo['id'];
$rsp = $f->photos_getInfo($photoID);
foreach ($rsp as $pic) {
$returnDesc[] = htmlspecialchars($pic['description'], ENT_QUOTES);
}
$descArray .= $photoID."|~|".$returnDesc[0]."|~|";
}
The string $descArray would then be placed in the MySQL string that puts it into the database with other information brought in from the form.
My first question is was I correct in using a second foreach loop to get those descriptions? I tried following other examples all over the net that didn't use that, but they never worked. When I brought on the second foreach, then it worked. Should I have done something else?
I noticed the data returned would be two entries. One being the description, and the other just an "o"...hence the array $returnDesc so I could just get the one string I wanted and not the other.
Second question is if I made this too complicated or not. I like to try to learn to write cleaner/leaner code, and was looking for opinions.
Suggestions on improvement are welcome. Thank you in advance.
I'm not 100% sure as I've just browsed the source for phpFlickr, and looked the the Flickr API for the getInfo() call. But let me have a go anyway :)
First off, it looks like you shouldn't need that loop, like you mention. What does the output of print_r($rsp); look like? It could be that $rsp is an array with 1 element, in which case you could ditch the inner loop and replace it with something like $pic = $rsp[0]; $desc = $pic['description'];
Also, I'd create a new "description" column in your database table (that has the photo id as the primary key), and store the description in their on its own. Parsing db fields like that is a bit of a nightmare. Lastly, you might want to force htmlspecialchars to work in UTF8 mode, cause I don't think it does by default. From memory, the third parameter is the content encoding.
edit: doesn't phpFlickr have its own caching system? Why not use that and make the cache size massive? Seems like you might be re-inventing the wheel here... maybe all you need to do is increase the cache size, and make a getDescription function:
function getDescription ($id)
{
$rsp = $phpFlickr->photos_getInfo ($id);
$pic = $rsp[0];
return $pic['description'];
}
I have created a small search and filter form with a POST action in controller/index, which POSTs to itself the conditions and fields to paginate ($this->paginate($conditions)).
That is good for the first page, however on the subsequent pages the filter conditions are lost. Pagination passedArgs supports GET variables well.
Are there an un-complex ways to pass the POST conditions to the other paginated pages?
The method I have looked at is to pass the $conditions via the session, which isn't without complexity of assigning the session and unsetting the session on submitting the form again (more refinements to the filter criteria by the user).
The other method is passing the $conditions as serialized string with url_encode as a GET parameter.
Is there a good 'cake' way to do this more like passedArgs. Sessions and url_encode do not look like cake style.
Thanks
Is there an un complex way to pass the
post conditions to the other paginated
pages?
Nope.
Is there an good cake way to do this
more like passArgs, sessions and url
encode do not look like cake style.
There is only one way, no matter, cake or not cake.
Search must be done using GET method.
Parameters being passed via QUERY STRING.
So, make your search form with method="GET" and then use http_build_query() to assemble a query string and use it to make links to other pages.
Being a little curious, you can see an example right here on SO:
http://stackoverflow.com/questions/tagged?tagnames=php&page=5&sort=newest&pagesize=50
You can use passedArgs.
in the method controller :
if ( empty($this->passedArgs['search']) ){
$this->passedArgs['search'] = $this->data['YourModel']['search'];
}
if ( empty($this->data) ){
$this->data['YourModel']['search'] = $this->passedArgs['search'];
}
in your view :
$this->Paginator->options(array('url' => $this->passedArgs));
If it was me I would run with your idea of saving the stuff into the session. Then I would add a page dimension to the session, to store each page, thus allowing users to go back and forth with ease.
$this->Session->write('Search.page.1.params',$params);
$this->Session->write('Search.page.2.params',$params2);
In order to do it in a Cake way, you'd probably want to write your own Pagination helper, or plugin. Which you could then use more effectivly in your controllers as
$this->MyPages->paginate('MyModel');
I suppose, this functionality would also give you the option to allow your users to 'Save my search' if they wanted to, as you could dump the session params into a SavedSearch model or similar.
Don't forget to $this->Session->destroy() before starting a new search though!
You can also use the Post/Redirect/Get design pattern pattern to solve this, allowing users to bookmark URLs of searches (without them expiring as a session would) and keeping URLs looking friendly. For example:
function index($searchTerms = null) {
// post/redirect/get
if (isset($this->data['SearchForm'])) {
$this->redirect(array($this->data['SearchForm']['search_terms']));
}
// your normal code here.
}
The search form data POSTs to /controller/action but the user is redirected and instead GETs /controller/action/search+terms where the terms are passed into the action as a parameter (ie. $searchTerms).
If you simply change the form submission method to GET you will instead see something like: /controller/action?data[SearchForm][search_terms]=search+terms
Thanks Deizel for the POST / REDIRECT / GET pattern.
I implemented the GET method of posting data.
For pagination used this
$urlparams = $this->params['url'];unset($urlparams['url']);
$paginator->options(array('url' => array('?' => http_build_query($urlparams))));
We had multi checkboxes and the naming convention used where :
foreach ($checkboxes as $chbox ) {
// used variable variables to generate the data grid table based on selected fields
${'_field'.$chbox} = (isset($this->params['url']['displayfields'][$chbox])?$this->params['url']['displayfields'][$chbox]:1);
$options = array('label'=>$chbox,'type'=>'checkbox','value'=> ${'_field'.$chbox});
if ( ${'_field'.$chbox} ) $options['checked'] = 'checked';
echo $form->input('Filter.displayfields['.$chbox.']',$options);
In the post method the naming convention for the checkboxs would be Filter.displayfields.checkbox name
This helps in getting an array either in $this->data or $this->params['url']
There should be an persistent pagination plugin/component for cakePHP would make life much more easier and fun to develop with cakePHP.
Thanks all.