Temporary Table not always available in Code Igniter? - php

Code Igniter - PHP - Mysql.
I am working on a Shopping Website, and due to the large number of Products and Client Pricing Options for each Product (inclusion of Discounts at a different rate for each user etc), have created a temporary table when a Client Logs in.
The table is creating successfully, however as I navigate thru the site it doesnt always remain persistent.
For eg, If i have a query saying "Select * From Temp_Products" running on each page of the site, it returns an empty set or says Temp_Products doesnt exist on some pages.
I am unable to figure out where the problem is, there seems to be no specific pattern or trigger causing this.
Also, how do e-commerce sites usually implement catalogues & inventry? Any info would be helpful!!
Thanks !

Create a table in the db
es: id - id_user - id_table
after, put in the session the field that permit you to retrive the item of table.
Create a library that permit you to dialog with the data in the db es: Mytable, and in this library, create some function that get automaticaly get the items on the db, starting from the field in the session.

If you use temporary tables there are a few pitfalls.
First of all, if you use persistent connections (which you never ever should), the temporary table will be shared among Ci-sessions since persistent connections are shared among CI-sessions. This is probably not what you want.
If you don't use persistent connections (as you should), the temporary table only lasts for the current request. Since when the CI-instance stops at the end of every request, it cleans up its database connection, which drops all temporary tables for that connection.
In your case you probably need a 'normal' table using the session-id as a key. Don't forget to clean up the sessions specific entries after the session dies. This is not easy, since codeigniter uses some delayed garbage collection mechanism for this. So you will probably need a cronjob that periodically checks whether sessions do or do not exist anymore and act upon this.

Related

PHP One time database query on application startup

