mschroeder 251 Bestower of Knowledge Team Colleague

It sounds like you have a file with 10000+ lines in it, that you need to split into 50 line chunks and save to new files...

If the file is well over your php memory limit, reading the whole thing into memory will only cause you headaches.

I'd highly suggest using SplFileObject to iterate over the file line by line. This will give you a much smaller memory footprint.

Create a blank file also using SplFileObject, iterate over 50 lines of the original file, writing each line to the new blank file.
Keep a counter of how many lines you've read through. When you've reached 50, simply increment the blank file you're using.

I'll be happy to share code examples.

mschroeder 251 Bestower of Knowledge Team Colleague

If you want the currently executing PHP file you can use the magic constant __FILE__ (http://php.net/manual/en/language.constants.predefined.php) which will give the filesystem path.

OR

If you want to link to the current file in a url fashion you can use $_SERVER['PHP_SELF'] (http://php.net/manual/en/reserved.variables.server.php)
e.g. if the url is http://www.domain.com/script.php then $_SERVER['PHP_SELF'] will contain /script.php

mschroeder 251 Bestower of Knowledge Team Colleague

From a high level, your class is trying to accomplish to much in a single place. Check out the concept of SOLID (http://www.freeklijten.nl/home/2012/03/23/SOLID-The-S-is-for-Single-responsibility)

What you should ultimately end up with is a set of classes that allow you to work with emails in the most generic of ways. An Email object would represent an email and it's fields only. This should probably implement a standard interface so you can develop multiple email objects, e.g. PlainText, Html, Multi-part etc. These would extend a base class or implement some kind of inteface to ensure they have certain basic methods.

From there you would have an object that represents a mail server and is responsible for sending an Email Object. For example EmailTransport. Email transport might be setup to use different adapters that allow it to interact with multiple server types, sendmail, smtp, mock(for saving an email object to a file for testing), and mail(). This can be designed using the Adapter pattern.

For validation and filtering you would want two finds of objects, One that is able to deal with specific pieces of validation. Again you'd have multiple validators each with a single functionality. Filters would be setup the same way.

This is really high level and a lot to digest but these are some of the common things I see wrong with OOP code in the PHP world and I hope this helps to set you on the right path.

<?php

    namespace Daniweb\Email;

    interface EmailInterface
    {
        protected $to;
        protected …
mschroeder 251 Bestower of Knowledge Team Colleague
echo $array[79]->value;

Something like that should do the trick, obviously depends on what the variable that contains the array is named.

mschroeder 251 Bestower of Knowledge Team Colleague

Using the idea of a Honey Pot has always been a pretty effective way to prevent comment form spam. Basically add one or more additional form fields that are hidden to the browsing user that should always be blank. When a form is submitted with those fields filled in, reject the submission.

Venom Rush commented: Great idea! +2
mschroeder 251 Bestower of Knowledge Team Colleague

As I said previously....

Oh EACH remote machine you want to access your wamp machine from, you will need to modify the hosts file.

The only other option is to create a DNS server just for .local domains and have your computers route through that. However, this is overkill when you just need access for a few machines.

mschroeder 251 Bestower of Knowledge Team Colleague

I've had extensive experience with all three of those frameworks.

Symfony2 - At the moment Symfony2 is the best framework I've used. The biggest feature of the whole "framework" is that it is nothing more than a collection of bundles architected together. It is extremely powerful and flexible, and you can replace pretty much any aspect of the system with your own implementations, but if you do not have a serious OOP background as well as a desire to learn how to use a DIC etc then Symfony2 is not for you. It can be a challenge to deploy and there is a STEEP learning curve, but once you've invested some time it is very hard to use other frameworks.

ZF1 - Used to be my favorite framework because of the structure and the access to documentation and users. The lack of native php namespaces and some of the design decisions made some of the components feel hackish in their implementations, but it worked and it worked well. However my experience with ZF2 has been much like Symfony2 but they are vastly different from one another and ZF2 has yet to have a "stable" release.

CI - I started using this framework when I started at my current employer. Personally I find it to be unorganized and convoluted (var_dump a get_instance() call just and look at the recursion and repetition in the array) . There are lots of 3rd party libraries that attempt to bring it more in line with …

mschroeder 251 Bestower of Knowledge Team Colleague

A few points to consider.
CI documentation suggests using an underscore naming convention (Books_model) vs camelcasing like BooksModel. Models should also start with a capital letter and be followed only by lowercase letters.

Also your models should call the parent constructor.

//...
public function __construct() {
    parent::__construct();
}
//...

Finally for a method to accept a post array as a method argument it means your method should look like:

public function fooBar( $post ){
    //...
}

And would be used as:

$this->model->fooBar( $_POST ); //or the post object in CI
mschroeder 251 Bestower of Knowledge Team Colleague

If you have server access or a hosting company that will install libraries for your use then a great PHP option is to use Snappy it wraps the wkhtmltopdf library and the wkhtmltoimage library.

diafol commented: good link +14
mschroeder 251 Bestower of Knowledge Team Colleague

@pritaeas
When you say output caching you mean caching the final rendered templates or caching the templates themselves?

I have always used twig behind Varnish servers which integrate very well with Symfony2 so I use a lot of ESI's to deal with my caching. Twig by default compiles all of your templates down to native php so that is also a kind of cache that vastly improves performance. I also usually run the twig php extension wherever possible to squeeze more performance out of it.

Apparently I don't get notifications when someone comments on threads I've posted in now... +1 for "upgrading functionality" I guess.

@ardav
I really like what is being done with composer and packagist they make PEAR feel archaic and remove the dependency on libraries that don't get updated fequently on shared servers because of dependency.

mschroeder 251 Bestower of Knowledge Team Colleague

Twig gets my vote by far. Having used a lot of different template languages for php it is the first one that really seems to get it right.

The syntax is concise but yet still very verbose. It is fast, but mostly it is extensible. Twig is a pleasure to write extensions for that keep the template language looking neat and tidy. Plus it is part of a major framework (Symfony2 Standard) and that ensures it will receive long-term attention and development.

mschroeder 251 Bestower of Knowledge Team Colleague

In my experience, having developed complex systems from scratch, Zend, Symfony2, and CodeIgniter, I can tell you that it really depends on what you want your end result to be. If you build something from scratch you have total control over every aspect, this can be both good and bad, of the process and architecture.

It also depends on how you expect the project to grow, often what is attractive about 3rd party frameworks is the standardization. if you know Zend, you should be able to easily acclamate yourself to any Zend project. So if you need more developers you can focus on people who know your particular framework and only have to train them on the business implementations whereas if you're working in a homespun environment it will take a new developer a lot longer to come up to speed, and be productive.

There are other things to consider as well, performance, security, documentation, unit testing etc. Third party frameworks often have hundreds or thousands of contributors which is what makes them so robust.

As far as frameworks go, I really liked Zend until I started working with Symfony2. While I know there are complex sites built on CodeIgniter I really find it to be a subpar framework. Its nearly impossible to swap out core components with your own implementations, it will fight you every step of the way to test, and while it uses OOP principles it is as far from OOP as you can …

mschroeder 251 Bestower of Knowledge Team Colleague

Why reinvent the wheel and try to create a code style guide from scratch when there are plenty of sensical, logical and well documented style guides out there already that are accepted and in use in lots of projects?

All you'll do with such a non-standard design is create a barrier that if you ever need someone to work on your code they'll spend more time trying to figure out the style than what it is they're tasked to do.

diafol commented: good comment - especially about collaborative coding +14
mschroeder 251 Bestower of Knowledge Team Colleague

If your webhost does not support .htaccess and the web server is Apache...move to a better host.
If your webhost does not support .htaccess and the web server is not Apache, look to see what type of url rewriting it supports. If you still can't...move to a better host.

.htaccess or its equivalent is pretty much an industry standard these days.

Creating tons of index.php files in tons of nested directories, not only introduces a maintenance nightmare, but also introduces a security risk when it comes to fixing bugs they will need to be pushed through any file with duplicated code. This goes back to creating a maintenance nightmare.

mschroeder 251 Bestower of Knowledge Team Colleague

First, your class is mixing to many responsibilities.
You should be passing an already established database into your quiz class if it is needed.
Second, Your class should not be responsible for rendering the form as well, this is another responsibility that is mixed.
Third, you could probably benefit from a more robust class design.

Think of the design like this:

  • A "quiz" is a composite of "questions" that are rendered into a singular form.
  • The quiz should be able to add and remove questions as well as do it in a batch fashion.
    • Questions may need to be of different types, therefore rendered individually. (Multiple Choice, Select One, Input a Value)
    • Think about a Question abstract or interface that all question types need to extend, they all have common functionality and/or methods but also specific details that need to be represented.
  • When rendering a quiz, the ultimate goal would be to have a template for each question type, and a template for a quiz as a whole which would render the question templates into a form template and create the output.

It sounds like a lot more work, but the end result with be a quiz structure where you will be able to swap pieces and parts with little to no hassle, and also add or replace the questions and templates without touching other portions of your code.

diafol commented: nice one - I learned a lot from that. :) +14
mschroeder 251 Bestower of Knowledge Team Colleague

If you have installed the SQL Server driver from Microsoft than you need to use the sqlsrv_* functions as demonstrated here: http://social.technet.microsoft.com/wiki/contents/articles/accessing-sql-server-databases-from-php.aspx More specifically these functions http://php.net/manual/en/book.sqlsrv.php

mschroeder 251 Bestower of Knowledge Team Colleague

Stop doing the insert in the loop. This is easily solved by using the loop to generate the insert query and then execute 1 query instead of 10000.

PDO Prepared Statements
Executes 10000 statements
Execution Completed: 10.082677841187 seconds

$db = new PDO( 
    'mysql:host=127.0.0.1;dbname=examples', 
    'username', 
    'password', 
    array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8") 
); 

$sth = $db->prepare('INSERT INTO persons (id, FirstName, LastName, Age, Code) VALUES (NULL, :FirstName, :LastName, :Age, :Code )');

for( $i=1; $i<=10000; $i++ ){
	
	$code = rand(10000,999999);
	$name = 'Peter'.rand(1000,9999);
	
	$sth->bindValue( ':FirstName', $name );
	$sth->bindValue( ':LastName', 'Griffin' );
	$sth->bindValue( ':Age', '35' );
	$sth->bindValue( ':Code', $code );
	$sth->execute();
}

PDO Single Query
Executes 1 query
Execution Completed: 0.28580498695374 seconds

$db = new PDO( 
    'mysql:host=127.0.0.1;dbname=examples', 
    'username', 
    'password', 
    array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8") 
); 

$inserts = array();
$queryFormat = '(NULL,"%s", "Griffin", "35", "%d")';

for ($i=1; $i<=10000; $i++)
{
	$code = rand(10000,999999);
	$name = 'Peter'.rand(1000,9999);	
	$inserts[] = sprintf( $queryFormat, $name, $code );	
}

$query = implode( ",", $inserts );

$db->query( 'INSERT INTO persons (id,FirstName, LastName, Age, Code) VALUES '.$query );

I made a few changes. The name "Peter" was not quoted, I also added a column for "Code' to my query as I think it was forgotten since the insert has a value for it.

Concept applies to all database drivers, but with PDO you'll have the most flexibility. If these values are coming from the end user, prepared statements will provide a much more secure database interaction than using the values directly in the query without first sanitizing/validating …

mschroeder 251 Bestower of Knowledge Team Colleague

In terms of an acl you often have the following entities, Users, Roles, Resources and Privileges. Of course everyone will have their own words for each thing but this is how I would define each for the rest of this post.

User - The Person
Role - The group 1 or more persons are in
Resources - A Noun e.g. newsletter, report, post, etc.
Privileges - The Actions e.g. edit, delete, create, view etc.

So when I have seen acl's applied to the routing it is usually handled in the FrontController via a plugin before the route is dispatched to a controller and action. Which seems to be how want it to function anyways. When this is implemented in this way, generally the Resources is in the pattern of Module.Controller.Action or Module-Controller-Action etc. and the FrontController is looking for a specific Privilege, such as view or access.

The nice thing about this naming convention is it allows you to control access at a granular or broad range. Your frontcontroller would first check the module only, than the module.controller and finally the module.controller.action.

So instead of having to enter records for every action in your system you could simple add the resource admin (admin module) with the access, view etc privilege to the user role admin.

The only thing to keep in mind is by default all users to your site either need a guest role, until they sign in, which allows access …

Stefano Mtangoo commented: Great post, thank you! +13
mschroeder 251 Bestower of Knowledge Team Colleague

@ajbest

Just be aware that there are limitations to strtotime and similar functions. The y2k38 bug is when the unix timestamp will exceed a 32bit integer. So for example, if you would try to generate a date, say 30 years in the future (maybe the end date of a mortgage), it will fail.

The php DateTime classes do no suffer from this same limitation. A 64bit build of php will also solve this.

mschroeder 251 Bestower of Knowledge Team Colleague

To my understanding hmac variations are substantially less prone to collisions than the standard hash functions.

I know this is not directly related to your question, but have you considered using bcrypt for your passwords? Assuming your environment is 5.3+
http://us2.php.net/crypt
http://yorickpeterse.com/articles/use-bcrypt-fool/
http://phpmaster.com/why-you-should-use-bcrypt-to-hash-stored-passwords/
http://chargen.matasano.com/chargen/2007/9/7/enough-with-the-rainbow-tables-what-you-need-to-know-about-s.html
http://gom-jabbar.org/articles/2008/12/03/why-you-should-use-bcrypt-to-store-your-passwords

mschroeder 251 Bestower of Knowledge Team Colleague

If you're going to evaluate a host, look less at the features and more at the infrastructure. If you are looking at a shared host or a reseller account than some important things to consider would be:

  1. Is your data protected by some kind of RAID array?
  2. Is your data also remotely backed up in some automated fashion at a set interval?
  3. Is the server oversold (AKA are the same resources sold to more than one user)?
  4. Where is the server located (Datacenter and Physically)?
  5. What kind of connectivity does the server have? 10Mbps/100Mbps/1000Mbps etc.

Some other more technical concerns should be how the host has PHP configured, including what extensions they have installed. Most shared/reseller hosts will NOT custom configure their php installations for you. But, there are some that will if that is what you need.

Most shared/reseller hosts use some form of control panel. These provide the features like emails, ftps, databases, etc etc. Commonly you'll see cPanel, DirectAdmin or Plesk. However, there are many other control panel solutions as well as some in-house solutions the host developed themselves.

I completely agree with ardav. You absolutely get what you pay for. Steer far away from unlimited hosting, unless of course you can show me an unlimited hard drive, or a NIC with an infinite port speed.

A great resource is Web Hosting Talk search for the name of any host you're looking at and read some reviews.

diafol commented: good points +13
mschroeder 251 Bestower of Knowledge Team Colleague

If you're opening a mysql connection for every method call you are definitely doing it inefficiently.

The best way to handle the connection would be to setup one connection per request, since php's scope is limited pretty much to each request, and pass it into all of your different objects where it is needed.

e.g.

<?php

try {
    $dbh = new PDO($dsn, $user, $password);
} catch (PDOException $e) {
    echo 'Connection failed: ' . $e->getMessage();
}

//Inject the database handler via constructor
$someClass = new SomeClassThatNeedsDatabaseAccess( $dbh );
// OR use a setter
//$someClass = new Some ClassThatNeedsDatabaseAccess();
//$someClass->setDbh( $dbh );

$someClass->useTheDbConnection();

//.....

class SomeClassThatNeedsDatabaseAccess
{
	protected $dbh;
	
	public function __construct( $dbh = null )
	{
		if( !is_null( $dbh ) ){
			$this->setDbh( $dbh );
		}
	}
	
	public function setDbh( PDO $dbh )
	{
		$this->dbh = $dbh;
	}
	
	public function getDbh()
	{
		return $this->dbh;
	}
	
	public function useTheDbConnection()
	{
		$result = $this->getDbh()->query('...');
	}
	
}
mschroeder 251 Bestower of Knowledge Team Colleague
<?php
  $date = '140811 060632';
  echo DateTime::createFromFormat('dmy his', $date)->format('Y-m-d H:i:s');

http://php.net/manual/en/datetime.createfromformat.php

cereal commented: nice! :) +6
mschroeder 251 Bestower of Knowledge Team Colleague

If you spent even a fraction of a minute looking at their HTML you'd notice an ajax link like this:
http://tastykitchen.com/recipes/wp-content/plugins/wp-recipes/ajax.php

If you use Firefox, Chrome or Safari, and opened the developer tools/firebug, and adjusted the servings you'd see that the site is using that to make an ajax request. Which then returns a full block of html that is replaced on the site.

Although that is not useful, what you will notice is the /plugins/wp-recipe/ part of that url.
Simply googled for "wp-recipe plugin" and got http://wordpress.org/extend/plugins/wp-recipes/

SImply download the plugin and review the actual PHP source code and you should have a great place to start from.

mschroeder 251 Bestower of Knowledge Team Colleague

if( isset($_POST) && !empty($_POST) ){

exit();

}

Seriously this code is of no use. Just delete it and use javascript.

Just Use Javascript Validation and submit its value to the modify_data.php , make a connection in modify_data.php file and retrieve value from previous page using post method . Build a select query on this this page using retrieved values and display data .

This is TERRIBLE advice. Validation should never be done just on the client-side. All it takes is disabling javascript to be able to submit any data you want to the form. Or simply making a post/get request with something like curl.

Make it validate server-side (PHP) first, than worry about javascript validation as this benefits the user and prevents the need to submit the form for trivial issues.

First, have you tried turning error_reporting on? Error reporting is often disabled in environments. Just add error_reporting(E_ALL | E_STRICT); after your <?php tags in your files. This will ensure you are actually seeing EVERY php error even the notices.

Note: line numbers are relevant to your posted code.

Second, line 28 - 31 of modify_data.php If that query doesn't return any results, it will show your message but continue running your code after that. http://php.net/manual/en/function.exit.php - Just one way to terminate execution.

Third, the query on line 33 appears as though it will fetch all of the data in your db since there is no where condition to limit it.

Fourth, …

mschroeder 251 Bestower of Knowledge Team Colleague
$doc = new DOMDocument();
$doc->loadXML('Your XML string');

//Gets the SpecialParameter node value
$specialParameter = $doc->getElementsByTagName('SpecialParameter')->item(0)->nodeValue;

//Gets the SpecialInfo::someNumber attribute value
$specialInfo = $doc->getElementsByTagName('SpecialInfo')->item(0)->getAttribute('someNumber');

This is untested but I believe this should get you in the right direction at the minimum.

iamthwee commented: you beat me to it +15
mschroeder 251 Bestower of Knowledge Team Colleague

1. For starters, anyone who has been around any form of serious web hosting environment will quickly tell you that there is NO such thing as unlimited hosting. There are no unlimited hard drives and there are no unlimited bandwidth connections. At some point there is a limit. Unlimited hosts may be getting better with the proliferation of massive hard drives and fast connections but there will always be a limit somewhere.

These shops tend to target smaller setups who have very small resource footprints and that is fine, but as soon as the resources grow to some, often unwritten, soft limitation you will have problems. This also tends to lead to a lot of overselling. Again if the resources are there it is not a big deal, until hundreds of accounts on the same server start trying to use the same chunk of unlimited bandwidth.

If you value the quality of your service and intend to have your site/service grow to a sizable level then do yourself a favor and steer clear of the allure of unlimited hosting. If you're just using it to get your feet wet and get off the ground it could be a cheap way to get started. You get what you pay for.

2. Video processing is going to require memory and processor resources. These are probably the most expensive and limited resources in a server. If your site sees any kind of steady traffic, you will probably quickly outgrow a …

mschroeder 251 Bestower of Knowledge Team Colleague

Hashing is a one-way algorithm it can not be run in reverse.
Encryption is a two-way algorithm where a string and be encrypted and then decrypted.

md5 and sha1 can't be decrypted, but what those sites do, is maintain giant databases of common lookups. So if you make your password 'password' the md5 will always be '5f4dcc3b5aa765d61d8327deb882cf99' which means you can store that and you know that the hash always (minus collisions) matches password.

With hashes it is recommended to always salt the hash with additional random characters that is unique to your site. So if your salt is "!@#$VSA!@#adjk_48ashkj345" no matter how weak someones password is, by default it will be as strong as the salt.

e.g. A user's password of "password" is now "!@#$VSA!@#adjk_48ashkj345password!@#$VSA!@#adjk_48ashkj345" before it gets hashed. This prevents the hashes from being easily matched if your db is compromised, but does nothing if your site is exploited from the frontend where an attacker throws common works at your login fields. This is where rate limits and failed login checks come into play.

This is also a place where it is suggested to make logging in as slow as possible by doing thousands if not hundreds of thousands of hash calculations so you become a much less viable target to attack with automation.

mschroeder 251 Bestower of Knowledge Team Colleague

My results are right on par with what you are seeing. Reflection is about twice as slow as using variable variables. I also benchmarked call_user_func and found that to be just about on par with the variable variable calls. I can't say I've seen reflection used as much as I've seen a mixture of variable class and method calls and call_user_func calls. Probably because of the performance hit.

PHP 5.3 added the ability to do variable static method calls $class::$staticMethod() , so I believe this is something that is here to stay in PHP.

Running Benchmark: Compare Variable Variables To Reflection To Call_User_Func
======================================================================
Running Test: test_Variable_Variable
	Cycles: 	 10000
	Mean: 		 0.0000545718 secs.
	Median: 	 0.0000410080 secs.
	Mode: 		 0.0000410080 secs.
	Range: 		 0.0287699699 secs.
	Min: 		 0.0000379086 secs.
	Max: 		 0.0288078785 secs.
======================================================================
Running Test: test_Reflection
	Cycles: 	 10000
	Mean: 		 0.0000928412 secs.
	Median: 	 0.0000720024 secs.
	Mode: 		 0.0000720024 secs.
	Range: 		 0.0295591354 secs.
	Min: 		 0.0000679493 secs.
	Max: 		 0.0296270847 secs.
======================================================================
Running Test: test_Call_User_Func
	Cycles: 	 10000
	Mean: 		 0.0000557658 secs.
	Median: 	 0.0000460148 secs.
	Mode: 		 0.0000460148 secs.
	Range: 		 0.0230920315 secs.
	Min: 		 0.0000429153 secs.
	Max: 		 0.0231349468 secs.
======================================================================
mschroeder 251 Bestower of Knowledge Team Colleague

Objects which can not be serialized or are composed of objects that can't be serialized will cause headaches with your sessions for starters.

In my experience there is a bigger performance hit for the server to serialize and unserialize session data than there is to recreate the objects from persistent storage, especially if the object collection grows and grows.

Stefano Mtangoo commented: Very useful! +6
mschroeder 251 Bestower of Knowledge Team Colleague

There probably isn't a reason to actually delete records.

On the query you use to pull the comments you should add an ORDER BY clause that sorts them by the date they were added to the database (assuming you have a column for this) and then add a LIMIT clause (http://dev.mysql.com/doc/refman/5.1/en/select.html#id848826) so that only the most recent 10 results are shown.

mschroeder 251 Bestower of Knowledge Team Colleague

You should have started a new thread for starters, but your problem is rather simple.
You're development environment is running at least php 5.3.0, which deprecated the session_is_registered function. (http://php.net/manual/en/function.session-is-registered.php)

Anywhere you have if( session_is_registerd('key') ) replace it with if( isset( $_SESSION ) )

session_register is also deprecated btw.(http://www.php.net/manual/en/function.session-register.php)

mschroeder 251 Bestower of Knowledge Team Colleague

I assume you want functionality like wordpress, where as you type into your title, the url is generated from it and displayed for the user.

While this could be achieved with pure javascript, I think your best solution will be to use an ajax request, so it can check the database if the url is already taken.

I'm just going to reference some jquery stuff as you can try to put the pieces together before we go any further, but essentially, the user enters the headline and on a .focusout() event (when they leave that input field for something else) you take whats in the headline field (See jQuery selectors) and make an ajax GET request to a php script which returns json (for this example) .

The php script, filters the headline to Alphanumeric and spaces. Then replaces the spaces with dashes and then lowercases the entire string. (Filter the string first as this will prevent any multi-byte issues)

<?php

$string = $_GET['headline']; //From the ajax get request. Should produce this-is-my-test-headline
$string = preg_replace( '/[^0-9a-zA-Z ]/i', '', $string );
$string = str_replace( ' ', '-', $string );
$string = strtolower($string);

/* 
Do a database lookup and return a count() value
e.g.

$stmt = $dbh->prepare("SELECT COUNT(ThreadId) AS ThreadCount WHERE Url = ?");
if ( $stmt->execute( $string ) ) {
  //Should only return ONE row
  $row = $stmt->fetch();
  if( $row['ThreadCount'] != '0' ){
	//Tack on ThreadCount + 1 to the headline
	$string …
mschroeder 251 Bestower of Knowledge Team Colleague

Having the value in a hidden input field would be no different than the user selecting it from a drop-down where it is also visible in the source.

If you inspect the source of most web forms you're going to commonly find the use of hidden input fields. This is why filtering/validating input and escaping your output is so important.

kekkaishi commented: exactly. +2
mschroeder 251 Bestower of Knowledge Team Colleague

Assuming DateAdded is a Date or DateTime column in mysql.

SELECT COUNT(CigarID) AS ReviewCount FROM reviews_cigar WHERE $UserID = UserID AND $CigarID = CigarID AND WHERE DATE_SUB(CURDATE(),INTERVAL 30 DAY) <= DateAdded

This should find any rows that have been added within the last 30 days of the DateAdded column.
**You may not want to use the COUNT() like I did because it will always return 1 row even when the count is 0.**

mschroeder 251 Bestower of Knowledge Team Colleague

This is not caching. You're actually causing your script to do more work when it tries to serve from cache than when you're just generating the content dynamically.

The way caching should work, is when your script runs, it attempts to load a cache, via unique identifier (key, hash, filename, etc). When that cache request fails, because it is expired or it does not exist, then it proceeds to execute the code that will be saved into the cache, saves to the cache and displays what it generated.

This is hopefully just to give you an idea of what you might expect, if you want a more appropriate OOP solution, you'd probably want a Cache Interface that multiple cache adapters (file, db, mongo, memcache, etc) can implement so you have a consistent api. Perhaps even all tucked away behind a cache factory that handles creating the different cache instances based on a supplied adapter.

<?php

class Cache
{
	protected $_key;
	
	public function __construct( array $settings = array() )
	{
		//Do something with your settings
		//Set maximum lifetime?
		//Set directory path?
	}
	
	public function load( $key )
	{
		$this->_key = $key;
		
		if( $this->isValid( $key ) )
		{
			$cache = file_get_content('some/path/to/some/file.cache');
			return $cache
		}
		
		return false;
	}
	
	public function save( $cacheable )
	{
		//saves the generated content somewhere
		//maybe check for object and serialize automatically (setting?)
	}
	
	public function isValid( $key )
	{
		//Validate the cache exists and is not expired etc.
		//return true or false
	}
	
	public function expire( …
diafol commented: Nice +8
mschroeder 251 Bestower of Knowledge Team Colleague

If you are completely new to Git, there is a great step-by-step tutorial site that will actually walk you through some hands on exercises and teach you most of the fundamentals of using Git: http://gitimmersion.com/

qazplm114477 commented: Thanks for the link! +1
mschroeder 251 Bestower of Knowledge Team Colleague

While I don't understand your use case, and I think you're encrypting the url parameters for no value, you could do this with mod_rewrite.

However you would need some kind of indicator to tell it where to route the url params to.

e.g.
website.com/books/{encrypted} and your rewrite rules would rewrite this to website.com/books.php?enc={encrypted}

The encrypted text would be best represented by base64_encode( mcrypt_encrypt( http_build_query( $array ) ) );

Your script would then receive this string via the $_GET variable and you would need to decode it, unecrypt it, and then parse the query back into attribute value pairs.

Also if you choose this route be aware you will need to use a URI-safe base64_encode as + / and = are not uri safe.

mschroeder 251 Bestower of Knowledge Team Colleague

-phper

The problem I have with timestamps mostly has to do with the limited range they are available for, 1970 - 2038 approximately. If you were to try to store a date 30 years from today, say for a 30year mortgage, you will exhaust the 32bit integer timestamp.

Mysql's datetime and date data types do not suffer from this. It is also just as easy to do a range calculation with mysql's datetime columns.

e.g.

SELECT * FROM table WHERE table.`date` BETWEEN NOW() AND NOW() + INTERVAL 30 YEAR

Downside with that query would be the inability for mysql to cache its results because of the use of NOW(). However, if that is an issue it can be remedied by using the php DateTime class instead of the time() and date() functions, which does not suffer from the same range as the unix timestamp.

<?php
//Current DateTime
$now = new DateTime();
$start = $now->format( 'Y-m-d H:i:s' );

//add() is php 5.3.0 functionality
$now->add( new DateInterval('P30Y') );
//For php < 5.3.0
//$now->modify( '+30 year' );

$end = $now->format( 'Y-m-d H:i:s' );

$query = sprintf( 'SELECT * FROM table WHERE table.`date` BETWEEN "%s" AND "%s"', $start, $end );
echo $query; 
//SELECT * FROM table WHERE table.`date` BETWEEN "2011-02-22 20:20:52" AND "2041-02-22 20:20:52"
mschroeder 251 Bestower of Knowledge Team Colleague

Personally I prefer to store dates using the mysql date or datetime format, usually the later, but it is a personal preference.

You'll often see a unix timestamp in an int column, a mysql timestamp cplumn, and even sometimes a date stored as a string, which is the only one I would say is unacceptable and should be avoided.

Just however you choose to handle your dates, stick with it, don't mix and match date types throughout the application.

mschroeder 251 Bestower of Knowledge Team Colleague

You have basically finished the script, with the exception of two things.
You need to call the function, and your SQL statement should be looking for any delete_date values that are less than or equal to the current time. If you leave it as >= you will be deleting all articles that are set to expire in the future.

I'm not sure how your dates are stored in your database, but $current_date is unused in your function, and NOW() will only work if the delete_date column is a date/datetime/timestamp etc. (http://dev.mysql.com/doc/refman/5.0/en/datetime.html)

Also just a note, in files that are purely php, it is good practice to drop the closing ?>. This prevents any issues with whitespace after the closing tag.

<?php

function delete_expired() {
    $current_date = date("m.d.y"); 
    $sql = "DELETE FROM cms_table WHERE delete_date <= NOW()";
    $res = mysql_query($sql) or die(mysql_error());
}

delete_expired();
drewpark88 commented: Helped me a Bunch!! : ) +2
mschroeder 251 Bestower of Knowledge Team Colleague

Instead of hard deleting them would it not be easier and more effective to just limit the display of them by the "delete_date" parameter?

So when displaying posts only display posts where delete_date < NOW()?

Then you have no time priority to physically remove the items from your database and could have a database "clean-up" routine that can be run manually whenever you are logged in, or maybe runs anytime a new post is made so you don't need a cron script etc to do it?

drewpark88 commented: Awesome! +2
mschroeder 251 Bestower of Knowledge Team Colleague

You could serve up an alternative image in its place via .htaccess but you can't force a page that displays your image to redirect to your website.

mschroeder 251 Bestower of Knowledge Team Colleague

It looks like only POST values get sent to php://input.
I reworked the function so it gets it's values from the $_SERVER variable.

<?php
function getRealGet()
{
	$pairs = explode( '&', $_SERVER['QUERY_STRING'] );
	$vars = array();
	foreach ($pairs as $pair) {
		$nv = explode("=", $pair);
		$name = urldecode($nv[0]);
		$value = urldecode($nv[1]);
		$vars[$name] = $value;
	}
	return $vars;
}

var_dump( getRealGet() );
OmniX commented: nice code example +4
mschroeder 251 Bestower of Knowledge Team Colleague

http://us3.php.net/variables.external

Explains why those periods are converted to underscores.
Through the comments there are also other characters that are mentioned that appear to be converted as well.

OmniX commented: useful link, thanks. +4
mschroeder 251 Bestower of Knowledge Team Colleague

I don't think there is really a best practice for handling variables. It really depends on the scope requirements of the variables.

If you prefer to work with many individual variables than continue to use $var1, $var2, etc etc.
If you don't like having so many loose variables, you could create a single array (single or multiple dimensions) that contains all the values.

e.g.

<?php

$variable = array(
  'page' => array(
    'title' => 'Page Title',
    'width' => 960,
  ),
  'form' => array(
    'field1' => 'value',
    'field2' => 37,
    'field3' => true,
  ),
);

If you use the array you can access everything down using: echo $variable['page']['title']; You also could slug all the variables into an object if you prefer the object notation of object->variable;

$obj = new stdClass();
$obj->page = new stdClass();
$obj->page->title = 'Page Title';
$obj->page->width = 960;

Personally I don't see much value in using objects as just empty stores like that.

Beyond the way you use the variables, you have to consider persistence. $var = 4; is only available within its local scope and must be passed into functions/objects etc. This is also only persisted for the current request.

Sessions allow you to persist volatile data over multiple requests while the use maintains their session. $_SESSION['var'] = 4; => index.php => go.php => xyz.php echo $_SESSION['var']; //4 Sessions are also global and can be accessed anywhere at anytime. But if the user loses their association with the session or closes the browser …

fuston05 commented: Very helpful, and knowledgable! +2
mschroeder 251 Bestower of Knowledge Team Colleague

Session garbage collecting is specific to how php handles sessions. It is independent of the storage mechanism.

There are three in particular that control the garbage collection you can see them all here: http://php.net/manual/en/session.configuration.php:
session.gc_probability
session.gc_divisor
session.gc_maxlifetime

There are a few caveats that affect how sessions work.

  1. Garbage collection is started with (gc_probability / gc_divisor) (default 1%) so it only has a 1% chance of running.
  2. Garbage collection runs on requests so if your server has little to no traffic don't expect your sessions to get cleaned up when they should expire.
  3. The gc_maxlifetime affects session life, but, again if the server is not running the garbage collector because of low traffic it will not be expiring sessions.

Essentially if you're storing your sessions in mysql, you can just empty the session table and forcefully log out all users. You could also delete all the files wherever your sessions are being stored and get the same result.

Suzie999 commented: Helpful advice +1
mschroeder 251 Bestower of Knowledge Team Colleague

This seems like it has two parts to me. To make dealing with the session data easier, implementing a custom session handler which stores the sessions in the database would be the first step.

http://www.php.net/manual/en/function.session-set-save-handler.php
http://www.nateklaiber.com/blog/2006/05/10/custom-php-session-handler
http://devzone.zend.com/article/141

Once you have that in place, you want to associate a logged in user id, the session id, and an ip address.

So say you have the following sql structure:

CREATE TABLE IF NOT EXISTS `sessions` (
  `id` varchar(32) NOT NULL,
  `access` int(11) NOT NULL COMMENT 'timestamp',
  `data` text NOT NULL COMMENT 'serialized array',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE IF NOT EXISTS `users` (
  `Id` int(11) NOT NULL AUTO_INCREMENT,
  `Username` varchar(320) NOT NULL,
  `Password` varchar(64) NOT NULL,
  PRIMARY KEY (`Id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

CREATE TABLE IF NOT EXISTS `usersessions` (
  `UserId` int(11) NOT NULL,
  `SessionId` varchar(32) NOT NULL,
  `IpAddress` int(11) NOT NULL,
  PRIMARY KEY (`UserId`,`SessionId`,`IpAddress`),
  KEY `SessionId` (`SessionId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

ALTER TABLE `usersessions`
  ADD CONSTRAINT `usersessions_ibfk_1` FOREIGN KEY (`UserId`) REFERENCES `users` (`Id`) ON DELETE CASCADE ON UPDATE NO ACTION,
  ADD CONSTRAINT `usersessions_ibfk_2` FOREIGN KEY (`SessionId`) REFERENCES `sessions` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION;

The session handler would take care of managing the data in the sessions table.

When you log a user in, the process would just be a series of quick checks. First, does the user have any records in the usersessions table, if no, then just log the user in …

mschroeder 251 Bestower of Knowledge Team Colleague

You have a few options:

1.) You can upload the files outside of the document root which will make them unaccessible via url. But, if you offer downloads you will have to do it via a php script.

2.) You can use a .htaccess file with a FileMatch directive to disable all access to .php files.

<FilesMatch "\.(php)$">
Order allow,deny
Deny from all
</FilesMatch>

http://httpd.apache.org/docs/current/mod/core.html#filesmatch

mschroeder 251 Bestower of Knowledge Team Colleague

Well both strtolower and strtoupper are not UTF-8 compatible but I believe you already knew this.

http://www.phpwact.org/php/i18n/utf-8 is a great resource for the compatability of utf-8 with the current string functions in php.

I get the same results as you when I put my own test together using a recommended internationalization test string (Iñtërnâtiônàlizætiøn).

<?php header('Content-Type: text/html; charset=utf-8'); ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
</head>
 
<body>
<?php
//header ('Content-type: text/html; charset=utf-8');
$string = 'Iñtërnâtiônàlizætiøn';

echo strtoupper($string).PHP_EOL;
echo strtolower($string).PHP_EOL;
echo mb_strtoupper($string).PHP_EOL;
echo mb_strtolower($string).PHP_EOL;
?>
</body>
</html>

It appears that strtoupper returns the string with the ASCII characters capitalized and the utf-8 characters untouched. However strtolower seems to corrupt the string.

IñTëRNâTIôNàLIZæTIøN
i�t�rn�ti�n�liz�ti�n
IñTëRNâTIôNàLIZæTIøN
i�t�rn�ti�n�liz�ti�n