I want to add a feature to an existing website thats built using the Zend Framework. One of the problems with this website is that it refreshes the page often at different positions on the web page. What I would like to do is use a built-in Zend framework function to keep the same position in a web page after it has been refreshed.
An example would be: A user clicks at the bottom of the page, the same page is reloaded but it does not reload at the top of the page, it stays where the user last clicked.
Is there such a thing?
Thank you
You will have to use a combination of Javascript (in the frontend) and Zend Framework (in the backend) to achieve this.
This is assuming you are using user cookies/sessions.
Create an event handler to detect mouse-clicks using Javascript anywhere on the page. In the event handler, use the event object to get the x and y-coordinates of the mouse position. (Mouse click event coordinates)
Set up an endpoint in your Zend Framework that will accept mouse coordinates for the user. For example: http://localhost/user/updateCoordinates?x=12&y=100
On mouse click, make your event handler perform an AJAX query sending the coordinates to the endpoint you set up in #2.
In Zend Framework, store these coordinates in the user session/cookie (so you can track it later)
On page load, get the value from the session and output Javascript code to automatically scroll to that coordinate. Also, remove the x and y-coordinate from the cookie since it has already been used.
You could use some javascript to record the scroll position of the window right before a refresh, and just save it to a cookie.
Then, when the next page loads, check for the cookie, scroll to its position, and delete it. This won't work well if the webpage has dynamically sized elements(example: an expanding accordion menu).
Personally though, I would try to avoid this. Every now and then I visit some website that likes to do stuff with my scroll bar and try to help me. Way too often they get it wrong and the webpage becomes unusable. Maybe you can just dynamically update the page(ajax?) instead of doing a real reload.
u can use existing components of ZF and combine them in some new plugin:
1) new ZF plugin saved in ZF structure in my case: /library/My/Controller/Plugin/ActionHistory.php
final class My_Controller_Plugin_ActionHistory extends Zend_Controller_Plugin_Abstract
{
/** #var bool flag indicating whether current action has been already logged */
private $dispatched = false;
/**
* #param Zend_Controller_Request_Abstract $request
* #return void
*/
public function pushStack(Zend_Controller_Request_Abstract $request) {
$storage = $this->getStorage();
$storage->stack[] = $request;
// limit the depth of the stack
if (count($storage->stack) > $this->getMaxDepth()) {
array_shift($storage->stack);
}
// mark current action as dispatched (influences getBacklink())
$this->dispatched = true;
}
public function popStack() {
$storage = $this->getStorage();
return array_pop($storage->stack);
}
/**
* Returns request to previous action (not current).
*
* #return Zend_Controller_Request_Abstract|null
*/
public function getBacklink() {
$storage = $this->getStorage();
$depth = count($storage->stack);
// points to top of the stack
$backlinkIndex = $depth - 1;
if ($this->dispatched) {
// current action has been already logged, "backlink" is second from the top
--$backlinkIndex;
}
return ($backlinkIndex >= 0 ? $storage->stack[$backlinkIndex] : null);
}
/**
* Returns stack with performed actions
* #return array
*/
public function getStack() {
return $this->getStorage()->stack;
}
/**
* #return Zend_Session_Namespace
*/
private function getStorage() {
static $storage = null;
if ($storage === null) {
$storage = new Zend_Session_Namespace(get_class($this), true);
if (!is_array($storage->stack)) {
// initialize stack if needed
$storage->stack = array();
}
}
return $storage;
}
/**
* Returns maximal depth of the action history
* #return int
*/
private function getMaxDepth() {
return 3;
}
}
2) Place somewhere this code to pushing history in stack. You can use history only e.g. with cooperation with logging to application or you can save all history. It depends on you:
// this code is example of usage in another ZF controller plugin class
$actionHistory = Zend_Controller_Action_HelperBroker::getStaticHelper("ActionHistory");
if ($actionHistory) {
// $this => instance of Zend_Controller_Plugin_Abstract
$actionHistory->pushStack($this->getRequest());
}
3) Then u can use this plugin in some controller where you want to handle action history like that:
// check if there is an backlink stored in actionStack, if yes than use it
if (($actionHistory = $this->getHelper('actionHistory'))) {
$request = $actionHistory->getBacklink();
if ($request) {
$actionHistory->popStack();
// use any of your redirect classes or simle redirector helper
// right path to previous site is accesible by $request->getUserParams()
$this->redirect($request->getUserParams());
}
}
Thats it:) Hope you can modify what you want but the theory and benefits of this solution are clear enought...
Related
I'm very new to Laravel and I was given a Laravel project, where I need to add some new features. The person, who has previously worked on that project hadn't left even a single comment in the code and now I must make my own scenarios about the features.
I have a controller, defined with some functions (dashboard, show_project, save_project etc.) and in one of my function, I need to use the result of calling other function.
In the concrete example, the call is made from "http://127.0.0.1:8000/username/project_slug" - there is a button "Save" and post function, called on onClick event. The function, whose output I need is normally called on "http://127.0.0.1:8000/username/project_slug/svg", which returns a view.
For better understanding, there's an example of the flow:
The user wants to save his/her project (an UML diagram) but in order to have a thumbnail, a function which generates a view (SVG format) will be called and the idea is, to take the HTML content of the page, which is on "http://127.0.0.1:8000/username/project_slug/svg" and to pass it to another API in order an image to be generated.
So far, I tried with cURL, file_get_contents, file_get_html, render methods but when I return the output, the server just keeps waiting and shows no error messages.
//The both functions are in ProjectController.php
/**
* A function, for saving the json file, where the whole of the diagram
* components are described. From the frontend we receive the project_id and
* the project_data(the json content).
*/
public function save_project(Request $request) {
$input = $request->only(['project_id', 'project_data']);
/*
Here we need to call the other function, to render the HTML content
and to pass it to the other API. Then we save the result with the
other information.
*/
/*
What I've tried?
$new_link = 'http://' . $_SERVER['HTTP_HOST'] . "/$username"
."/$project_slug" . "/svg";
$contents = file_get_contents($new_link);
return $contents;
*/
//In the same way with cURL.
$project = Project::where('user_id',session('userid'))
->where('id',$input['project_id'])->first();
$project->project_data = json_encode($input['project_data']);
if($project->save()) {
return ["status"=>"saved"];
}
else {
return ["status"=>"error"];
}
}
/**
* A function, which takes the the Json content (project_data) from the
* database and passes it to the view, where the Json is transformed in HTML
* tags.
*/
public function generate_svg(Request $request,$username,$project_slug) {
if(session('username')!=$username) {
return redirect("/");
}
$userid = session('userid');
$project = Project::where([
'user_id' => $userid,
'slug' => $project_slug,
])->first();
if(!is_null($project)) {
return view('svg',compact('project'));
}
}
I've read about some possible ways, including Guzzle request but maybe I haven't understood correctly the idea:
If I need to make a Guzzle request from my controller to the other function inside my controller, do I need an API configuration?
What I mean? Example:
Before saving the project, the user is on this URL address "http://127.0.0.1:8000/hristo/16test". Inside the controller, I have in session variables the token, the username(hristo) and i can get the project_name(16test) from the URL but after passing this URL to the generate_svg function, there is no indication of error or success.
So I'm missing some kind of token information?
If you just need the response of the other function you can just use
$response = $this->generate_svg($request, $username, $project_slug);
If you'll need to use this function from a different controller you can use this
app('App\Http\Controllers\UsernameController')->generate_svg($request, $username, $project_slug);
Is it possible to make sessions per Browser tabs?
As example a user opened 2 tabs in his browser:
Tab 1 and Tab 2
In Tab 1 he has a session:
$_SESSION['xxx'] = 'lorem';
And in Tab 2 the session is:
$_SESSION['xxx'] = 'ipsum';
Now on refresh i need to get the current session in the active tab. For example if the user refreshes Tab 2 i need to get the $_SESSION['xxx'] for tab 2 on load which is 'ipsum'. But $_SESSION['xxx'] shouldn't change on Tab 1.
Is there any option to save sessions per tab. If not what are other options to handle this issue?
Thanks for any help!
PHP stores session IDs in cookies and cookies are per client (browser), not tab. So there is no simple and easy way to do this. There are ways of doing this by creating your own session handlers, but they are more hacks than solutions and as such come with their own risks and complexity. For whatever reason you may need this, I am quite sure that there is a better architectural solution than session splitting.
I've been scouring the web for answers to this problem and have not yet found a satisfying solution. I finally pulled together something in JavaScript that sort of works.
//generate a random ID, doesn't really matter how
if(!sessionStorage.tab) {
var max = 99999999;
var min = 10000000;
sessionStorage.tab = Math.floor(Math.random() * (max - min + 1) + min);
}
//set tab_id cookie before leaving page
window.addEventListener('beforeunload', function() {
document.cookie = 'tab_id=' + sessionStorage.tab;
});
HTML5 sessionStorage is not shared between tabs, so we can store a unique tab ID there. Listening for the beforeunload event on the window tells us that we're leaving (and loading some other page). By setting a cookie before we leave, we include our value in the new request without any extra URL manipulation. To distinguish between tabs you just have to check $_COOKIE['tab_id'] on the server and store sessions values appropriately.
Do note that Firefox behaves strangely, in that triggering window.open() will create a window that shares sessionStorage with its parent, giving you two tabs with the same ID. Manually opening a blank tab and then navigating to the target URL will give you separate storage. Chrome works for me in all of my tests so far.
I realize this is probably not the right answer, or even a "good" answer, but it is an answer.
Here's my solution; we're using this to allow multiple app views open per client.
POST to get data:
'doStuff=getData&model=GTD&sn=6789&type=random&date=18-Dec-2018'
the controller then gets the data from the tables, build the object for the device, stores it to the session object and stores it in the variable as such. It generates a per tab guid so that the user can compare the same instrument with a different view in the UI.
$_session[$model][$sn][$type][$guid][$key];
the guid of course is also sent back in the data object so that the tab knows how to recall that data later on.
When the user wants to print the results to a file (pdf, etc) it sends a post with the relevant data in a POST.
'doStuff=saveFile&model=GTD&sn=6789&type=random&calDate=18-Dec-2018&guid=randomKey'
The controller then will pass that to the storage to retrieve.
Session class file example:
<?php
class Session {
public $fieldKey1;
public $fieldKey2;
public function GetStorage($model, $sn, $type, $guid, $key) {
return $_SESSION[$model][$sn][$type][$guid][$key];
}
}
?>
the controller file:
<?php
require_once('session.php');
global $session; //from session class file
switch($_POST['doStuff']) {
case 'saveFile':
$session->GetStorage($_POST['model'], $_POST['sn'], $_POST['type'], $_POST['guid'], $key);
break;
}
?>
This allows the user to have several views of the same data, without overwriting the data-set from each tab. If you don't need as much data granularity per tab, you can of course simplify the number of keys for your $_SESSION variable.
I've been taking a shot to make a web app with this feature.
It have not been matured and have constraints and flows, like having to transmit the session id in the url if your javascript make a post to an external php code depending on it, but it's functional and suits my needs (for now).
I am thinking of a more secure solution, so feel free to adapt it to your needs and give me your suggestions.
<?php
/**
* Split $_SESSION by browser Tab emulator.
* methods exemples are used whith :
* $session = new SessionSplit();
* as SessionSplit may reload the page, it has to be used on top of the code.
*
*/
class SessionSplit{
public $id;
private $gprefix="session_slice_";
private $prefix="";
private $witness="";
function SessionSplit($witness='witness'){
if(session_status()===PHP_SESSION_NONE){
session_start();
}
$this->witness=$witness;
if($this->get_id()){
$this->prefix=$this->gprefix.$this->id;
//set a witness to 'register' the session id
$this->set($this->witness,'true');
}else{
// force the session id in the url to not interfere with form validation
$actual_link = "http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
$new_link = $actual_link.(strpos($actual_link,'?')===false?'?':'&').
'session_id='.$this->id;
header('Location: '.$new_link);
}
}
private function get_id(){
if(isset($_GET['session_id'])){
$this->id=$_GET['session_id'];
return true;
}else{
$this->new_id();
return false;
}
}
private function new_id(){
$id=0;
while(isset($_SESSION[$this->gprefix.$id.'.'.$this->witness])){$id++;}
$this->id=$id;
}
// ----------- publics
public function clearAll(){
foreach($_SESSION as $key=>$value){
if(strpos($key,$this->prefix.'.')===0){
unset($_SESSION[$key]);
}
}
}
/**
* $is_user=$session->has('user');
* equivalent to
* $is_user=isset($_SESSION['user']);
* #param {string} $local_id
* #return {boolean}
*/
public function has($local_id){
return isset($_SESSION[$this->prefix.'.'.$local_id]);
}
/**
*
* $session->clear('user');
* equivalent to
* unset($_SESSION['user']);
* #param {string} $local_id
*/
public function clear($local_id){
unset($_SESSION[$this->prefix.'.'.$local_id]);
}
/**
* $user=$session->get('user');
* equivalent to
* $user=$_SESSION['user'];
* #param {string} $local_id
* #return {mixed}
*/
public function get($local_id){
if (isset($_SESSION[$this->prefix.'.'.$local_id])) {
return $_SESSION[$this->prefix.'.'.$local_id];
}else return null;
}
/**
* $session->set('user',$user);
* equivalent to
* $_SESSION['user']=$user;
* #param {string} $local_id
* #param {mixed} $value
*/
public function set($local_id,$value){
$_SESSION[$this->prefix.'.'.$local_id]=$value;
}
};
?>
Is it possible to make sessions per Browser tabs?
As example a user opened 2 tabs in his browser:
Tab 1 and Tab 2
In Tab 1 he has a session:
$_SESSION['xxx'] = 'lorem';
And in Tab 2 the session is:
$_SESSION['xxx'] = 'ipsum';
Now on refresh i need to get the current session in the active tab. For example if the user refreshes Tab 2 i need to get the $_SESSION['xxx'] for tab 2 on load which is 'ipsum'. But $_SESSION['xxx'] shouldn't change on Tab 1.
Is there any option to save sessions per tab. If not what are other options to handle this issue?
Thanks for any help!
PHP stores session IDs in cookies and cookies are per client (browser), not tab. So there is no simple and easy way to do this. There are ways of doing this by creating your own session handlers, but they are more hacks than solutions and as such come with their own risks and complexity. For whatever reason you may need this, I am quite sure that there is a better architectural solution than session splitting.
I've been scouring the web for answers to this problem and have not yet found a satisfying solution. I finally pulled together something in JavaScript that sort of works.
//generate a random ID, doesn't really matter how
if(!sessionStorage.tab) {
var max = 99999999;
var min = 10000000;
sessionStorage.tab = Math.floor(Math.random() * (max - min + 1) + min);
}
//set tab_id cookie before leaving page
window.addEventListener('beforeunload', function() {
document.cookie = 'tab_id=' + sessionStorage.tab;
});
HTML5 sessionStorage is not shared between tabs, so we can store a unique tab ID there. Listening for the beforeunload event on the window tells us that we're leaving (and loading some other page). By setting a cookie before we leave, we include our value in the new request without any extra URL manipulation. To distinguish between tabs you just have to check $_COOKIE['tab_id'] on the server and store sessions values appropriately.
Do note that Firefox behaves strangely, in that triggering window.open() will create a window that shares sessionStorage with its parent, giving you two tabs with the same ID. Manually opening a blank tab and then navigating to the target URL will give you separate storage. Chrome works for me in all of my tests so far.
I realize this is probably not the right answer, or even a "good" answer, but it is an answer.
Here's my solution; we're using this to allow multiple app views open per client.
POST to get data:
'doStuff=getData&model=GTD&sn=6789&type=random&date=18-Dec-2018'
the controller then gets the data from the tables, build the object for the device, stores it to the session object and stores it in the variable as such. It generates a per tab guid so that the user can compare the same instrument with a different view in the UI.
$_session[$model][$sn][$type][$guid][$key];
the guid of course is also sent back in the data object so that the tab knows how to recall that data later on.
When the user wants to print the results to a file (pdf, etc) it sends a post with the relevant data in a POST.
'doStuff=saveFile&model=GTD&sn=6789&type=random&calDate=18-Dec-2018&guid=randomKey'
The controller then will pass that to the storage to retrieve.
Session class file example:
<?php
class Session {
public $fieldKey1;
public $fieldKey2;
public function GetStorage($model, $sn, $type, $guid, $key) {
return $_SESSION[$model][$sn][$type][$guid][$key];
}
}
?>
the controller file:
<?php
require_once('session.php');
global $session; //from session class file
switch($_POST['doStuff']) {
case 'saveFile':
$session->GetStorage($_POST['model'], $_POST['sn'], $_POST['type'], $_POST['guid'], $key);
break;
}
?>
This allows the user to have several views of the same data, without overwriting the data-set from each tab. If you don't need as much data granularity per tab, you can of course simplify the number of keys for your $_SESSION variable.
I've been taking a shot to make a web app with this feature.
It have not been matured and have constraints and flows, like having to transmit the session id in the url if your javascript make a post to an external php code depending on it, but it's functional and suits my needs (for now).
I am thinking of a more secure solution, so feel free to adapt it to your needs and give me your suggestions.
<?php
/**
* Split $_SESSION by browser Tab emulator.
* methods exemples are used whith :
* $session = new SessionSplit();
* as SessionSplit may reload the page, it has to be used on top of the code.
*
*/
class SessionSplit{
public $id;
private $gprefix="session_slice_";
private $prefix="";
private $witness="";
function SessionSplit($witness='witness'){
if(session_status()===PHP_SESSION_NONE){
session_start();
}
$this->witness=$witness;
if($this->get_id()){
$this->prefix=$this->gprefix.$this->id;
//set a witness to 'register' the session id
$this->set($this->witness,'true');
}else{
// force the session id in the url to not interfere with form validation
$actual_link = "http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
$new_link = $actual_link.(strpos($actual_link,'?')===false?'?':'&').
'session_id='.$this->id;
header('Location: '.$new_link);
}
}
private function get_id(){
if(isset($_GET['session_id'])){
$this->id=$_GET['session_id'];
return true;
}else{
$this->new_id();
return false;
}
}
private function new_id(){
$id=0;
while(isset($_SESSION[$this->gprefix.$id.'.'.$this->witness])){$id++;}
$this->id=$id;
}
// ----------- publics
public function clearAll(){
foreach($_SESSION as $key=>$value){
if(strpos($key,$this->prefix.'.')===0){
unset($_SESSION[$key]);
}
}
}
/**
* $is_user=$session->has('user');
* equivalent to
* $is_user=isset($_SESSION['user']);
* #param {string} $local_id
* #return {boolean}
*/
public function has($local_id){
return isset($_SESSION[$this->prefix.'.'.$local_id]);
}
/**
*
* $session->clear('user');
* equivalent to
* unset($_SESSION['user']);
* #param {string} $local_id
*/
public function clear($local_id){
unset($_SESSION[$this->prefix.'.'.$local_id]);
}
/**
* $user=$session->get('user');
* equivalent to
* $user=$_SESSION['user'];
* #param {string} $local_id
* #return {mixed}
*/
public function get($local_id){
if (isset($_SESSION[$this->prefix.'.'.$local_id])) {
return $_SESSION[$this->prefix.'.'.$local_id];
}else return null;
}
/**
* $session->set('user',$user);
* equivalent to
* $_SESSION['user']=$user;
* #param {string} $local_id
* #param {mixed} $value
*/
public function set($local_id,$value){
$_SESSION[$this->prefix.'.'.$local_id]=$value;
}
};
?>
Does Phalcon support content negotiation out-of-the-box or is there some easy-to-implement solution? I'm scouring the 'nets and not seeing it.
Thanks!
Short answer is no and thank god for that, or we'd have another 100 bugs for a non-major component :)
You can easily plug an existing library, like Negotiation, into DI and use it later globally throughout the app.
$di->setShared('negotiator', function(){
return new \Negotiation\Negotiator();
});
$bestHeader = $di->getShared('negotiator')->getBest('en; q=0.1, fr; q=0.4, fu; q=0.9, de; q=0.2');
Keep in mind that with the default server config (.htaccess / Nginx) from examples static files will be served as is, without interception by Phalcon. So, to server files from the server it would be best to create a separate controller / action to handle that rather than making all request go through your app.
Edit:
If it's simply about enabling your app sending either xml or json based on the common distinction (header, param, method), then you can easily accomplish it without external frameworks. There are many strategies, the simplest would be to intercept Dispatcher::dispatch(), decide in there what content to return and configure the view and response accordingly – Phalcon will do the rest.
/**
* All controllers must extend the base class and actions must set result to `$this->responseContent` property,
* that value will be later converted to the appropriate form.
*/
abstract class AbstractController extends \Phalcon\Mvc\Controller
{
/**
* Response content in a common format that can be converted to either json or xml.
*
* #var array
*/
public $responseContent;
}
/**
* New dispatcher checks if the last dispatched controller has `$responseContent` property it will convert it
* to the right format, disable the view and direcly return the result.
*/
class Dispatcher extends \Phalcon\Mvc\Dispatcher
{
/**
* #inheritdoc
*/
public function dispatch()
{
$result = parent::dispatch();
$headerAccept = $this->request->getHeader('Accept');
$headerContentType = $this->request->getHeader('Content-Type');
$lastController = $this->getLastController();
// If controller is an "alien" or the response content is not provided, just return the original result.
if (!$lastController instanceof AbstractController || !isset($lastController->responseContent)) {
return $result;
}
// Decide what content format has been requested and prepare the response.
if ($headerAccept === 'application/json' && $headerContentType === 'application/json') {
$response = json_encode($lastController->responseContent);
$contentType = 'application/json';
} else {
$response = your_xml_convertion_method_call($lastController->responseContent);
$contentType = 'application/xml';
}
// Disable the view – we are not rendering anything (unless you've already disabled it globally).
$view->disable();
// Prepare the actual response object.
$response = $lastController->response
->setContent($response)
->setContentType($contentType);
// The returned value must also be set explicitly.
$this->setReturnedValue($response);
return $result;
}
}
// In your configuration you must insert the right dispatcher into DI.
$di->setShared('dispatcher', function(){
return new \The\Above\Dispatcher();
});
Just thought that you can probably achieve the same using dispatch loop events. The solution in theory might look more elegant but I never attempted this, so you might want to try this yourself.
I hope I worded the title accurately enough but I typically use Java and don't have much experience in Web Development/PHP/CodeIgniter. I have a difficult time understanding the life cycle of a script as I found out trying to implement a certain feature to a website I am developing (as a means of learning how to). I'll first describe the feature I tried implementing and then the problem I ran into that made me question my fundamental understanding of how scripts work since I'm used to typical OOP.
Ok so here goes...
I have a webpage that has 2 basic tasks a user can do, create and delete an entry. What I attempted to implement was a way to time a user how long it takes them to complete a certain task. The way I did this was have a homepage where there would be a list of tasks a user to choose from (in this case 2, create and delete). A user would click a task which would link to the 'true' homepage where the user then would be expected to complete the task. My script looks like this:
<?php
class Site extends CI_Controller {
var $task1;
var $tasks = array(
"task1" => NULL,
"date1" => 0,
"date2" => 0,
"diff" => 0);
function __construct()
{
parent::__construct();
include 'timetask.php';
$this->task1 = new TimeTask("create");
}
function index()
{
$this->tasks['task1'] = $this->task1->getTask();
$this->tasks['diff'] = $this->task1->getTimeDiff();
if($this->tasks['diff'] == NULL)
{
$this->tasks['diff'] = 0;
}
$this->load->view('usability_test', $this->tasks);
}
function origIndex()
{
$this->task1->setDate1(new DateTime());
$this->tasks['date1'] = $this->task1->getDate1()->getTimestamp();
$data = array();
if($q = $this->site_model->get_records())
{
$data['records'] = $q;
}
$this->load->view('options_view', $data);
}
function create()
{
$this->task1->setDate2(new DateTime());
$this->tasks['date2'] = $this->task1->getDate2()->getTimestamp();
$data = array(
'author' => $this->input->post('author'),
'title' => $this->input->post('title'),
'contents' => $this->input->post('contents')
);
$this->site_model->add_record($data);
$this->index();
}
I only included create to keep it short. Then I also have the TimeTask class, that actually another StackOverflow so kindly helped me with:
<?php
class TimeTask
{
private $task;
/**
* #var DateTime
*/
private $date1, $date2;
function __construct($currTask)
{
$this->task = $currTask;
}
public function getTimeDiff()
{
$hasDiff = $this->date1 && $this->date2;
if ($hasDiff) {
return $this->date2->getTimestamp() - $this->date1->getTimestamp();
} else {
return NULL;
}
}
public function __toString()
{
return (string) $this->getTimeDiff();
}
/**
* #return \DateTime
*/
public function getDate1()
{
return $this->date1;
}
/**
* #param \DateTime $date1
*/
public function setDate1(DateTime $date1)
{
$this->date1 = $date1;
}
/**
* #return \DateTime
*/
public function getDate2()
{
return $this->date2;
}
/**
* #param \DateTime $date2
*/
public function setDate2(DateTime $date2)
{
$this->date2 = $date2;
}
/**
* #return get current task
*/
public function getTask()
{
return $this->task;
}
}
?>
I don't think posting the views is necessary for the question but here is atleast how the links are made.
<?php echo form_open('site/create');?>
...and...
<?php echo anchor("site/delete/$row->id", $row->title); ?>
Now there's no error in the code but it doesn't do what I expect of it and the reason I assume why is because that each time a function of the script is called via a new page it is NOT the same instance of the script called previously so any previously created objects are no longer there. This confuses me and leaves me quite unsure of how to implement this gracefully. Some ways I would guess of how to do this is by passing the necessary data through the URL or have data saved in a database and retrieve it later to compare the times. What would be a recommended way to do, not just this, but anything that needs previously created data? Also, am I correct to think that a script is only 'alive' for one webpage at a time?
Thanks!
Web development is a bit different to "standard" development - principally because of the nature of HTTP. Each request to the web application has to travel across the network using HTTP, which, as all web developers know, is stateless. What this means is that web servers do not have to remember anything about previous HTTP requests. Usually, webdevs get round this using cookies in one way or another - where a cookie is some bit of data, coded as a text string, which is sent back to the browser so that it can resend it to the application on the next request. Like that, a cookie is a kind of transferable memory.
So, each time you make a request, unless you transfer some data using a cookie (either an HTTP cookie, or what is sometimes called a URL cookie - state data coded in the URL), it looks to the web application like a brand new request, unrelated to any past request. So, for your application to work, you need to use a cookie in some way to remember or recover the start time when you detect that the user has finished a task. You can either (i) use CI's built-in facilities for remembering data (flashdata, as mentioned above, or userdata from the CI Session class - see http://codeigniter.com/user_guide/libraries/sessions.html), which are built on top of CI cookies), (ii) do this using your own cookie data (not recommended - why use the framework in that case?), or (iii) use hidden form fields - an oldie but sometimes goldie technique that requires the PHP script generating a view to write hidden form fields whose values are the data you want to remember and have sent back to you on the next request.
This kind of problem is something you'll come across again and again in web development - so get to know the problem and its solutions well!
You can use flashdata to make data available for next server request.
Reference: http://codeigniter.com/user_guide/libraries/sessions.html
You can go the extra step with sessions and implement the database table to store the current sessions. This gives you the ability to validate the id and confirm it's a valid session and not an old session accidentially restored via modded cookies for example.
It's very straight forward.
Create the table:
CREATE TABLE IF NOT EXISTS `ci_sessions` (
session_id varchar(40) DEFAULT '0' NOT NULL,
ip_address varchar(45) DEFAULT '0' NOT NULL,
user_agent varchar(120) NOT NULL,
last_activity int(10) unsigned DEFAULT 0 NOT NULL,
user_data text NOT NULL,
PRIMARY KEY (session_id),
KEY `last_activity_idx` (`last_activity`)
);
Modify the config file(application/config/config.php):
$config['sess_use_database'] = TRUE;
$config['sess_table_name'] = 'ci_sessions';
And then, use the standard methods to set and get the values.
Here is the guide: CI User Guide - Session Class