I have a ajax based PHP app (without any frameworks etc.).
I need to retrieve some records from the database (html select element items) ONCE, and once only, during application startup, store it in a PHP array, and have this array available for future use to prevent future database calls, for ALL future users.
I could do this easily in Spring with initializing beans. And this bean would have the application scope (context) so that it could be used for ALL future user threads needing the data. That means the database retrieval would be once, only during app boot, and then some bean would hold the dropdown data permanently.
I can't understand how to replicate the usecase in PHP.
There's no "application" bootstrapping as such, not until the first user actually does something to invoke my php files.
Moreover, there is no application context - records retrieved for the first user will not be available to another user.
How do I solve this problem? (Note: I don't want to use any library like memcache or whatever.)
If you truly need to get the data only the first time the app is loaded by any user, than you could write something that gets the data from your database, and then rewrites the html page that you're wanting those values in. That way when the next user comes along, they are viewing a static page that has been written by a program.
I'm not so sure that 1 call to the database everytime a user hits your app is going to kill you though. Maybe you've got a good reason, but avoiding the database all but 1 time seems rediculous IMO.
If you need to hit the database one time per visitor, you could use $_SESSION. At the beginning of your script(s) you would start up a session and check to see if there are values in it from the database. If not, it's the user's first visit and you need to query the database. Store the database values in the $_SESSION superglobal and carry on. If the data is in the session, use it and don't query the database.
Would that cover you?

synchronize different user sessions when events happened in PHP

I’m writing a social networking application and I want to synchronize different user sessions.
My context is following:
userA is logged and has an array of his contacts in session.
userB is logged and has an array of his contacts in session.
userA adds userB as a contact.
So, Contact table (DB) sees a new record
And userA has an update of his array of contacts (easy because the event happens on userA navigation side)
My need is following:
I want now to synchronize automatically userB’s session so that his array of contacts is refreshed
without doing a sql query to check the contacts table (db). I want that in order to avoid making too many sql queries to check that.
Do you have any suggestions?
I’m using CodeIgniter (PHP) and the session is managed with database.
Thanks a lot
This is not possible without doing a sql query to check the contacts table. Even if you hold your sessions in sql table you still have to query for the data
You want to update a copy of the data (userAs session) without refering to the master set of data. This is just not going to work.
With it's shared nothing architecture, this is going to be hard to implement in PHP.
The only sensible way to achieve this in anything approaching realtime is to maintain a semaphore for each current user session - and set that semaphore when the session data should be re-loaded. And at that point you must read the data from the database.
Much of this could be done within the session handler - which is probably the most sensible place to handle it - but you need to be aware that the semaphore is therefore volatile and code it appropriately (e.g. using optimistic locking around reading/writing the semaphore).

How to implement semaphores in PHP without PHP Semaphore?

Question:
How can I implement shared memory variable in PHP without the semaphore package (http://php.net/manual/en/function.shm-get-var.php) ?
Context
I have a simple web application (actually a plugin for WordPress)
this gets a url
this then checks the database if that url already exists
if not then it goes out and does some operations
and then writes the record in the database with the url as unique entry
What happens in reality is that 4,5,6 ... sessions at the same time request the url and I get up to 9 duplicate entries in the database of the url.. (possibly 9 because the processing time and database write of the first entry takes just enough time to let 9 other requests fall through). After that all requests read the correct entry that the record already exists so that is good.
Since it is a WordPress plugin there will be many users on all kind of shared hosting platforms with variable compiles/settings of PHP.
So I'm looking for a more generic solution. I cant use database or text file writes since these will be too slow. while i write to the db the next session will already have passed.
fyi: the database code: http://plugins.svn.wordpress.org/wp-favicons/trunk/includes/server/plugins/metadata_favicon/inc/class-favicon.php
update
Using a unique key on a new md5 hash of the uri together with try catches around it seems to work.
I found 1 duplicate entry with
SELECT uri, COUNT( uri ) AS NumOccurrences
FROM edl40_21_wpfavicons_1
GROUP BY uri
HAVING (
COUNT( uri ) >1
)
LIMIT 0 , 30
So I thought it did not work but this was because they were:
http://en.wikipedia.org/wiki/Book_of_the_dead
http://en.wikipedia.org/wiki/Book_of_the_Dead
(capitals grin)
This could be achieved with MySQL.
You could do it explicitly by locking the table from read access. This will prevent any read access from the entire table though, so may not be preferable. http://dev.mysql.com/doc/refman/5.5/en/lock-tables.html
Otherwise if the field in the table is classified as unique, then when the next session tries to write the same URL to the table they will get an error, you can catch that error and continue as there's no need to do anything if the entry is already there. The only time wasted is the possibility of two or more sessions creating the same URL, the result is still one record, as the database won't add the same unique URL again.
As discussed in comments, because the length of a URL could be very long, and fixed length unique hash can help overcome that issue.
There are other shared memory modules in PHP (shmop or APC for example), but I think what you are saying is that there is an issue relying on non-standard/not pre-installed libraries.
My suggestion is that before you go and do "other operations" you need to make an entry in the database, perhaps with a status of "compiling" (or something) so you know it is still not available. This way you don't run into issues with getting multiple entries. I would also be sure you are using transactions when they are available so your commits are atomic.
Then, when you "other operations" are done, update the database entry to "available" and do whatever else it is you need to do.

do i use ci_sessions to store session data

Im developing site for a travel site, in the process when a user searches I do manipulation on the database result then store it in session. Which stores the data in the ci_session database. By following this method I'm able to easily filter the data from
$this->session->userdata();
A normal search which results in 4 hotels the session data goes more than 20kb, in actual server environment it is possible that the result will be more than 200 hotels, i.e. 4000kb data for a single user on each row, in ci_session table.
this process is making the app very slow, What other approach i can follow to make the search result much faster.
You can store the session data in your database. CI Sessions have the ability to handle that. No need to do it yourself.
Read the chapter in the manual how to configure it properly. Choose wisely what you write into the "session" since lots of sessiondata in the database could make the requests slow if you need them on every site.

MySQL Transaction across many PHP Requests

I would like to create an interface for manipulating invoices in a transaction-like manner.
The database consists of an invoices table, which holds billing information, and an invoice_lines table, which holds line items for the invoices. The website is a set of scripts which allow the addition, modification, and removal of invoices and their corresponding lines.
The problem I have is this, I would like the ACID properties of the database to be reflected in the web application.
Atomic: When the user hits save, either the entire invoice is modified or the entire invoice is not changed at all.
Consistent: The application code already ensures consistency, lines cannot be added to non-existent invoices. Invoice IDs cannot be duplicated.
Isolated: If a user is in the middle of a set of changes to an invoice, I would like to hide those changes from other users until the user clicks save.
Durable: If the web site dies, the data should be safe. This already works.
If I were writing a desktop application, it would maintain a connection to the MySQL database at all times, allowing me to simply use the BEGIN TRANSACTION and COMMIT at the beginning and end of the edit.
From what I understand you cannot BEGIN TRANSACTION on one PHP page and COMMIT on a different page because the connection is closed between pages.
Is there a way to make this possible without extensions? From what I have found, only SQL Relay does this (but it is an extension).
you don't want to have long running transactions, because that'll limit concurrency. http://en.wikipedia.org/wiki/Command_pattern
The translation on the web for this type of processing is the use of session data or data stored in the page itself. Typically what is done is that after each web page is completed the data is stored in the session (or in the page itself) and at the point in which all of the pages have been completed (via data entry) and a "Process" (or "Save") button is hit, the data is converted into the database form and saved - even with the relational aspect of data like you mentioned. There are many ways to do this but I would say that most developers have an architecture similar to what I mentioned (using session data or state within the page) to satisfy what you are talking about.
You'll get much advice here on different architectures but I can say that the Zend Framework (http://framework.zend.com) and the use of Doctrine (http://www.doctrine-project.org/) make this fairy easy since Zend provides much of the MVC architecture and session management and Doctrine provides the basic CRUD (create, retrieve, update, delete) you are looking for - plus all of the other aspects (uniqueness, commit, rollback, etc). Keeping the connection open to mysql may cause timeouts and lack of available connections.
Database transactions aren't really intended for this purpose - if you did use them, you'd probably run into other problems.
But also you can't use them as each page request uses its own connection (potentially) so cannot share a transaction with any others.
Keep the modifications to the invoice somewhere else while the user is editing them, then apply them when she hits save; you can do this final apply step in a transaction (albeit quite a short-lived one).
Long-lived transactions are usually bad.
The solution is not to open the transaction during the GET phase. Do all aspects of the transaction—BEGIN TRANSACTION, processing, and COMMIT—all during the POST triggered by the "save" button.
Persistent connections may help you:
http://php.net/manual/en/features.persistent-connections.php
Another is that when using
transactions, a transaction block will
also carry over to the next script
which uses that connection if script
execution ends before the transaction
block does.
But I recommend you to find another approach to the problem.
For example: create a cache table.
When you need to "commit", transfer the records from the cache table to the "real" tables.
Altough there are some good answers, I think that found some good responses to your question, that I was stuck with also. I think the best approach is using a framework like Doctrine (O/R mapping) that has this kind of approach somehow implemented. Here you have a link to what I'm talking about.

Categories